]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_keychain/lib/SecKey.cpp
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecKey.cpp
index a80fe3be30355a1b342c6b2d98b2bc1c4eeb6a48..c346136cfbe933a76d25582f344ffeaccad403bf 100644 (file)
@@ -32,6 +32,7 @@
 #include <Security/SecAsn1Types.h>
 #include <Security/SecAsn1Coder.h>
 #include <security_keychain/KeyItem.h>
 #include <Security/SecAsn1Types.h>
 #include <Security/SecAsn1Coder.h>
 #include <security_keychain/KeyItem.h>
+#include <security_utilities/casts.h>
 #include <CommonCrypto/CommonKeyDerivation.h>
 
 #include "SecBridge.h"
 #include <CommonCrypto/CommonKeyDerivation.h>
 
 #include "SecBridge.h"
@@ -54,6 +55,7 @@ static OSStatus
 SecCDSAKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
     key->key = const_cast<KeyItem *>(reinterpret_cast<const KeyItem *>(keyData));
     key->key->initializeWithSecKeyRef(key);
 SecCDSAKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
     key->key = const_cast<KeyItem *>(reinterpret_cast<const KeyItem *>(keyData));
     key->key->initializeWithSecKeyRef(key);
+    key->credentialType = kSecCredentialTypeDefault;
     return errSecSuccess;
 }
 
     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.
 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<CFIndex, DERSize>(CFDataGetLength(pubKeyInfo)) }, pubKeyItem;
     DERByte numUnused;
     DERSubjPubKeyInfo subjPubKey;
     if (DERParseSequence(&keyItem, DERNumSubjPubKeyInfoItemSpecs,
     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.
 
 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<CFIndex, DERSize>(CFDataGetLength(pubKeyInfo)) };
     DERSubjPubKeyInfo subjPubKey;
     if (DERParseSequence(&keyItem, DERNumSubjPubKeyInfoItemSpecs,
                          DERSubjPubKeyInfoItemSpecs,
     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<DERByte *>(oidECsecp384);
             subjPubKey.algId.length = sizeof(oidECsecp256);
         } else if (keySizeInBits == 384) {
             subjPubKey.algId.data = const_cast<DERByte *>(oidECsecp384);
-            subjPubKey.algId.length = sizeof(oidECsecp256);
+            subjPubKey.algId.length = sizeof(oidECsecp384);
         } if (keySizeInBits == 521) {
             subjPubKey.algId.data = const_cast<DERByte *>(oidECsecp521);
         } if (keySizeInBits == 521) {
             subjPubKey.algId.data = const_cast<DERByte *>(oidECsecp521);
-            subjPubKey.algId.length = sizeof(oidECsecp256);
+            subjPubKey.algId.length = sizeof(oidECsecp521);
         }
     }
     DERSize size = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, &subjPubKey,
         }
     }
     DERSize size = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, &subjPubKey,
@@ -248,7 +250,7 @@ static OSStatus SecCDSAKeyCopyPublicBytes(SecKeyRef key, CFDataRef *serializatio
                     CFRef<CFDataRef> privKeyData;
                     result = SecItemExport(key, kSecFormatOpenSSL, 0, NULL, privKeyData.take());
                     if (result == errSecSuccess) {
                     CFRef<CFDataRef> 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<CFIndex, DERSize>(CFDataGetLength(privKeyData)) };
                         DERRSAKeyPair keyPair;
                         if (DERParseSequence(&keyItem, DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
                                              &keyPair, sizeof(keyPair)) == DR_Success) {
                         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.
             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<CFIndex, DERSize>(CFDataGetLength(keyData)) };
                 DERECPrivateKey privateKey;
                 DERECPrivateKeyPublicKey privateKeyPublicKey;
                 DERByte numUnused;
                 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<SecKeyRef>(publicKey->handle());
         }
             Item publicKey = key->keychain()->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, uniqueId);
             result = reinterpret_cast<SecKeyRef>(publicKey->handle());
         }
-    } else if (key->publicKey()) {
+    }
+
+    if (result == NULL && key->publicKey()) {
         KeyItem *publicKey = new KeyItem(key->publicKey());
         result = reinterpret_cast<SecKeyRef>(publicKey->handle());
     }
         KeyItem *publicKey = new KeyItem(key->publicKey());
         result = reinterpret_cast<SecKeyRef>(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,
 
 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();
     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;
                 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;
                 } 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;
                 } 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;
                 } 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;
                 } 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;
                 } 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;
                 } 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;
                 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5)) {
                     secondaryAlgorithm = CSSM_ALGID_MD5;
                     paddingAlgorithm = CSSM_PADDING_PKCS1;
+                    inputSizeLimit = 16;
                 } else {
                     return NULL;
                 }
                 } 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;
                 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;
                 } else if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionPKCS1)) {
                     secondaryAlgorithm = CSSM_ALGID_NONE;
                     paddingAlgorithm = CSSM_PADDING_PKCS1;
+                    inputSizeLimit = operation == kSecKeyOperationTypeEncrypt ? -11 : 0;
                 } else {
                     return NULL;
                 }
                 } 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)
                                                CFArrayRef allAlgorithms, SecKeyOperationMode mode,
                                                CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
     BEGIN_SECKEYAPI(CFTypeRef, kCFNull)
