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.

     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 }

mercurial