]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_smime/lib/crypto-embedded.c
Security-59754.80.3.tar.gz
[apple/security.git] / libsecurity_smime / lib / crypto-embedded.c
index c9dd8e708f30a9bbad1a173e1291faf2a4ec4c1c..8e9a4b9bd291362a73669b7e8cb5444bdeacb5da 100644 (file)
@@ -1,10 +1,24 @@
 /*
 /*
- *  crypto-embedded.c
- *  libsecurity_smime
+ * Copyright (c) 2008-2011,2013,2015 Apple Inc. All Rights Reserved.
  *
  *
- *  Created by Conrad Sauerwald on 2/7/08.
- *  Copyright (c) 2008-2011,2013 Apple Inc. All Rights Reserved.
+ * @APPLE_LICENSE_HEADER_START@
  *
  *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
  */
 
 #include <stdio.h>
  */
 
 #include <stdio.h>
 #include <Security/oidsalg.h>
 #include <Security/SecPolicy.h>
 #include <Security/SecItem.h>
 #include <Security/oidsalg.h>
 #include <Security/SecPolicy.h>
 #include <Security/SecItem.h>
+#include <Security/SecItemPriv.h>
 #include <Security/SecIdentity.h>
 #include <Security/SecCertificateInternal.h>
 #include <Security/SecKeyPriv.h>
 #include <Security/SecIdentity.h>
 #include <Security/SecCertificateInternal.h>
 #include <Security/SecKeyPriv.h>
+#include <utilities/SecCFWrappers.h>
 
 #include <CommonCrypto/CommonDigest.h>
 #include <AssertMacros.h>
 
 SECStatus
 CERT_VerifyCert(SecKeychainRef keychainOrArray __unused, CFArrayRef certs,
 
 #include <CommonCrypto/CommonDigest.h>
 #include <AssertMacros.h>
 
 SECStatus
 CERT_VerifyCert(SecKeychainRef keychainOrArray __unused, CFArrayRef certs,
-               CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef)
+                CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef)
 {
     SecTrustRef trust = NULL;
     OSStatus rv;
 {
     SecTrustRef trust = NULL;
     OSStatus rv;
@@ -50,44 +66,76 @@ CERT_VerifyCert(SecKeychainRef keychainOrArray __unused, CFArrayRef certs,
     rv = SecTrustSetVerifyDate(trust, verifyDate);
     CFRelease(verifyDate);
     if (rv)
     rv = SecTrustSetVerifyDate(trust, verifyDate);
     CFRelease(verifyDate);
     if (rv)
-       goto loser;
+        goto loser;
 
     if (trustRef)
     {
 
     if (trustRef)
     {
-       *trustRef = trust;
+        *trustRef = trust;
     }
     else
     {
     }
     else
     {
-       SecTrustResultType result;
-       /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
-       rv = SecTrustEvaluate(trust, &result);
-       if (rv)
-           goto loser;
-
-       switch (result)
-       {
-       case kSecTrustResultProceed:
-       case kSecTrustResultUnspecified:
-           /* TP Verification succeeded and there was either a UserTurst entry
-              telling us to procceed, or no user trust setting was specified. */
-           CFRelease(trust);
-           break;
-       default:
-           PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
-           rv = SECFailure;
-           goto loser;
-           break;
-       }
+        SecTrustResultType result;
+        /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
+        rv = SecTrustEvaluate(trust, &result);
+        if (rv)
+            goto loser;
+
+        switch (result)
+        {
+            case kSecTrustResultProceed:
+            case kSecTrustResultUnspecified:
+                /* TP Verification succeeded and there was either a UserTurst entry
+                 telling us to procceed, or no user trust setting was specified. */
+                CFRelease(trust);
+                break;
+            default:
+                PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
+                rv = SECFailure;
+                goto loser;
+        }
     }
 
     return SECSuccess;
 loser:
     if (trust)
     }
 
     return SECSuccess;
 loser:
     if (trust)
-       CFRelease(trust);
+        CFRelease(trust);
 
     return rv;
 }
 
 
     return rv;
 }
 
+static CF_RETURNS_RETAINED CFTypeRef CERT_FindItemInAllAvailableKeychains(CFDictionaryRef query) {
+    CFTypeRef item = NULL;
+    CFMutableDictionaryRef q = NULL;
+    CFDictionaryRef whoAmI = NULL;
+    CFErrorRef error = NULL;
+    CFDataRef musr = NULL;
+    const uint8_t activeUserUuid[16] = "\xA7\x5A\x3A\x35\xA5\x57\x4B\x10\xBE\x2E\x83\x94\x7E\x4A\x34\x72";
+
+    /* Do the standard keychain query */
+    require_quiet(errSecItemNotFound == SecItemCopyMatching(query, &item), out);
+
+    /* No item found. Can caller use the system keychain? */
+    whoAmI = _SecSecuritydCopyWhoAmI(&error);
+    require_quiet(NULL == error && whoAmI && CFDictionaryGetValue(whoAmI, CFSTR("status")), out);
+    musr = CFDictionaryGetValue(whoAmI, CFSTR("musr"));
+    /* Caller has system-keychain entitlement, is in multi-user mode, and is an active user. */
+    if (CFDictionaryGetValue(whoAmI, CFSTR("system-keychain")) && musr &&
+        (16 == CFDataGetLength(musr)) && (0 == memcmp(activeUserUuid,CFDataGetBytePtr(musr),12))) {
+        q = CFDictionaryCreateMutableCopy(NULL, CFDictionaryGetCount(query) + 1, query);
+        CFDictionaryAddValue(q, kSecUseSystemKeychain, kCFBooleanTrue);
+        SecItemCopyMatching(q, &item);
+    }
+
+out:
+    if (q)
+        CFRelease(q);
+    if (whoAmI)
+        CFRelease(whoAmI);
+    if (error)
+        CFRelease(error);
+
+    return item;
+}
 
 SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray,
                         char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win)
 
 SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray,
                         char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win)
