Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include <CoreFoundation/CoreFoundation.h>
6 #include <Security/Security.h>
7 #include <dlfcn.h>
9 #include "cryptox.h"
11 // We declare the necessary parts of the Security Transforms API here since
12 // we're building with the 10.6 SDK, which doesn't know about Security
13 // Transforms.
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 const CFStringRef kSecTransformInputAttributeName = CFSTR("INPUT");
18 typedef CFTypeRef SecTransformRef;
19 typedef struct OpaqueSecKeyRef* SecKeyRef;
21 typedef SecTransformRef (*SecTransformCreateReadTransformWithReadStreamFunc)
22 (CFReadStreamRef inputStream);
23 SecTransformCreateReadTransformWithReadStreamFunc
24 SecTransformCreateReadTransformWithReadStreamPtr = NULL;
25 typedef CFTypeRef (*SecTransformExecuteFunc)(SecTransformRef transform,
26 CFErrorRef* error);
27 SecTransformExecuteFunc SecTransformExecutePtr = NULL;
28 typedef SecTransformRef (*SecVerifyTransformCreateFunc)(SecKeyRef key,
29 CFDataRef signature,
30 CFErrorRef* error);
31 SecVerifyTransformCreateFunc SecVerifyTransformCreatePtr = NULL;
32 typedef Boolean (*SecTransformSetAttributeFunc)(SecTransformRef transform,
33 CFStringRef key,
34 CFTypeRef value,
35 CFErrorRef* error);
36 SecTransformSetAttributeFunc SecTransformSetAttributePtr = NULL;
37 #ifdef __cplusplus
38 }
39 #endif
41 #define MAC_OS_X_VERSION_10_7_HEX 0x00001070
43 static int sOnLionOrLater = -1;
45 static bool OnLionOrLater()
46 {
47 if (sOnLionOrLater < 0) {
48 SInt32 major = 0, minor = 0;
50 CFURLRef url =
51 CFURLCreateWithString(kCFAllocatorDefault,
52 CFSTR("file:///System/Library/CoreServices/SystemVersion.plist"),
53 NULL);
54 CFReadStreamRef stream =
55 CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
56 CFReadStreamOpen(stream);
57 CFDictionaryRef sysVersionPlist = (CFDictionaryRef)
58 CFPropertyListCreateWithStream(kCFAllocatorDefault,
59 stream, 0, kCFPropertyListImmutable,
60 NULL, NULL);
61 CFReadStreamClose(stream);
62 CFRelease(stream);
63 CFRelease(url);
65 CFStringRef versionString = (CFStringRef)
66 CFDictionaryGetValue(sysVersionPlist, CFSTR("ProductVersion"));
67 CFArrayRef versions =
68 CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault,
69 versionString, CFSTR("."));
70 CFIndex count = CFArrayGetCount(versions);
71 if (count > 0) {
72 CFStringRef component = (CFStringRef) CFArrayGetValueAtIndex(versions, 0);
73 major = CFStringGetIntValue(component);
74 if (count > 1) {
75 component = (CFStringRef) CFArrayGetValueAtIndex(versions, 1);
76 minor = CFStringGetIntValue(component);
77 }
78 }
79 CFRelease(sysVersionPlist);
80 CFRelease(versions);
82 if (major < 10) {
83 sOnLionOrLater = 0;
84 } else {
85 int version = 0x1000 + (minor << 4);
86 sOnLionOrLater = version >= MAC_OS_X_VERSION_10_7_HEX ? 1 : 0;
87 }
88 }
90 return sOnLionOrLater > 0 ? true : false;
91 }
93 static bool sCssmInitialized = false;
94 static CSSM_VERSION sCssmVersion = {2, 0};
95 static const CSSM_GUID sMozCssmGuid =
96 { 0x9243121f, 0x5820, 0x4b41,
97 { 0xa6, 0x52, 0xba, 0xb6, 0x3f, 0x9d, 0x3d, 0x7f }};
98 static CSSM_CSP_HANDLE sCspHandle = NULL;
100 void* cssmMalloc (CSSM_SIZE aSize, void* aAllocRef) {
101 (void)aAllocRef;
102 return malloc(aSize);
103 }
105 void cssmFree (void* aPtr, void* aAllocRef) {
106 (void)aAllocRef;
107 free(aPtr);
108 return;
109 }
111 void* cssmRealloc (void* aPtr, CSSM_SIZE aSize, void* aAllocRef) {
112 (void)aAllocRef;
113 return realloc(aPtr, aSize);
114 }
116 void* cssmCalloc (uint32 aNum, CSSM_SIZE aSize, void* aAllocRef) {
117 (void)aAllocRef;
118 return calloc(aNum, aSize);
119 }
121 static CSSM_API_MEMORY_FUNCS cssmMemFuncs = {
122 &cssmMalloc,
123 &cssmFree,
124 &cssmRealloc,
125 &cssmCalloc,
126 NULL
127 };
129 CryptoX_Result
130 CryptoMac_InitCryptoProvider()
131 {
132 if (!OnLionOrLater()) {
133 return CryptoX_Success;
134 }
136 if (!SecTransformCreateReadTransformWithReadStreamPtr) {
137 SecTransformCreateReadTransformWithReadStreamPtr =
138 (SecTransformCreateReadTransformWithReadStreamFunc)
139 dlsym(RTLD_DEFAULT, "SecTransformCreateReadTransformWithReadStream");
140 }
141 if (!SecTransformExecutePtr) {
142 SecTransformExecutePtr = (SecTransformExecuteFunc)
143 dlsym(RTLD_DEFAULT, "SecTransformExecute");
144 }
145 if (!SecVerifyTransformCreatePtr) {
146 SecVerifyTransformCreatePtr = (SecVerifyTransformCreateFunc)
147 dlsym(RTLD_DEFAULT, "SecVerifyTransformCreate");
148 }
149 if (!SecTransformSetAttributePtr) {
150 SecTransformSetAttributePtr = (SecTransformSetAttributeFunc)
151 dlsym(RTLD_DEFAULT, "SecTransformSetAttribute");
152 }
153 if (!SecTransformCreateReadTransformWithReadStreamPtr ||
154 !SecTransformExecutePtr ||
155 !SecVerifyTransformCreatePtr ||
156 !SecTransformSetAttributePtr) {
157 return CryptoX_Error;
158 }
159 return CryptoX_Success;
160 }
162 CryptoX_Result
163 CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData)
164 {
165 if (!aInputData) {
166 return CryptoX_Error;
167 }
169 void* inputData = CFDataCreateMutable(kCFAllocatorDefault, 0);
170 if (!inputData) {
171 return CryptoX_Error;
172 }
174 if (!OnLionOrLater()) {
175 CSSM_DATA_PTR cssmData = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
176 if (!cssmData) {
177 CFRelease(inputData);
178 return CryptoX_Error;
179 }
180 cssmData->Data = (uint8*)inputData;
181 cssmData->Length = 0;
182 *aInputData = cssmData;
183 return CryptoX_Success;
184 }
186 *aInputData = inputData;
187 return CryptoX_Success;
188 }
190 CryptoX_Result
191 CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData, void* aBuf,
192 unsigned int aLen)
193 {
194 if (aLen == 0) {
195 return CryptoX_Success;
196 }
197 if (!aInputData || !*aInputData) {
198 return CryptoX_Error;
199 }
201 CFMutableDataRef inputData;
202 if (!OnLionOrLater()) {
203 inputData = (CFMutableDataRef)((CSSM_DATA_PTR)*aInputData)->Data;
204 ((CSSM_DATA_PTR)*aInputData)->Length += aLen;
205 } else {
206 inputData = (CFMutableDataRef)*aInputData;
207 }
209 CFDataAppendBytes(inputData, (const uint8*)aBuf, aLen);
210 return CryptoX_Success;
211 }
213 CryptoX_Result
214 CryptoMac_LoadPublicKey(const unsigned char* aCertData,
215 CryptoX_PublicKey* aPublicKey)
216 {
217 if (!aCertData || !aPublicKey) {
218 return CryptoX_Error;
219 }
220 *aPublicKey = NULL;
222 if (!OnLionOrLater()) {
223 if (!sCspHandle) {
224 CSSM_RETURN rv;
225 if (!sCssmInitialized) {
226 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
227 rv = CSSM_Init(&sCssmVersion,
228 CSSM_PRIVILEGE_SCOPE_PROCESS,
229 &sMozCssmGuid,
230 CSSM_KEY_HIERARCHY_NONE,
231 &pvcPolicy,
232 NULL);
233 if (rv != CSSM_OK) {
234 return CryptoX_Error;
235 }
236 sCssmInitialized = true;
237 }
239 rv = CSSM_ModuleLoad(&gGuidAppleCSP,
240 CSSM_KEY_HIERARCHY_NONE,
241 NULL,
242 NULL);
243 if (rv != CSSM_OK) {
244 return CryptoX_Error;
245 }
247 CSSM_CSP_HANDLE cspHandle;
248 rv = CSSM_ModuleAttach(&gGuidAppleCSP,
249 &sCssmVersion,
250 &cssmMemFuncs,
251 0,
252 CSSM_SERVICE_CSP,
253 0,
254 CSSM_KEY_HIERARCHY_NONE,
255 NULL,
256 0,
257 NULL,
258 &cspHandle);
259 if (rv != CSSM_OK) {
260 return CryptoX_Error;
261 }
262 sCspHandle = cspHandle;
263 }
265 FILE* certFile = NULL;
266 long certFileSize = 0;
267 uint8* certBuffer = NULL;
269 certFile = fopen((char*)aCertData, "rb");
270 if (!certFile) {
271 return CryptoX_Error;
272 }
273 if (fseek(certFile, 0, SEEK_END)) {
274 fclose(certFile);
275 return CryptoX_Error;
276 }
277 certFileSize = ftell(certFile);
278 if (certFileSize < 0) {
279 fclose(certFile);
280 return CryptoX_Error;
281 }
282 certBuffer = (uint8*)malloc(certFileSize);
283 if (fseek(certFile, 0, SEEK_SET)) {
284 free(certBuffer);
285 fclose(certFile);
286 return CryptoX_Error;
287 }
288 uint readResult = fread(certBuffer, sizeof(uint8), certFileSize, certFile);
289 if (readResult != certFileSize) {
290 free(certBuffer);
291 fclose(certFile);
292 return CryptoX_Error;
293 }
294 fclose(certFile);
296 CFDataRef certData = CFDataCreate(kCFAllocatorDefault,
297 certBuffer,
298 certFileSize);
299 free(certBuffer);
300 if (!certData) {
301 return CryptoX_Error;
302 }
304 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault,
305 certData);
306 CFRelease(certData);
307 if (!cert) {
308 return CryptoX_Error;
309 }
311 SecKeyRef publicKey;
312 OSStatus status = SecCertificateCopyPublicKey(cert, (SecKeyRef*)&publicKey);
313 CFRelease(cert);
314 if (status) {
315 return CryptoX_Error;
316 }
318 *aPublicKey = (void*)publicKey;
319 return CryptoX_Success;
320 }
322 CFURLRef url =
323 CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
324 aCertData,
325 strlen((char*)aCertData),
326 false);
327 if (!url) {
328 return CryptoX_Error;
329 }
331 CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
332 if (!stream) {
333 CFRelease(url);
334 return CryptoX_Error;
335 }
337 SecTransformRef readTransform =
338 SecTransformCreateReadTransformWithReadStreamPtr(stream);
339 if (!readTransform) {
340 CFRelease(url);
341 CFRelease(stream);
342 return CryptoX_Error;
343 }
345 CFErrorRef error;
346 CFDataRef tempCertData = (CFDataRef)SecTransformExecutePtr(readTransform,
347 &error);
348 if (!tempCertData || error) {
349 CFRelease(url);
350 CFRelease(stream);
351 CFRelease(readTransform);
352 return CryptoX_Error;
353 }
355 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault,
356 tempCertData);
357 if (!cert) {
358 CFRelease(url);
359 CFRelease(stream);
360 CFRelease(readTransform);
361 CFRelease(tempCertData);
362 return CryptoX_Error;
363 }
365 CryptoX_Result result = CryptoX_Error;
366 OSStatus status = SecCertificateCopyPublicKey(cert,
367 (SecKeyRef*)aPublicKey);
368 if (status == 0) {
369 result = CryptoX_Success;
370 }
372 CFRelease(url);
373 CFRelease(stream);
374 CFRelease(readTransform);
375 CFRelease(tempCertData);
376 CFRelease(cert);
378 return result;
379 }
381 CryptoX_Result
382 CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
383 CryptoX_PublicKey* aPublicKey,
384 const unsigned char* aSignature,
385 unsigned int aSignatureLen)
386 {
387 if (!aInputData || !*aInputData || !aPublicKey || !*aPublicKey ||
388 !aSignature || aSignatureLen == 0) {
389 return CryptoX_Error;
390 }
392 if (!OnLionOrLater()) {
393 if (!sCspHandle) {
394 return CryptoX_Error;
395 }
397 CSSM_KEY* publicKey;
398 OSStatus status = SecKeyGetCSSMKey((SecKeyRef)*aPublicKey,
399 (const CSSM_KEY**)&publicKey);
400 if (status) {
401 return CryptoX_Error;
402 }
404 CSSM_CC_HANDLE ccHandle;
405 if (CSSM_CSP_CreateSignatureContext(sCspHandle,
406 CSSM_ALGID_SHA1WithRSA,
407 NULL,
408 publicKey,
409 &ccHandle) != CSSM_OK) {
410 return CryptoX_Error;
411 }
413 CryptoX_Result result = CryptoX_Error;
414 CSSM_DATA signatureData;
415 signatureData.Data = (uint8*)aSignature;
416 signatureData.Length = aSignatureLen;
417 CSSM_DATA inputData;
418 inputData.Data =
419 CFDataGetMutableBytePtr((CFMutableDataRef)
420 (((CSSM_DATA_PTR)*aInputData)->Data));
421 inputData.Length = ((CSSM_DATA_PTR)*aInputData)->Length;
422 if (CSSM_VerifyData(ccHandle,
423 &inputData,
424 1,
425 CSSM_ALGID_NONE,
426 &signatureData) == CSSM_OK) {
427 result = CryptoX_Success;
428 }
429 return result;
430 }
432 CFDataRef signatureData = CFDataCreate(kCFAllocatorDefault,
433 aSignature, aSignatureLen);
434 if (!signatureData) {
435 return CryptoX_Error;
436 }
438 CFErrorRef error;
439 SecTransformRef verifier =
440 SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey,
441 signatureData,
442 &error);
443 if (!verifier || error) {
444 CFRelease(signatureData);
445 return CryptoX_Error;
446 }
448 SecTransformSetAttributePtr(verifier,
449 kSecTransformInputAttributeName,
450 (CFDataRef)*aInputData,
451 &error);
452 if (error) {
453 CFRelease(signatureData);
454 CFRelease(verifier);
455 return CryptoX_Error;
456 }
458 CryptoX_Result result = CryptoX_Error;
459 CFTypeRef rv = SecTransformExecutePtr(verifier, &error);
460 if (error) {
461 CFRelease(signatureData);
462 CFRelease(verifier);
463 return CryptoX_Error;
464 }
466 if (CFGetTypeID(rv) == CFBooleanGetTypeID() &&
467 CFBooleanGetValue((CFBooleanRef)rv) == true) {
468 result = CryptoX_Success;
469 }
471 CFRelease(signatureData);
472 CFRelease(verifier);
474 return result;
475 }
477 void
478 CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData)
479 {
480 if (!aInputData || !*aInputData) {
481 return;
482 }
484 CFMutableDataRef inputData = NULL;
485 if (OnLionOrLater()) {
486 inputData = (CFMutableDataRef)*aInputData;
487 } else {
488 inputData = (CFMutableDataRef)((CSSM_DATA_PTR)*aInputData)->Data;
489 }
491 CFRelease(inputData);
492 if (!OnLionOrLater()) {
493 free((CSSM_DATA_PTR)*aInputData);
494 }
495 }
497 void
498 CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey)
499 {
500 if (!aPublicKey || !*aPublicKey) {
501 return;
502 }
503 if (!OnLionOrLater() && sCspHandle) {
504 CSSM_ModuleDetach(sCspHandle);
505 sCspHandle = NULL;
506 }
507 CFRelease((SecKeyRef)*aPublicKey);
508 }