X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/b04fe171f0375ecd5d8a24747ca1dff85720a0ca..dd5fb164cf5b32c462296bc65e289e100f74b59a:/OSX/libsecurity_keychain/lib/SecKey.cpp diff --git a/OSX/libsecurity_keychain/lib/SecKey.cpp b/OSX/libsecurity_keychain/lib/SecKey.cpp index 2c2bd87d..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" @@ -162,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, @@ -177,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, @@ -215,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, @@ -249,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) { @@ -347,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; @@ -517,15 +518,17 @@ 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, CFIndex &inputSizeLimit) { KeyItem *keyItem = key->key; @@ -583,6 +586,14 @@ static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType o } 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; } @@ -847,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) @@ -901,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 } @@ -1073,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; } @@ -1436,6 +1461,7 @@ static OSStatus SetKeyLabelAndTag(SecKeyRef keyRef, CFTypeRef label, CFDataRef t SecKeychainAttribute attributes[numToModify]; int i = 0; + void *data = NULL; if (label != NULL) { @@ -1445,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); } } @@ -1476,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; } @@ -1820,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[] = { @@ -1915,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); } @@ -1976,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; } @@ -1992,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; } @@ -2000,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; } @@ -2023,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; } @@ -2032,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; } @@ -2040,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: @@ -2053,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; }