@@ -97,13 +145,13 @@ SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray,
        const void *values[] = { kSecClassCertificate,  nickname_cfstr };
        CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
        CFTypeRef result = NULL;
        const void *values[] = { kSecClassCertificate,  nickname_cfstr };
        CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
        CFTypeRef result = NULL;
-       SecItemCopyMatching(query, &result);
+       result = CERT_FindItemInAllAvailableKeychains(query);
        CFRelease(query);
        CFRelease(nickname_cfstr);
        return (SecCertificateRef)result;
 }
 
        CFRelease(query);
        CFRelease(nickname_cfstr);
        return (SecCertificateRef)result;
 }
 
-CF_RETURNS_RETAINED CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot)
+CF_RETURNS_RETAINED CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot, Boolean mustIncludeRoot)
 {
     CFMutableArrayRef certs = NULL;
     SecPolicyRef policy = NULL;
 {
     CFMutableArrayRef certs = NULL;
     SecPolicyRef policy = NULL;
@@ -111,30 +159,55 @@ CF_RETURNS_RETAINED CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SE
     CFArrayRef wrappedCert = NULL;
     
     policy = SecPolicyCreateBasicX509();
     CFArrayRef wrappedCert = NULL;
     
     policy = SecPolicyCreateBasicX509();
-    if (!policy)
+    if (!policy) {
         goto out;
         goto out;
+    }
     
     wrappedCert = CERT_CertListFromCert(cert);
     
     wrappedCert = CERT_CertListFromCert(cert);
-    if (SecTrustCreateWithCertificates(wrappedCert, policy, &trust))
+    if (SecTrustCreateWithCertificates(wrappedCert, policy, &trust)) {
         goto out;
         goto out;
+    }
 
        SecTrustResultType result;
 
        SecTrustResultType result;
-    if (SecTrustEvaluate(trust, &result))
+    if (SecTrustEvaluate(trust, &result)) {
         goto out;
         goto out;
+    }
     CFIndex idx, count = SecTrustGetCertificateCount(trust);
     CFIndex idx, count = SecTrustGetCertificateCount(trust);
+
+    /* If we weren't able to build a chain to a self-signed cert, warn. */
+    Boolean isSelfSigned = false;
+    SecCertificateRef lastCert = SecTrustGetCertificateAtIndex(trust, count - 1);
+    if (lastCert && (0 == SecCertificateIsSelfSigned(lastCert, &isSelfSigned)) && !isSelfSigned) {
+        CFStringRef commonName = NULL;
+        (void)SecCertificateCopyCommonName(cert, &commonName);
+        fprintf(stderr, "Warning: unable to build chain to self-signed root for signer \"%s\"\n",
+                commonName ? CFStringGetCStringPtr(commonName, kCFStringEncodingUTF8) : "");
+        if (commonName) { CFRelease(commonName); }
+
+        // we don't have a root, so if the caller required one, fail
+        if (mustIncludeRoot) {
+            goto out;
+        }
+    }
+
+    /* We don't drop the root if there is only 1 certificate in the chain. */
+    if (isSelfSigned && !includeRoot && count > 1) {
+        count--;
+    }
     certs = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks);
     certs = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks);
