modules/libmar/verify/MacVerifyCrypto.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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.

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

mercurial