+    CFIndex inputSizeLimit = 0;
     CSSM_ALGORITHMS baseAlgorithm, secondaryAlgorithm, paddingAlgorithm;
     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;
     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());
     }
 
     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<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
             CssmAutoData signature(signContext.allocator());
             signContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm);
             CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::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());
         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<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
             verifyContext.verify(CssmData(CFDataRef(input)), CssmData(CFRef<CFDataRef>::check(in2, errSecParam)));
             verifyContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm);
             CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
             verifyContext.verify(CssmData(CFDataRef(input)), CssmData(CFRef<CFDataRef>::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);
             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<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
             CssmAutoData output(encryptContext.allocator()), remainingData(encryptContext.allocator());
             size_t length = encryptContext.encrypt(CssmData(CFDataRef(input)), output.get(), remainingData.get());
             CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::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);
             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<CFDataRef>::check(in1, errSecParam)),
                                                    output.get(), remainingData.get());
             CssmAutoData output(decryptContext.allocator()), remainingData(decryptContext.allocator());
             size_t length = decryptContext.decrypt(CssmData(CFRef<CFDataRef>::check(in1, errSecParam)),
                                                    output.get(), remainingData.get());
@@ -730,7 +752,7 @@ static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationTyp
     END_SECKEYAPI
 }
 
     END_SECKEYAPI
 }
 
-static Boolean SecCDSAIsEqual(SecKeyRef key1, SecKeyRef key2) {
+static Boolean SecCDSAKeyIsEqual(SecKeyRef key1, SecKeyRef key2) {
     CFErrorRef *error;
     BEGIN_SECKEYAPI(Boolean, false)
 
     CFErrorRef *error;
     BEGIN_SECKEYAPI(Boolean, false)
 
@@ -739,6 +761,19 @@ static Boolean SecCDSAIsEqual(SecKeyRef key1, SecKeyRef key2) {
     END_SECKEYAPI
 }
 
     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",
 const SecKeyDescriptor kSecCDSAKeyDescriptor = {
     .version = kSecKeyDescriptorVersion,
     .name = "CDSAKey",
@@ -752,7 +787,8 @@ const SecKeyDescriptor kSecCDSAKeyDescriptor = {
     .copyExternalRepresentation = SecCDSAKeyCopyExternalRepresentation,
     .copyPublicKey = SecCDSAKeyCopyPublicKey,
     .copyOperationResult = SecCDSAKeyCopyOperationResult,
     .copyExternalRepresentation = SecCDSAKeyCopyExternalRepresentation,
     .copyPublicKey = SecCDSAKeyCopyPublicKey,
     .copyOperationResult = SecCDSAKeyCopyOperationResult,
-    .isEqual = SecCDSAIsEqual,
+    .isEqual = SecCDSAKeyIsEqual,
+    .setParameter = SecCDSAKeySetParameter,
 };
 
 namespace Security {
 };
 
 namespace Security {
@@ -1990,7 +2026,9 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr
     } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA512)) {
         algorithm = kCCPRFHmacAlgSHA512;
     } else {
     } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA512)) {
         algorithm = kCCPRFHmacAlgSHA512;
     } else {
-        *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidAlgorithmParms, NULL);
+        if(error) {
+            *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidAlgorithmParms, NULL);
+        }
         goto errOut;
     }
 
         goto errOut;
     }
 
@@ -2007,7 +2045,9 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr
         retval =  SecKeyCreateFromData(parameters, keyData, error);
         CFRelease(keyData);
     } else {
         retval =  SecKeyCreateFromData(parameters, keyData, error);
         CFRelease(keyData);
     } else {
-        *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL);
+        if(error) {
+            *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL);
+        }
     }
 
 errOut:
     }
 
 errOut:
@@ -2020,13 +2060,17 @@ errOut:
 CFDataRef
 SecKeyWrapSymmetric(SecKeyRef keyToWrap, SecKeyRef wrappingKey, CFDictionaryRef parameters, CFErrorRef *error)
 {
 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)
 {
     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;
 }
     return NULL;
 }