-    for(idx = 0; idx < count; idx++)
+    for(idx = 0; idx < count; idx++) {
         CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(trust, idx));
         CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(trust, idx));
-    
+    }
+
 out:
 out:
-    if (trust) CFRelease(trust);
-    if (policy) CFRelease(policy);
-    if (wrappedCert) CFRelease(wrappedCert);
+    if (trust) { CFRelease(trust); }
+    if (policy) { CFRelease(policy); }
+    if (wrappedCert) { CFRelease(wrappedCert); }
 
     return certs;
 }
 
 
     return certs;
 }
 
-CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
+CF_RETURNS_RETAINED CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
 {
     const void *value = cert;
     return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL;
 {
     const void *value = cert;
     return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL;
@@ -149,7 +222,7 @@ CFArrayRef CERT_DupCertList(CFArrayRef oldList)
 // Extract a public key object from a SubjectPublicKeyInfo
 SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert)
 {
 // Extract a public key object from a SubjectPublicKeyInfo
 SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert)
 {
-    return SecCertificateCopyPublicKey(cert);
+    return SecCertificateCopyKey(cert);
 }
 
 // Extract the issuer and serial number from a certificate
 }
 
 // Extract the issuer and serial number from a certificate
@@ -159,35 +232,40 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce
 
     void *mark;
     mark = PORT_ArenaMark(pl);
 
     void *mark;
     mark = PORT_ArenaMark(pl);
-    CFDataRef serial_data = NULL;
     CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert);
     CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert);
-    if (!issuer_data)
+    CFDataRef serial_data = SecCertificateCopySerialNumberData(cert, NULL);
+    if (!issuer_data || !serial_data) {
         goto loser;
         goto loser;
-    serial_data = SecCertificateCopySerialNumber(cert);
-    if (!serial_data)
-        goto loser;
-    
-    SecAsn1Item serialNumber = { CFDataGetLength(serial_data),
-        (uint8_t *)CFDataGetBytePtr(serial_data) };
-    SecAsn1Item issuer = { CFDataGetLength(issuer_data),
-        (uint8_t *)CFDataGetBytePtr(issuer_data) };
-    
-        /* Allocate the SecCmsIssuerAndSN struct. */
+    }
+
+    SecAsn1Item serialNumber = {
+        .Length = CFDataGetLength(serial_data),
+        .Data = (uint8_t *)CFDataGetBytePtr(serial_data)
+    };
+    SecAsn1Item issuer = {
+        .Length = CFDataGetLength(issuer_data),
+        .Data = (uint8_t *)CFDataGetBytePtr(issuer_data)
+    };
+
+    /* Allocate the SecCmsIssuerAndSN struct. */
     certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN));
     certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN));
-    if (certIssuerAndSN == NULL)
-       goto loser;
+    if (certIssuerAndSN == NULL) {
+        goto loser;
+    }
 
     /* Copy the issuer. */
     certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length);
 
     /* Copy the issuer. */
     certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length);
-    if (!certIssuerAndSN->derIssuer.Data)
-       goto loser;
+    if (!certIssuerAndSN->derIssuer.Data) {
+        goto loser;
+    }
     PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer.Data, issuer.Length);
     certIssuerAndSN->derIssuer.Length = issuer.Length;
 
     /* Copy the serialNumber. */
     certIssuerAndSN->serialNumber.Data = (uint8_t *) PORT_ArenaAlloc(pl, serialNumber.Length);
     PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer.Data, issuer.Length);
     certIssuerAndSN->derIssuer.Length = issuer.Length;
 
     /* Copy the serialNumber. */
     certIssuerAndSN->serialNumber.Data = (uint8_t *) PORT_ArenaAlloc(pl, serialNumber.Length);
-    if (!certIssuerAndSN->serialNumber.Data)
-       goto loser;
+    if (!certIssuerAndSN->serialNumber.Data) {
+        goto loser;
+    }
     PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length);
     certIssuerAndSN->serialNumber.Length = serialNumber.Length;
 
     PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length);
     certIssuerAndSN->serialNumber.Length = serialNumber.Length;
 
@@ -195,14 +273,12 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce
     CFRelease(issuer_data);
 
     PORT_ArenaUnmark(pl, mark);
     CFRelease(issuer_data);
 
     PORT_ArenaUnmark(pl, mark);
-    
+
     return certIssuerAndSN;
 
 loser:
     return certIssuerAndSN;
 
 loser:
