MacVerifyCrypto.cpp (6854B)
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/. */ 4 5 #include <CoreFoundation/CoreFoundation.h> 6 #include <Security/Security.h> 7 #include <dlfcn.h> 8 9 #include "cryptox.h" 10 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 #if defined(__cplusplus) 15 extern "C" { 16 #endif 17 const CFStringRef kSecTransformInputAttributeName = CFSTR("INPUT"); 18 typedef CFTypeRef SecTransformRef; 19 typedef OpaqueSecKeyRef* SecKeyRef; 20 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 #if defined(__cplusplus) 38 } 39 #endif 40 41 CryptoX_Result CryptoMac_InitCryptoProvider() { 42 if (!SecTransformCreateReadTransformWithReadStreamPtr) { 43 SecTransformCreateReadTransformWithReadStreamPtr = 44 (SecTransformCreateReadTransformWithReadStreamFunc)dlsym( 45 RTLD_DEFAULT, "SecTransformCreateReadTransformWithReadStream"); 46 } 47 if (!SecTransformExecutePtr) { 48 SecTransformExecutePtr = 49 (SecTransformExecuteFunc)dlsym(RTLD_DEFAULT, "SecTransformExecute"); 50 } 51 if (!SecVerifyTransformCreatePtr) { 52 SecVerifyTransformCreatePtr = (SecVerifyTransformCreateFunc)dlsym( 53 RTLD_DEFAULT, "SecVerifyTransformCreate"); 54 } 55 if (!SecTransformSetAttributePtr) { 56 SecTransformSetAttributePtr = (SecTransformSetAttributeFunc)dlsym( 57 RTLD_DEFAULT, "SecTransformSetAttribute"); 58 } 59 if (!SecTransformCreateReadTransformWithReadStreamPtr || 60 !SecTransformExecutePtr || !SecVerifyTransformCreatePtr || 61 !SecTransformSetAttributePtr) { 62 return CryptoX_Error; 63 } 64 return CryptoX_Success; 65 } 66 67 CryptoX_Result CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData) { 68 if (!aInputData) { 69 return CryptoX_Error; 70 } 71 72 void* inputData = CFDataCreateMutable(kCFAllocatorDefault, 0); 73 if (!inputData) { 74 return CryptoX_Error; 75 } 76 77 *aInputData = inputData; 78 return CryptoX_Success; 79 } 80 81 CryptoX_Result CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData, 82 void* aBuf, unsigned int aLen) { 83 if (aLen == 0) { 84 return CryptoX_Success; 85 } 86 if (!aInputData || !*aInputData) { 87 return CryptoX_Error; 88 } 89 90 CFMutableDataRef inputData = (CFMutableDataRef)*aInputData; 91 92 CFDataAppendBytes(inputData, (const uint8*)aBuf, aLen); 93 return CryptoX_Success; 94 } 95 96 CryptoX_Result CryptoMac_LoadPublicKey(const unsigned char* aCertData, 97 unsigned int aDataSize, 98 CryptoX_PublicKey* aPublicKey) { 99 if (!aCertData || aDataSize == 0 || !aPublicKey) { 100 return CryptoX_Error; 101 } 102 *aPublicKey = NULL; 103 CFDataRef certData = CFDataCreate(kCFAllocatorDefault, aCertData, aDataSize); 104 if (!certData) { 105 return CryptoX_Error; 106 } 107 108 SecCertificateRef cert = 109 SecCertificateCreateWithData(kCFAllocatorDefault, certData); 110 CFRelease(certData); 111 if (!cert) { 112 return CryptoX_Error; 113 } 114 115 OSStatus status = SecCertificateCopyPublicKey(cert, (SecKeyRef*)aPublicKey); 116 CFRelease(cert); 117 if (status != 0) { 118 return CryptoX_Error; 119 } 120 121 return CryptoX_Success; 122 } 123 124 CryptoX_Result CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData, 125 CryptoX_PublicKey* aPublicKey, 126 const unsigned char* aSignature, 127 unsigned int aSignatureLen) { 128 if (!aInputData || !*aInputData || !aPublicKey || !*aPublicKey || 129 !aSignature || aSignatureLen == 0) { 130 return CryptoX_Error; 131 } 132 133 CFDataRef signatureData = 134 CFDataCreate(kCFAllocatorDefault, aSignature, aSignatureLen); 135 if (!signatureData) { 136 return CryptoX_Error; 137 } 138 139 CFErrorRef error; 140 SecTransformRef verifier = SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey, 141 signatureData, &error); 142 if (!verifier || error) { 143 if (error) { 144 CFRelease(error); 145 } 146 CFRelease(signatureData); 147 return CryptoX_Error; 148 } 149 150 SecTransformSetAttributePtr(verifier, kSecDigestTypeAttribute, kSecDigestSHA2, 151 &error); 152 if (error) { 153 CFRelease(error); 154 CFRelease(signatureData); 155 CFRelease(verifier); 156 return CryptoX_Error; 157 } 158 159 int digestLength = 384; 160 CFNumberRef dLen = 161 CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &digestLength); 162 SecTransformSetAttributePtr(verifier, kSecDigestLengthAttribute, dLen, 163 &error); 164 CFRelease(dLen); 165 if (error) { 166 CFRelease(error); 167 CFRelease(signatureData); 168 CFRelease(verifier); 169 return CryptoX_Error; 170 } 171 172 SecTransformSetAttributePtr(verifier, kSecTransformInputAttributeName, 173 (CFDataRef)*aInputData, &error); 174 if (error) { 175 CFRelease(error); 176 CFRelease(signatureData); 177 CFRelease(verifier); 178 return CryptoX_Error; 179 } 180 181 CryptoX_Result result = CryptoX_Error; 182 CFTypeRef rv = SecTransformExecutePtr(verifier, &error); 183 if (error) { 184 CFRelease(error); 185 CFRelease(signatureData); 186 CFRelease(verifier); 187 return CryptoX_Error; 188 } 189 190 if (CFGetTypeID(rv) == CFBooleanGetTypeID() && 191 CFBooleanGetValue((CFBooleanRef)rv) == true) { 192 result = CryptoX_Success; 193 } 194 195 CFRelease(signatureData); 196 CFRelease(verifier); 197 198 return result; 199 } 200 201 void CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData) { 202 if (!aInputData || !*aInputData) { 203 return; 204 } 205 206 CFMutableDataRef inputData = NULL; 207 inputData = (CFMutableDataRef)*aInputData; 208 209 CFRelease(inputData); 210 } 211 212 void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey) { 213 if (!aPublicKey || !*aPublicKey) { 214 return; 215 } 216 217 CFRelease((SecKeyRef)*aPublicKey); 218 }