X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/fa7225c82381bac4432a6edf16f53b5370238d85..6b200bc335dc93c5516ccb52f14bd896d8c7fad7:/OSX/libsecurity_keychain/lib/SecKey.cpp diff --git a/OSX/libsecurity_keychain/lib/SecKey.cpp b/OSX/libsecurity_keychain/lib/SecKey.cpp index a80fe3be..c346136c 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,7 +518,9 @@ 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()) { + } + + if (result == NULL && key->publicKey()) { KeyItem *publicKey = new KeyItem(key->publicKey()); result = reinterpret_cast(publicKey->handle()); } @@ -526,7 +530,7 @@ static SecKeyRef SecCDSAKeyCopyPublicKey(SecKeyRef privateKey) { 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,9 +578,11 @@ 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; } @@ -629,21 +643,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 +676,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 +687,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 +701,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 +752,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 +761,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 +787,8 @@ const SecKeyDescriptor kSecCDSAKeyDescriptor = { .copyExternalRepresentation = SecCDSAKeyCopyExternalRepresentation, .copyPublicKey = SecCDSAKeyCopyPublicKey, .copyOperationResult = SecCDSAKeyCopyOperationResult, - .isEqual = SecCDSAIsEqual, + .isEqual = SecCDSAKeyIsEqual, + .setParameter = SecCDSAKeySetParameter, }; namespace Security { @@ -1990,7 +2026,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; } @@ -2007,7 +2045,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 +2060,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; }