-    if (serial_data)
-        CFRelease(serial_data);
-    if (issuer_data)
-        CFRelease(issuer_data);
+    CFReleaseNull(serial_data);
+    CFReleaseNull(issuer_data);
     PORT_ArenaRelease(pl, mark);
     PORT_SetError(SEC_INTERNAL_ONLY);
 
     PORT_ArenaRelease(pl, mark);
     PORT_SetError(SEC_INTERNAL_ONLY);
 
@@ -217,7 +293,7 @@ SecAsn1Item *CERT_FindSMimeProfile(SecCertificateRef cert)
 
 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
 
 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
-static CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef class, const SecCmsIssuerAndSN *issuerAndSN)
+static CF_RETURNS_RETAINED CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef class, const SecCmsIssuerAndSN *issuerAndSN)
 {
     CFTypeRef ident = NULL;
        CFDictionaryRef query = NULL;
 {
     CFTypeRef ident = NULL;
        CFDictionaryRef query = NULL;
@@ -238,14 +314,17 @@ static CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef cl
         CFIndex c, count = CFArrayGetCount((CFArrayRef)keychainOrArray);
         for (c = 0; c < count; c++) {
             SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex((CFArrayRef)keychainOrArray, c);
         CFIndex c, count = CFArrayGetCount((CFArrayRef)keychainOrArray);
         for (c = 0; c < count; c++) {
             SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex((CFArrayRef)keychainOrArray, c);
-            if (CFEqual(SecCertificateGetNormalizedIssuerContent(cert), issuer)) {
-                CFDataRef cert_serial = SecCertificateCopySerialNumber(cert);
-                bool found = CFEqual(cert_serial, serial);
-                CFRelease(cert_serial);
-                if (found) {
-                    CFRetain(cert);
-                    ident = cert;
-                    goto out;
+            CFDataRef nic = (cert) ? SecCertificateGetNormalizedIssuerContent(cert) : NULL;
+            if (nic && CFEqual(nic, issuer)) {
+                CFDataRef cert_serial = SecCertificateCopySerialNumberData(cert, NULL);
+                if (cert_serial) {
+                    bool found = CFEqual(cert_serial, serial);
+                    CFRelease(cert_serial);
+                    if (found) {
+                        CFRetain(cert);
+                        ident = cert;
+                        goto out;
+                    }
                 }
             }
         }
                 }
             }
         }
@@ -254,7 +333,7 @@ static CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef cl
        const void *keys[] = { kSecClass, kSecAttrIssuer, kSecAttrSerialNumber, kSecReturnRef };
        const void *values[] = { class, issuer, serial, kCFBooleanTrue };
        query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
        const void *keys[] = { kSecClass, kSecAttrIssuer, kSecAttrSerialNumber, kSecReturnRef };
        const void *values[] = { class, issuer, serial, kCFBooleanTrue };
        query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
-       require_noerr_quiet(SecItemCopyMatching(query, (CFTypeRef*)&ident), out);
+       ident = CERT_FindItemInAllAvailableKeychains(query);
 
 out:
     if (query)
 
 out:
     if (query)
@@ -277,16 +356,36 @@ SecCertificateRef CERT_FindCertificateByIssuerAndSN (CFTypeRef keychainOrArray,
     return (SecCertificateRef)CERT_FindByIssuerAndSN(keychainOrArray, kSecClassCertificate, issuerAndSN);
 }
 
     return (SecCertificateRef)CERT_FindByIssuerAndSN(keychainOrArray, kSecClassCertificate, issuerAndSN);
 }
 
-SecIdentityRef CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray __unused, const SecAsn1Item *subjKeyID)
+// Generate a certificate key from the Subject Key ID, then look it up in the database.
+// Return the cert if found. "subjKeyID" is the Subject Key ID to look for
+static CF_RETURNS_RETAINED CFTypeRef CERT_FindBySubjectKeyID (CFTypeRef keychainOrArray, CFTypeRef class, const SecAsn1Item *subjKeyID)
 {
 {
-    SecIdentityRef ident = NULL;
-       CFDictionaryRef query = NULL;
+    CFTypeRef ident = NULL;
+    CFDictionaryRef query = NULL;
+
+    if (!subjKeyID || !subjKeyID->Data || !subjKeyID->Length) {
+        return NULL;
+    }
+
     CFDataRef subjectkeyid = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, subjKeyID->Data, subjKeyID->Length, kCFAllocatorNull);
     CFDataRef subjectkeyid = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, subjKeyID->Data, subjKeyID->Length, kCFAllocatorNull);
