OSStatus EAPOLClientSetACLForIdentity(SecIdentityRef identity) { SecKeyRef private_key = NULL; CFArrayRef trusted_apps = NULL; OSStatus status; status = SecIdentityCopyPrivateKey(identity, &private_key); if (status != noErr) { goto done; } trusted_apps = copy_trusted_applications(TRUE); if (trusted_apps == NULL) { status = errSecParam; goto done; } status = EAPSecKeychainItemSetAccessForTrustedApplications((SecKeychainItemRef) private_key, trusted_apps); done: my_CFRelease(&private_key); my_CFRelease(&trusted_apps); return (status); }
static CFDictionaryRef SecItemCopyAttributeDictionary(CFTypeRef ref) { CFDictionaryRef refDictionary = NULL; CFTypeID typeID = CFGetTypeID(ref); if (typeID == SecKeyGetTypeID()) { refDictionary = SecKeyCopyAttributeDictionary((SecKeyRef)ref); } else if (typeID == SecCertificateGetTypeID()) { refDictionary = SecCertificateCopyAttributeDictionary((SecCertificateRef)ref); } else if (typeID == SecIdentityGetTypeID()) { assert(false); SecIdentityRef identity = (SecIdentityRef)ref; SecCertificateRef cert = NULL; SecKeyRef key = NULL; if (!SecIdentityCopyCertificate(identity, &cert) && !SecIdentityCopyPrivateKey(identity, &key)) { CFDataRef data = SecCertificateCopyData(cert); CFDictionaryRef key_dict = SecKeyCopyAttributeDictionary(key); if (key_dict && data) { refDictionary = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, key_dict); CFDictionarySetValue((CFMutableDictionaryRef)refDictionary, CFSTR(CERTIFICATE_DATA_COLUMN_LABEL), data); } CFReleaseNull(key_dict); CFReleaseNull(data); } CFReleaseNull(cert); CFReleaseNull(key); } else { refDictionary = NULL; } return refDictionary; }
SecKeyRef _crypt_get_private_key() { uint8_t keyData[strlen(AIRPORT_PRIVATE_KEY_P12)]; size_t keyDataLen = base64_decode(AIRPORT_PRIVATE_KEY_P12, keyData); CFDataRef key = CFDataCreate(NULL, keyData, keyDataLen); CFMutableDictionaryRef options = CFDictionaryCreateMutable(NULL, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(options, kSecImportExportPassphrase, CFSTR("")); CFArrayRef items = NULL; OSStatus error = SecPKCS12Import(key, options, &items); SecKeyRef privateKey = NULL; if (error == noErr && CFArrayGetCount(items) > 0) { CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0); SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity); error = SecIdentityCopyPrivateKey(identity, &privateKey); if (error != noErr) privateKey = NULL; } CFRelease(items); CFRelease(options); return privateKey; }
extern "C" int32_t AppleCryptoNative_X509CopyPrivateKeyFromIdentity(SecIdentityRef identity, SecKeyRef* pPrivateKeyOut) { if (pPrivateKeyOut != nullptr) *pPrivateKeyOut = nullptr; // This function handles null inputs for both identity and key return SecIdentityCopyPrivateKey(identity, pPrivateKeyOut); }
int nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wincx) { SecCmsRecipient *recipient; SecCertificateRef cert = NULL; SecPrivateKeyRef privKey = NULL; SecIdentityRef identity = NULL; CFTypeRef keychainOrArray = NULL; // @@@ The caller should be able to pass this in somehow. int index; for (index = 0; recipient_list[index] != NULL; ++index) { recipient = recipient_list[index]; switch (recipient->kind) { case RLIssuerSN: identity = CERT_FindIdentityByIssuerAndSN(keychainOrArray, recipient->id.issuerAndSN); break; case RLSubjKeyID: identity = CERT_FindIdentityBySubjectKeyID(keychainOrArray, recipient->id.subjectKeyID); break; } if (identity) break; } if (!recipient) goto loser; if (SecIdentityCopyCertificate(identity, &cert)) goto loser; if (SecIdentityCopyPrivateKey(identity, &privKey)) goto loser; CFRelease(identity); recipient->cert = cert; recipient->privkey = privKey; return index; loser: if (identity) CFRelease(identity); if (cert) CFRelease(cert); if (privKey) CFRelease(privKey); return -1; }
void signData(SecIdentityRef identity, const uint8_t *from, int flen, uint8_t *to, size_t *tlen) { SecKeyRef privateKey = NULL; OSStatus status; status = SecIdentityCopyPrivateKey(identity, &privateKey); if (status != noErr) { printErrorStatusMsg("signData: SecIdentityCopyPrivateKey", status); *tlen = 0; return; } status = SecKeyRawSign(privateKey, kSecPaddingPKCS1, from, flen, to, tlen); CFRelease(privateKey); if (status != noErr) { printErrorStatusMsg("signData: SecKeyRawSign", status); *tlen = 0; return; } }
SecCmsSignerInfoRef SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag) { SecCmsSignerInfoRef signerInfo = NULL; SecCertificateRef cert = NULL; SecPrivateKeyRef signingKey = NULL; if (SecIdentityCopyCertificate(identity, &cert)) goto loser; if (SecIdentityCopyPrivateKey(identity, &signingKey)) goto loser; signerInfo = nss_cmssignerinfo_create(cmsg, SecCmsSignerIDIssuerSN, cert, NULL, NULL, signingKey, digestalgtag); loser: if (cert) CFRelease(cert); if (signingKey) CFRelease(signingKey); return signerInfo; }
/* * In Mac OS terms, get the keychain on which a given identity resides. */ static krb5_error_code pkinit_cert_to_db( krb5_pkinit_signing_cert_t idRef, krb5_pkinit_cert_db_t *dbRef) { SecKeychainRef kcRef = NULL; SecKeyRef keyRef = NULL; OSStatus ortn; /* that's an identity - get the associated key's keychain */ ortn = SecIdentityCopyPrivateKey((SecIdentityRef)idRef, &keyRef); if(ortn) { pkiCssmErr("SecIdentityCopyPrivateKey", ortn); return ortn; } ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)keyRef, &kcRef); if(ortn) { pkiCssmErr("SecKeychainItemCopyKeychain", ortn); } else { *dbRef = (krb5_pkinit_cert_db_t)kcRef; } CFRelease(keyRef); return ortn; }
OSStatus parseIncomingCerts( SSLContext *ctx, CFArrayRef certs, CFArrayRef *destCertChain, /* &ctx->{localCertChain,encryptCertChain} */ SSLPubKey **sslPubKey, /* &ctx->signingPubKey, etc. */ SSLPrivKey **sslPrivKey, /* &ctx->signingPrivKeyRef, etc. */ CFIndex *signerAlg) /* optional */ { OSStatus ortn; CFIndex ix, numCerts; SecIdentityRef identity; CFMutableArrayRef certChain = NULL; /* Retained */ SecCertificateRef leafCert = NULL; /* Retained */ SecKeyRef pubKey = NULL; /* Retained */ SecKeyRef privKey = NULL; /* Retained */ SecTrustRef trust = NULL; /* Retained */ SecTrustResultType trustResult; assert(ctx != NULL); assert(destCertChain != NULL); /* though its referent may be NULL */ assert(sslPubKey != NULL); assert(sslPrivKey != NULL); if (certs == NULL) { sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); ortn = errSSLBadCert; goto errOut; } numCerts = CFArrayGetCount(certs); if (numCerts == 0) { sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); ortn = errSSLBadCert; goto errOut; } /* * Certs[0] is an SecIdentityRef from which we extract subject cert, * privKey, pubKey. * * 1. ensure the first element is a SecIdentityRef. */ identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); if (identity == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); ortn = paramErr; goto errOut; } if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); ortn = paramErr; goto errOut; } /* * 2. Extract cert, keys and convert to local format. */ ortn = SecIdentityCopyCertificate(identity, &leafCert); if (ortn) { sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); goto errOut; } /* Fetch private key from identity */ ortn = SecIdentityCopyPrivateKey(identity, &privKey); if (ortn) { sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", (int)ortn); goto errOut; } /* Convert the input array of SecIdentityRef at the start to an array of all certificates. */ certChain = CFArrayCreateMutable(kCFAllocatorDefault, numCerts, &kCFTypeArrayCallBacks); if (!certChain) { ortn = memFullErr; goto errOut; } CFArrayAppendValue(certChain, leafCert); for (ix = 1; ix < numCerts; ++ix) { SecCertificateRef intermediate = (SecCertificateRef)CFArrayGetValueAtIndex(certs, ix); if (intermediate == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); ortn = paramErr; goto errOut; } if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); ortn = paramErr; goto errOut; } CFArrayAppendValue(certChain, intermediate); } /* Obtain public key from cert */ #if TARGET_OS_IOS ortn = SecTrustCreateWithCertificates(certChain, NULL, &trust); #else { SecPolicyRef policy = SecPolicyCreateBasicX509(); ortn = SecTrustCreateWithCertificates(certChain, policy, &trust); CFReleaseSafe(policy); if (!ortn) { /* We are only interested in getting the public key from the leaf * cert here, so for best performance, don't try to build a chain * or search any keychains. */ CFArrayRef emptyArray = CFArrayCreate(NULL, NULL, 0, NULL); (void)SecTrustSetAnchorCertificates(trust, emptyArray); (void)SecTrustSetKeychains(trust, emptyArray); CFReleaseSafe(emptyArray); } } #endif if (ortn) { sslErrorLog("parseIncomingCerts: SecTrustCreateWithCertificates err %d\n", (int)ortn); goto errOut; } ortn = SecTrustEvaluate(trust, &trustResult); if (ortn) { sslErrorLog("parseIncomingCerts: SecTrustEvaluate err %d\n", (int)ortn); goto errOut; } pubKey = SecTrustCopyPublicKey(trust); if (pubKey == NULL) { sslErrorLog("parseIncomingCerts: SecTrustCopyPublicKey failed\n"); ortn = -67712; // errSecInvalidKeyRef goto errOut; } /* SUCCESS */ errOut: CFReleaseSafe(trust); CFReleaseSafe(leafCert); CFReleaseSafe(*destCertChain); sslFreePubKey(sslPubKey); sslFreePrivKey(sslPrivKey); if (ortn) { CFReleaseSafe(certChain); CFReleaseSafe(pubKey); CFReleaseSafe(privKey); *destCertChain = NULL; } else { *destCertChain = certChain; *sslPubKey = (SSLPubKey*)pubKey; *sslPrivKey = (SSLPrivKey*)privKey; } return ortn; }
OSStatus parseIncomingCerts( SSLContext *ctx, CFArrayRef certs, SSLCertificate **destCert, /* &ctx->{localCert,encryptCert} */ CSSM_KEY_PTR *pubKey, /* &ctx->signingPubKey, etc. */ SecKeyRef *privKeyRef, /* &ctx->signingPrivKeyRef, etc. */ CSSM_ALGORITHMS *signerAlg) /* optional */ { CFIndex numCerts; CFIndex cert; SSLCertificate *certChain = NULL; SSLCertificate *thisSslCert; OSStatus ortn; SecIdentityRef identity; SecCertificateRef certRef; SecKeyRef keyRef; CSSM_DATA certData; CSSM_CL_HANDLE clHand; // carefully derive from a SecCertificateRef CSSM_RETURN crtn; CSSM_KEY_PTR *pubKey; SecKeyRef *privKeyRef; assert(ctx != NULL); assert(destCert != NULL); /* though its referent may be NULL */ assert(sslPubKey != NULL); assert(sslPrivKeyRef != NULL); pubKey = &sslPubKey->key; privKeyRef = &sslPrivKey->key; sslDeleteCertificateChain(*destCert, ctx); *destCert = NULL; *pubKey = NULL; *privKeyRef = NULL; if(certs == NULL) { sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); return errSSLBadCert; } numCerts = CFArrayGetCount(certs); if(numCerts == 0) { sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); return errSSLBadCert; } /* * Certs[0] is an SecIdentityRef from which we extract subject cert, * privKeyRef, pubKey. * * 1. ensure the first element is a SecIdentityRef. */ identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); if(identity == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); return paramErr; } if(CFGetTypeID(identity) != SecIdentityGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); return paramErr; } /* * 2. Extract cert, keys and convert to local format. */ ortn = SecIdentityCopyCertificate(identity, &certRef); if(ortn) { sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); return ortn; } ortn = secCertToSslCert(ctx, certRef, &thisSslCert); if(ortn) { sslErrorLog("parseIncomingCerts: bad cert array (4)\n"); return ortn; } /* enqueue onto head of cert chain */ thisSslCert->next = certChain; certChain = thisSslCert; if(signerAlg != NULL) { ortn = sslCertSignerAlg(certRef, signerAlg); if(ortn) { return ortn; } } /* fetch private key from identity */ ortn = SecIdentityCopyPrivateKey(identity, &keyRef); if(ortn) { sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", (int)ortn); return ortn; } *privKeyRef = keyRef; /* obtain public key from cert */ ortn = SecCertificateGetCLHandle(certRef, &clHand); if(ortn) { sslErrorLog("parseIncomingCerts: SecCertificateGetCLHandle err %d\n", (int)ortn); return ortn; } certData.Data = thisSslCert->derCert.data; certData.Length = thisSslCert->derCert.length; crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, pubKey); if(crtn) { sslErrorLog("parseIncomingCerts: CSSM_CL_CertGetKeyInfo err\n"); return (OSStatus)crtn; } /* OK, that's the subject cert. Fetch optional remaining certs. */ /* * Convert: CFArray of SecCertificateRefs --> chain of SSLCertificates. * Incoming certs have root last; SSLCertificate chain has root * first. */ for(cert=1; cert<numCerts; cert++) { certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certs, cert); if(certRef == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); return paramErr; } if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); return paramErr; } /* Extract cert, convert to local format. */ ortn = secCertToSslCert(ctx, certRef, &thisSslCert); if(ortn) { sslErrorLog("parseIncomingCerts: bad cert array (7)\n"); return ortn; } /* enqueue onto head of cert chain */ thisSslCert->next = certChain; certChain = thisSslCert; } /* SUCCESS */ *destCert = certChain; return noErr; /* free certChain, everything in it, other vars, return ortn */ sslDeleteCertificateChain(certChain, ctx); /* FIXME - anything else? */ return ortn; }
int findEncryptionIdentities(CFTypeRef *identityOrArray) { /* Similar code is available in Leopard9A311 and later as "DIHLFVCopyEncryptionIdentities". See <rdar://problem/4816811> FV: Add SecTokenBasedEncryptionIdentities call We reproduce it here for two reasons: 1) The semantics of DIHLFVCopyEncryptionIdentities are different, returning either a CFData or CFArray 2) We don' have to introduce a dependence on DiskImages.framework here Since CSSM searching for attributes is an AND, not an OR, we need to get all identities then check each one for a good key usage. If we built up a search using an OR predicate, we would want to specify this for key usage: uint32_t keyuse = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP; */ OSStatus status = noErr; CFArrayRef searchList = NULL; CFMutableArrayRef idArray = NULL; // holds all SecIdentityRefs found status = SecKeychainCopyDomainSearchList(kSecPreferencesDomainDynamic, &searchList); if (status) return status; CFIndex count = searchList ? CFArrayGetCount(searchList) : 0; if (!count) return errSecNoSuchKeychain; // Search for all identities uint32_t keyuse = 0; SecIdentitySearchRef srchRef = NULL; status = SecIdentitySearchCreate(searchList, keyuse, &srchRef); if (status) return status; while (!status) { SecIdentityRef identity = NULL; status = SecIdentitySearchCopyNext(srchRef, &identity); if (status == errSecItemNotFound) // done break; if (status) return status; SecKeyRef privateKeyRef = NULL; status = SecIdentityCopyPrivateKey(identity, &privateKeyRef); if (status) continue; bool canEncrypt = encryptionEnabled(privateKeyRef); CFRelease(privateKeyRef); if (!canEncrypt) continue; // add the identity to the array if (!idArray) idArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue(idArray, identity); } if ((status == noErr || status == errSecItemNotFound) && idArray && CFArrayGetCount(idArray)) { if (idArray) { *identityOrArray = idArray; ::CFRetain(*identityOrArray); } status = noErr; } else if (idArray) CFRelease(idArray); return status; }
static void tests(void) { CFDataRef message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, _user_one_p12, sizeof(_user_one_p12), kCFAllocatorNull); CFArrayRef items = NULL; SecCertificateRef cert = NULL; SecKeyRef pkey = NULL; is_status(SecPKCS12Import(message, NULL, NULL), errSecAuthFailed, "try null password on a known good p12"); CFStringRef password = CFSTR("user-one"); CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&kSecImportExportPassphrase, (const void **)&password, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecPKCS12Import(message, options, &items), "import user one"); is(CFArrayGetCount(items), 1, "one identity"); CFDictionaryRef item = CFArrayGetValueAtIndex(items, 0); SecIdentityRef identity = NULL; ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); CFReleaseNull(items); CFReleaseNull(message); CFReleaseNull(options); CFReleaseNull(password); CFReleaseNull(cert); CFReleaseNull(pkey); message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, _user_two_p12, sizeof(_user_two_p12), kCFAllocatorNull); items = NULL; password = CFSTR("user-two"); options = CFDictionaryCreate(NULL, (const void **)&kSecImportExportPassphrase, (const void **)&password, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecPKCS12Import(message, options, &items), "import user two"); is(CFArrayGetCount(items), 1, "one identity"); item = CFArrayGetValueAtIndex(items, 0); ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); CFReleaseNull(items); CFReleaseNull(message); CFReleaseNull(options); CFReleaseNull(password); CFReleaseNull(cert); CFReleaseNull(pkey); message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, ECDSA_fails_import_p12, ECDSA_fails_import_p12_len, kCFAllocatorNull); items = NULL; password = CFSTR("test"); options = CFDictionaryCreate(NULL, (const void **)&kSecImportExportPassphrase, (const void **)&password, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecPKCS12Import(message, options, &items), "import ECDSA_fails_import_p12"); is(CFArrayGetCount(items), 1, "one identity"); item = CFArrayGetValueAtIndex(items, 0); ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); CFDataRef pubdata = NULL; SecKeyRef pubkey = NULL; ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key"); ok(pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault, CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata), kSecKeyEncodingBytes), "recreate seckey"); /* Sign something. */ uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; size_t sigLen = SecKeyGetSize(pkey, kSecKeySignatureSize); uint8_t sig[sigLen]; ok_status(SecKeyRawSign(pkey, kSecPaddingPKCS1, something, sizeof(something), sig, &sigLen), "sign something"); ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1, something, sizeof(something), sig, sigLen), "verify sig on something"); CFReleaseNull(pubdata); CFReleaseNull(pubkey); CFReleaseNull(pkey); ok(pkey = SecKeyCreateECPrivateKey(kCFAllocatorDefault, ECDSA_fails_import_priv_only, ECDSA_fails_import_priv_only_len, kSecKeyEncodingPkcs1), "import privkey without pub"); ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key"); ok(pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault, CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata), kSecKeyEncodingBytes), "recreate seckey"); ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1, something, sizeof(something), sig, sigLen), "verify sig on something"); CFReleaseNull(pubdata); CFReleaseNull(pubkey); CFReleaseNull(pkey); CFReleaseNull(items); CFReleaseNull(message); CFReleaseNull(options); CFReleaseNull(password); CFReleaseNull(cert); }
static OSStatus parseIncomingCerts(CFArrayRef certs, SSLCertificate **destCertChain, /* &ctx->{localCertChain,encryptCertChain} */ tls_private_key_t *sslPrivKey) /* &ctx->signingPrivKeyRef, etc. */ { OSStatus ortn; CFIndex ix, numCerts; SecIdentityRef identity; SSLCertificate *certChain = NULL; /* Retained */ SecCertificateRef leafCert = NULL; /* Retained */ SecKeyRef privKey = NULL; /* Retained */ assert(destCertChain != NULL); /* though its referent may be NULL */ assert(sslPrivKey != NULL); if (certs == NULL) { sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); ortn = errSSLBadCert; goto errOut; } numCerts = CFArrayGetCount(certs); if (numCerts == 0) { sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); ortn = errSSLBadCert; goto errOut; } certChain=sslMalloc(numCerts*sizeof(SSLCertificate)); if (!certChain) { ortn = errSecAllocate; goto errOut; } /* * Certs[0] is an SecIdentityRef from which we extract subject cert, * privKey, pubKey. * * 1. ensure the first element is a SecIdentityRef. */ identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); if (identity == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); ortn = errSecParam; goto errOut; } if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); ortn = errSecParam; goto errOut; } /* * 2. Extract cert, keys and convert to local format. */ ortn = SecIdentityCopyCertificate(identity, &leafCert); if (ortn) { sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); goto errOut; } /* Fetch private key from identity */ ortn = SecIdentityCopyPrivateKey(identity, &privKey); if (ortn) { sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", (int)ortn); goto errOut; } /* Convert the input array of SecIdentityRef at the start to an array of all certificates. */ SSLCopyBufferFromData(SecCertificateGetBytePtr(leafCert), SecCertificateGetLength(leafCert), &certChain[0].derCert); certChain[0].next = NULL; for (ix = 1; ix < numCerts; ++ix) { SecCertificateRef intermediate = (SecCertificateRef)CFArrayGetValueAtIndex(certs, ix); if (intermediate == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); ortn = errSecParam; goto errOut; } if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); ortn = errSecParam; goto errOut; } SSLCopyBufferFromData(SecCertificateGetBytePtr(intermediate), SecCertificateGetLength(intermediate), &certChain[ix].derCert); certChain[ix].next = NULL; certChain[ix-1].next = &certChain[ix]; } size_t size = SecKeyGetBlockSize(privKey); tls_private_key_desc_t desc; if(SecKeyGetAlgorithmId(privKey) == kSecRSAAlgorithmID) { desc.type = tls_private_key_type_rsa; desc.rsa.sign = mySSLPrivKeyRSA_sign; desc.rsa.decrypt = mySSLPrivKeyRSA_decrypt; desc.rsa.size = SecKeyGetBlockSize(privKey); } else if (SecKeyGetAlgorithmId(privKey) == kSecECDSAAlgorithmID) { desc.type = tls_private_key_type_ecdsa; desc.ecdsa.sign = mySSLPrivKeyECDSA_sign; desc.ecdsa.curve = SecECKeyGetNamedCurve(privKey); #if TARGET_OS_IPHONE /* Compute signature size from key size */ desc.ecdsa.size = 8+2*size; #else desc.ecdsa.size = size; #endif } else { ortn = errSecParam; goto errOut; } *sslPrivKey = tls_private_key_create(&desc, privKey, (tls_private_key_ctx_release)&CFRelease); if(*sslPrivKey) ortn = errSecSuccess; else ortn = errSecAllocate; /* SUCCESS */ errOut: CFReleaseSafe(leafCert); if (ortn) { free(certChain); CFReleaseSafe(privKey); *destCertChain = NULL; } else { *destCertChain = certChain; } return ortn; }