X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/fa7225c82381bac4432a6edf16f53b5370238d85..dd5fb164cf5b32c462296bc65e289e100f74b59a:/OSX/libsecurity_keychain/lib/SecKey.cpp diff --git a/OSX/libsecurity_keychain/lib/SecKey.cpp b/OSX/libsecurity_keychain/lib/SecKey.cpp index a80fe3be..229ee8bb 100644 --- a/OSX/libsecurity_keychain/lib/SecKey.cpp +++ b/OSX/libsecurity_keychain/lib/SecKey.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "SecBridge.h" @@ -54,6 +55,7 @@ static OSStatus SecCDSAKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { key->key = const_cast(reinterpret_cast(keyData)); key->key->initializeWithSecKeyRef(key); + key->credentialType = kSecCredentialTypeDefault; return errSecSuccess; } @@ -161,7 +163,7 @@ SecCDSAKeyGetAlgorithmId(SecKeyRef key) { static CFDataRef SecCDSAKeyCopyPublicKeyDataFromSubjectInfo(CFDataRef pubKeyInfo) { // First of all, consider x509 format and try to strip SubjPubKey envelope. If it fails, do not panic // and export data as is. - DERItem keyItem = { (DERByte *)CFDataGetBytePtr(pubKeyInfo), CFDataGetLength(pubKeyInfo) }, pubKeyItem; + DERItem keyItem = { (DERByte *)CFDataGetBytePtr(pubKeyInfo), int_cast(CFDataGetLength(pubKeyInfo)) }, pubKeyItem; DERByte numUnused; DERSubjPubKeyInfo subjPubKey; if (DERParseSequence(&keyItem, DERNumSubjPubKeyInfoItemSpecs, @@ -176,7 +178,7 @@ static CFDataRef SecCDSAKeyCopyPublicKeyDataFromSubjectInfo(CFDataRef pubKeyInfo static CFDataRef SecCDSAKeyCopyPublicKeyDataWithSubjectInfo(CSSM_ALGORITHMS algorithm, uint32 keySizeInBits, CFDataRef pubKeyInfo) { // First check, whether X509 pubkeyinfo is already present. If not, add it according to the key type. - DERItem keyItem = { (DERByte *)CFDataGetBytePtr(pubKeyInfo), CFDataGetLength(pubKeyInfo) }; + DERItem keyItem = { (DERByte *)CFDataGetBytePtr(pubKeyInfo), int_cast(CFDataGetLength(pubKeyInfo)) }; DERSubjPubKeyInfo subjPubKey; if (DERParseSequence(&keyItem, DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, @@ -214,10 +216,10 @@ static CFDataRef SecCDSAKeyCopyPublicKeyDataWithSubjectInfo(CSSM_ALGORITHMS algo subjPubKey.algId.length = sizeof(oidECsecp256); } else if (keySizeInBits == 384) { subjPubKey.algId.data = const_cast(oidECsecp384); - subjPubKey.algId.length = sizeof(oidECsecp256); + subjPubKey.algId.length = sizeof(oidECsecp384); } if (keySizeInBits == 521) { subjPubKey.algId.data = const_cast(oidECsecp521); - subjPubKey.algId.length = sizeof(oidECsecp256); + subjPubKey.algId.length = sizeof(oidECsecp521); } } DERSize size = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, &subjPubKey, @@ -248,7 +250,7 @@ static OSStatus SecCDSAKeyCopyPublicBytes(SecKeyRef key, CFDataRef *serializatio CFRef privKeyData; result = SecItemExport(key, kSecFormatOpenSSL, 0, NULL, privKeyData.take()); if (result == errSecSuccess) { - DERItem keyItem = { (DERByte *)CFDataGetBytePtr(privKeyData), CFDataGetLength(privKeyData) }; + DERItem keyItem = { (DERByte *)CFDataGetBytePtr(privKeyData), int_cast(CFDataGetLength(privKeyData)) }; DERRSAKeyPair keyPair; if (DERParseSequence(&keyItem, DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs, &keyPair, sizeof(keyPair)) == DR_Success) { @@ -346,7 +348,7 @@ SecCDSAKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) { MacOSError::check(SecItemExport(key, kSecFormatOpenSSL, 0, NULL, keyData.take())); if (header.keyClass() == CSSM_KEYCLASS_PRIVATE_KEY) { // Convert DER format into x9.63 format, which is expected for exported key. - DERItem keyItem = { (DERByte *)CFDataGetBytePtr(keyData), CFDataGetLength(keyData) }; + DERItem keyItem = { (DERByte *)CFDataGetBytePtr(keyData), int_cast(CFDataGetLength(keyData)) }; DERECPrivateKey privateKey; DERECPrivateKeyPublicKey privateKeyPublicKey; DERByte numUnused; @@ -516,17 +518,19 @@ static SecKeyRef SecCDSAKeyCopyPublicKey(SecKeyRef privateKey) { Item publicKey = key->keychain()->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, uniqueId); result = reinterpret_cast(publicKey->handle()); } - } else if (key->publicKey()) { - KeyItem *publicKey = new KeyItem(key->publicKey()); + } + + if (result == NULL && key->publicKey()) { + SecPointer publicKey(new KeyItem(key->publicKey())); result = reinterpret_cast(publicKey->handle()); } END_SECKEYAPI } -static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm, +static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType &operation, SecKeyAlgorithm algorithm, CSSM_ALGORITHMS &baseAlgorithm, CSSM_ALGORITHMS &secondaryAlgorithm, - CSSM_ALGORITHMS &paddingAlgorithm) { + CSSM_ALGORITHMS &paddingAlgorithm, CFIndex &inputSizeLimit) { KeyItem *keyItem = key->key; CSSM_KEYCLASS keyClass = keyItem->key()->header().keyClass(); baseAlgorithm = keyItem->key()->header().algorithm(); @@ -537,27 +541,35 @@ static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType o if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureRaw)) { secondaryAlgorithm = CSSM_ALGID_NONE; paddingAlgorithm = CSSM_PADDING_NONE; + inputSizeLimit = 0; } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw)) { secondaryAlgorithm = CSSM_ALGID_NONE; paddingAlgorithm = CSSM_PADDING_PKCS1; + inputSizeLimit = -11; } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1)) { secondaryAlgorithm = CSSM_ALGID_SHA1; paddingAlgorithm = CSSM_PADDING_PKCS1; + inputSizeLimit = 20; } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224)) { secondaryAlgorithm = CSSM_ALGID_SHA224; paddingAlgorithm = CSSM_PADDING_PKCS1; + inputSizeLimit = 224 / 8; } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256)) { secondaryAlgorithm = CSSM_ALGID_SHA256; paddingAlgorithm = CSSM_PADDING_PKCS1; + inputSizeLimit = 256 / 8; } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384)) { secondaryAlgorithm = CSSM_ALGID_SHA384; paddingAlgorithm = CSSM_PADDING_PKCS1; + inputSizeLimit = 384 / 8; } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512)) { secondaryAlgorithm = CSSM_ALGID_SHA512; paddingAlgorithm = CSSM_PADDING_PKCS1; + inputSizeLimit = 512 / 8; } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5)) { secondaryAlgorithm = CSSM_ALGID_MD5; paddingAlgorithm = CSSM_PADDING_PKCS1; + inputSizeLimit = 16; } else { return NULL; } @@ -566,12 +578,22 @@ static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType o if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRaw)) { secondaryAlgorithm = CSSM_ALGID_NONE; paddingAlgorithm = CSSM_PADDING_NONE; + inputSizeLimit = 0; } else if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionPKCS1)) { secondaryAlgorithm = CSSM_ALGID_NONE; paddingAlgorithm = CSSM_PADDING_PKCS1; + inputSizeLimit = operation == kSecKeyOperationTypeEncrypt ? -11 : 0; } else { return NULL; } + } else if (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeDecrypt && + CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRaw)) { + // Raw RSA decryption is identical to raw RSA encryption, so lets use encryption instead of decryption, + // because CDSA keys refuses to perform decrypt using public key. + operation = kSecKeyOperationTypeEncrypt; + secondaryAlgorithm = CSSM_ALGID_NONE; + paddingAlgorithm = CSSM_PADDING_NONE; + inputSizeLimit = 0; } else { return NULL; } @@ -629,21 +651,29 @@ static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationTyp CFArrayRef allAlgorithms, SecKeyOperationMode mode, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { BEGIN_SECKEYAPI(CFTypeRef, kCFNull) + CFIndex inputSizeLimit = 0; CSSM_ALGORITHMS baseAlgorithm, secondaryAlgorithm, paddingAlgorithm; - KeyItem *keyItem = SecCDSAKeyPrepareParameters(key, operation, algorithm, baseAlgorithm, secondaryAlgorithm, paddingAlgorithm); + KeyItem *keyItem = SecCDSAKeyPrepareParameters(key, operation, algorithm, baseAlgorithm, secondaryAlgorithm, paddingAlgorithm, inputSizeLimit); if (keyItem == NULL) { // Operation/algorithm/key combination is not supported. return kCFNull; } else if (mode == kSecKeyOperationModeCheckIfSupported) { // Operation is supported and caller wants to just know that. return kCFBooleanTrue; + } else if (baseAlgorithm == CSSM_ALGID_RSA) { + if (inputSizeLimit <= 0) { + inputSizeLimit += SecCDSAKeyGetBlockSize(key); + } + if (CFDataGetLength((CFDataRef)in1) > inputSizeLimit) { + MacOSError::throwMe(errSecParam); + } } switch (operation) { case kSecKeyOperationTypeSign: { CssmClient::Sign signContext(keyItem->csp(), baseAlgorithm, secondaryAlgorithm); signContext.key(keyItem->key()); - signContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault)); + signContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN, key->credentialType)); signContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm); CFRef input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef::check(in1, errSecParam), algorithm); CssmAutoData signature(signContext.allocator()); @@ -654,7 +684,7 @@ static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationTyp case kSecKeyOperationTypeVerify: { CssmClient::Verify verifyContext(keyItem->csp(), baseAlgorithm, secondaryAlgorithm); verifyContext.key(keyItem->key()); - verifyContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ANY, kSecCredentialTypeDefault)); + verifyContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ANY, key->credentialType)); verifyContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm); CFRef input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef::check(in1, errSecParam), algorithm); verifyContext.verify(CssmData(CFDataRef(input)), CssmData(CFRef::check(in2, errSecParam))); @@ -665,7 +695,7 @@ static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationTyp CssmClient::Encrypt encryptContext(keyItem->csp(), baseAlgorithm); encryptContext.key(keyItem->key()); encryptContext.padding(paddingAlgorithm); - encryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT, kSecCredentialTypeDefault)); + encryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT, key->credentialType)); CFRef input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef::check(in1, errSecParam), algorithm); CssmAutoData output(encryptContext.allocator()), remainingData(encryptContext.allocator()); size_t length = encryptContext.encrypt(CssmData(CFDataRef(input)), output.get(), remainingData.get()); @@ -679,7 +709,7 @@ static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationTyp CssmClient::Decrypt decryptContext(keyItem->csp(), baseAlgorithm); decryptContext.key(keyItem->key()); decryptContext.padding(paddingAlgorithm); - decryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeDefault)); + decryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT, key->credentialType)); CssmAutoData output(decryptContext.allocator()), remainingData(decryptContext.allocator()); size_t length = decryptContext.decrypt(CssmData(CFRef::check(in1, errSecParam)), output.get(), remainingData.get()); @@ -730,7 +760,7 @@ static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationTyp END_SECKEYAPI } -static Boolean SecCDSAIsEqual(SecKeyRef key1, SecKeyRef key2) { +static Boolean SecCDSAKeyIsEqual(SecKeyRef key1, SecKeyRef key2) { CFErrorRef *error; BEGIN_SECKEYAPI(Boolean, false) @@ -739,6 +769,19 @@ static Boolean SecCDSAIsEqual(SecKeyRef key1, SecKeyRef key2) { END_SECKEYAPI } +static Boolean SecCDSAKeySetParameter(SecKeyRef key, CFStringRef name, CFPropertyListRef value, CFErrorRef *error) { + BEGIN_SECKEYAPI(Boolean, false) + + if (CFEqual(name, kSecUseAuthenticationUI)) { + key->credentialType = CFEqual(value, kSecUseAuthenticationUIAllow) ? kSecCredentialTypeDefault : kSecCredentialTypeNoUI; + result = true; + } else { + result = SecError(errSecUnimplemented, error, CFSTR("Unsupported parameter '%@' for SecKeyCDSASetParameter"), name); + } + + END_SECKEYAPI +} + const SecKeyDescriptor kSecCDSAKeyDescriptor = { .version = kSecKeyDescriptorVersion, .name = "CDSAKey", @@ -752,7 +795,8 @@ const SecKeyDescriptor kSecCDSAKeyDescriptor = { .copyExternalRepresentation = SecCDSAKeyCopyExternalRepresentation, .copyPublicKey = SecCDSAKeyCopyPublicKey, .copyOperationResult = SecCDSAKeyCopyOperationResult, - .isEqual = SecCDSAIsEqual, + .isEqual = SecCDSAKeyIsEqual, + .setParameter = SecCDSAKeySetParameter, }; namespace Security { @@ -814,13 +858,10 @@ static OSStatus SecKeyCreatePairInternal( SecPointer pubItem, privItem; if (((publicKeyAttr | privateKeyAttr) & CSSM_KEYATTR_PERMANENT) != 0) { keychain = Keychain::optional(keychainRef); - StLock _(*keychain->getKeychainMutex()); - KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr, - privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem); - } else { - KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr, - privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem); } + StMaybeLock _(keychain ? keychain->getKeychainMutex() : NULL); + KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr, + privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem); // Return the generated keys. if (publicKeyRef) @@ -868,13 +909,24 @@ SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY **cssmKey) // Private APIs // +static ModuleNexus gSecReturnedKeyCSPsMutex; +static std::set gSecReturnedKeyCSPs; + OSStatus SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle) { BEGIN_SECAPI SecPointer keyItem(KeyItem::required(keyRef)); - Required(cspHandle) = keyItem->csp()->handle(); + + // Once we vend this handle, we can no longer delete this CSP object via RAII (and thus call CSSM_ModuleDetach on the CSP). + // Keep a global pointer to it to force the CSP to stay live forever. + CssmClient::CSP returnedKeyCSP = keyItem->csp(); + { + StLock _(gSecReturnedKeyCSPsMutex()); + gSecReturnedKeyCSPs.insert(returnedKeyCSP); + } + Required(cspHandle) = returnedKeyCSP->handle(); END_SECAPI } @@ -1040,13 +1092,19 @@ static u_int32_t ConvertCFStringToInteger(CFStringRef ref) // figure out the size of the string CFIndex numChars = CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref), kCFStringEncodingUTF8); - char buffer[numChars]; + char *buffer = (char *)malloc(numChars); + if (NULL == buffer) { + UnixError::throwMe(ENOMEM); + } if (!CFStringGetCString(ref, buffer, numChars, kCFStringEncodingUTF8)) { + free(buffer); MacOSError::throwMe(errSecParam); } - return atoi(buffer); + u_int32_t result = atoi(buffer); + free(buffer); + return result; } @@ -1403,6 +1461,7 @@ static OSStatus SetKeyLabelAndTag(SecKeyRef keyRef, CFTypeRef label, CFDataRef t SecKeychainAttribute attributes[numToModify]; int i = 0; + void *data = NULL; if (label != NULL) { @@ -1412,11 +1471,12 @@ static OSStatus SetKeyLabelAndTag(SecKeyRef keyRef, CFTypeRef label, CFDataRef t attributes[i].data = (void*) CFStringGetCStringPtr(label_string, kCFStringEncodingUTF8); if (NULL == attributes[i].data) { CFIndex buffer_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(label_string), kCFStringEncodingUTF8); - attributes[i].data = alloca((size_t)buffer_length); + data = attributes[i].data = malloc((size_t)buffer_length); if (NULL == attributes[i].data) { UnixError::throwMe(ENOMEM); } if (!CFStringGetCString(label_string, static_cast(attributes[i].data), buffer_length, kCFStringEncodingUTF8)) { + free(data); MacOSError::throwMe(errSecParam); } } @@ -1443,8 +1503,14 @@ static OSStatus SetKeyLabelAndTag(SecKeyRef keyRef, CFTypeRef label, CFDataRef t attrList.count = numToModify; attrList.attr = attributes; - - return SecKeychainItemModifyAttributesAndData((SecKeychainItemRef) keyRef, &attrList, 0, NULL); + + OSStatus result = SecKeychainItemModifyAttributesAndData((SecKeychainItemRef) keyRef, &attrList, 0, NULL); + if (data) + { + free(data); + } + + return result; } @@ -1787,18 +1853,18 @@ SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error) } else { // we can set the label attributes on the generated key if it's a keychain item - size_t labelBufLen = (label) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label), kCFStringEncodingUTF8) + 1 : 0; + size_t labelBufLen = (label) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label), kCFStringEncodingUTF8) + 1 : 1; char *labelBuf = (char *)malloc(labelBufLen); - size_t appLabelBufLen = (appLabel) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel), kCFStringEncodingUTF8) + 1 : 0; + size_t appLabelBufLen = (appLabel) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel), kCFStringEncodingUTF8) + 1 : 1; char *appLabelBuf = (char *)malloc(appLabelBufLen); - size_t appTagBufLen = (appTag) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag), kCFStringEncodingUTF8) + 1 : 0; + size_t appTagBufLen = (appTag) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag), kCFStringEncodingUTF8) + 1 : 1; char *appTagBuf = (char *)malloc(appTagBufLen); - if (label && !CFStringGetCString(label, labelBuf, labelBufLen-1, kCFStringEncodingUTF8)) + if (!label || !CFStringGetCString(label, labelBuf, labelBufLen-1, kCFStringEncodingUTF8)) labelBuf[0]=0; - if (appLabel && !CFStringGetCString(appLabel, appLabelBuf, appLabelBufLen-1, kCFStringEncodingUTF8)) + if (!appLabel || !CFStringGetCString(appLabel, appLabelBuf, appLabelBufLen-1, kCFStringEncodingUTF8)) appLabelBuf[0]=0; - if (appTag && !CFStringGetCString(appTag, appTagBuf, appTagBufLen-1, kCFStringEncodingUTF8)) + if (!appTag || !CFStringGetCString(appTag, appTagBuf, appTagBufLen-1, kCFStringEncodingUTF8)) appTagBuf[0]=0; SecKeychainAttribute attrs[] = { @@ -1882,6 +1948,7 @@ SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef * CFRelease(ka); return sk; } else { + CFRelease(ka); if (error) { *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, crtn ? crtn : CSSM_ERRCODE_INTERNAL_ERROR, NULL); } @@ -1943,7 +2010,9 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr /* Pick Values from parameters */ if((saltDictValue = (CFDataRef) CFDictionaryGetValue(parameters, kSecAttrSalt)) == NULL) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecMissingAlgorithmParms, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecMissingAlgorithmParms, NULL); + } goto errOut; } @@ -1959,7 +2028,9 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr saltLen = CFDataGetLength(saltDictValue); if((salt = (uint8_t *) malloc(saltLen)) == NULL) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); + } goto errOut; } @@ -1967,13 +2038,17 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr passwordLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(password), kCFStringEncodingUTF8) + 1; if((thePassword = (char *) malloc(passwordLen)) == NULL) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); + } goto errOut; } CFStringGetBytes(password, CFRangeMake(0, CFStringGetLength(password)), kCFStringEncodingUTF8, '?', FALSE, (UInt8*)thePassword, passwordLen, &passwordLen); if((derivedKey = (uint8_t *) malloc(derivedKeyLen)) == NULL) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); + } goto errOut; } @@ -1990,7 +2065,9 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA512)) { algorithm = kCCPRFHmacAlgSHA512; } else { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidAlgorithmParms, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidAlgorithmParms, NULL); + } goto errOut; } @@ -1999,7 +2076,9 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr } if(CCKeyDerivationPBKDF(kCCPBKDF2, thePassword, passwordLen, salt, saltLen, algorithm, rounds, derivedKey, derivedKeyLen)) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL); + } goto errOut; } @@ -2007,7 +2086,9 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr retval = SecKeyCreateFromData(parameters, keyData, error); CFRelease(keyData); } else { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL); + } } errOut: @@ -2020,13 +2101,17 @@ errOut: CFDataRef SecKeyWrapSymmetric(SecKeyRef keyToWrap, SecKeyRef wrappingKey, CFDictionaryRef parameters, CFErrorRef *error) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL); + } return NULL; } SecKeyRef SecKeyUnwrapSymmetric(CFDataRef *keyToUnwrap, SecKeyRef unwrappingKey, CFDictionaryRef parameters, CFErrorRef *error) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL); + if(error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL); + } return NULL; }