+    if (keychainOrArray && (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) && CFEqual(class, kSecClassCertificate))
+    {
+        CFIndex c, count = CFArrayGetCount((CFArrayRef)keychainOrArray);
+        for (c = 0; c < count; c++) {
+            SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex((CFArrayRef)keychainOrArray, c);
+            CFDataRef skid = (cert) ? SecCertificateGetSubjectKeyID(cert) : NULL;
+            if (skid && CFEqual(skid, subjectkeyid)) {
+                CFRetain(cert);
+                ident = cert;
+                goto out;
+            }
+        }
+    }
 
 
-       const void *keys[] = { kSecClass, kSecAttrSubjectKeyID, kSecReturnRef };
-       const void *values[] = { kSecClassIdentity, subjectkeyid, kCFBooleanTrue };
-       query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
-       require_noerr_quiet(SecItemCopyMatching(query, (CFTypeRef*)&ident), out);
+    const void *keys[] = { kSecClass, kSecAttrSubjectKeyID, kSecReturnRef };
+    const void *values[] = { class, subjectkeyid, kCFBooleanTrue };
+    query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
+    ident = CERT_FindItemInAllAvailableKeychains(query);
 
 out:
     if (query)
 
 out:
     if (query)
@@ -297,6 +396,16 @@ out:
     return ident;
 }
 
     return ident;
 }
 
+SecIdentityRef CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID)
+{
+    return (SecIdentityRef)CERT_FindBySubjectKeyID(keychainOrArray, kSecClassIdentity, subjKeyID);
+}
+
+SecCertificateRef CERT_FindCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID)
+{
+     return (SecCertificateRef)CERT_FindBySubjectKeyID(keychainOrArray, kSecClassCertificate, subjKeyID);
+}
+
 
 
 SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey)
 
 
 SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey)
@@ -305,7 +414,7 @@ SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey)
     return pubKey;
 }
 
     return pubKey;
 }
 
-void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey)
+void SECKEY_DestroyPublicKey(SecPublicKeyRef CF_CONSUMED pubKey)
 {
     CFRelease(pubKey);
 }
 {
     CFRelease(pubKey);
 }
@@ -342,16 +451,24 @@ WRAP_PubWrapSymKey(SecPublicKeyRef publickey,
                         encKey->Data, &encKey->Length);
 }
 
                         encKey->Data, &encKey->Length);
 }
 
+#define MAX_KEY_SIZE 8192/8
 SecSymmetricKeyRef
 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, const SecAsn1Item *encKey, SECOidTag bulkalgtag)
 {
     size_t bulkkey_size = encKey->Length;
 SecSymmetricKeyRef
 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, const SecAsn1Item *encKey, SECOidTag bulkalgtag)
 {
     size_t bulkkey_size = encKey->Length;
-    uint8_t bulkkey_buffer[bulkkey_size];
-    if (SecKeyDecrypt(privkey, kSecPaddingPKCS1, 
-        encKey->Data, encKey->Length, bulkkey_buffer, &bulkkey_size))
-            return NULL;
+    if (bulkkey_size > MAX_KEY_SIZE) {
+        return NULL;
+    }
+
+    uint8_t *bulkkey_buffer = (uint8_t *)malloc(bulkkey_size);
+    if (!bulkkey_buffer) {
+        return NULL;
+    }
+    if (SecKeyDecrypt(privkey, kSecPaddingPKCS1, encKey->Data, encKey->Length, bulkkey_buffer, &bulkkey_size)) {
+        return NULL;
+    }
 
 
-    CFDataRef bulkkey = CFDataCreate(kCFAllocatorDefault, bulkkey_buffer, bulkkey_size);
+    CFDataRef bulkkey = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bulkkey_buffer, bulkkey_size, kCFAllocatorMalloc);
     return (SecSymmetricKeyRef)bulkkey;
 }
 
     return (SecSymmetricKeyRef)bulkkey;
 }
 
@@ -369,7 +486,7 @@ CERT_CheckIssuerAndSerial(SecCertificateRef cert, SecAsn1Item *issuer, SecAsn1It
                 break;
             }
         CFRelease(cert_issuer);
                 break;
             }
         CFRelease(cert_issuer);
-        CFDataRef cert_serial = SecCertificateCopySerialNumber(cert);
+        CFDataRef cert_serial = SecCertificateCopySerialNumberData(cert, NULL);
         if (!cert_serial)
             break;
         if ((serial->Length != (size_t)CFDataGetLength(cert_serial)) ||
         if (!cert_serial)
             break;
         if ((serial->Length != (size_t)CFDataGetLength(cert_serial)) ||