X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_ssl/lib/sslKeychain.c?ds=inline diff --git a/libsecurity_ssl/lib/sslKeychain.c b/libsecurity_ssl/lib/sslKeychain.c deleted file mode 100644 index 5e80e622..00000000 --- a/libsecurity_ssl/lib/sslKeychain.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2008,2010-2012 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@ - */ - -/* - * sslKeychain.c - Apple Keychain routines - */ - -#include "ssl.h" -#include "sslContext.h" -#include "sslMemory.h" - -#include "sslCrypto.h" -#ifdef USE_CDSA_CRYPTO -#include -#else -#include -#include -#include -#include -#include -#endif /* !USE_CDSA_CRYPTO */ -#include "utilities/SecCFRelease.h" - -#include "sslDebug.h" -#include "sslKeychain.h" -#include "sslUtils.h" -#include -#include - -#if TARGET_OS_IPHONE -#include "utilities/SecCFRelease.h" -#endif - -#ifdef USE_SSLCERTIFICATE - -/* - * Given an array of certs (as SecIdentityRefs, specified by caller - * in SSLSetCertificate or SSLSetEncryptionCertificate) and a - * destination SSLCertificate: - * - * -- free destCerts if we have any - * -- Get raw cert data, convert to array of SSLCertificates in *destCert - * -- validate cert chain - * -- get pub, priv keys from certRef[0], store in *pubKey, *privKey - */ - -/* Convert a SecCertificateRef to an SSLCertificate * */ -static OSStatus secCertToSslCert( - SSLContext *ctx, - SecCertificateRef certRef, - SSLCertificate **sslCert) -{ - CSSM_DATA certData; // struct is transient, referent owned by - // Sec layer - OSStatus ortn; - SSLCertificate *thisSslCert = NULL; - - ortn = SecCertificateGetData(certRef, &certData); - if(ortn) { - sslErrorLog("SecCertificateGetData() returned %d\n", (int)ortn); - return ortn; - } - - thisSslCert = (SSLCertificate *)sslMalloc(sizeof(SSLCertificate)); - if(thisSslCert == NULL) { - return errSecAllocate; - } - if(SSLAllocBuffer(&thisSslCert->derCert, certData.Length, - ctx)) { - return errSecAllocate; - } - memcpy(thisSslCert->derCert.data, certData.Data, certData.Length); - thisSslCert->derCert.length = certData.Length; - *sslCert = thisSslCert; - return errSecSuccess; -} - -/* - * Determine the basic signing algorithm, without the digest, component, of - * a cert. The returned algorithm will be RSA, DSA, or ECDSA. - */ -static OSStatus sslCertSignerAlg( - SecCertificateRef certRef, - CSSM_ALGORITHMS *signerAlg) -{ - OSStatus ortn; - CSSM_DATA_PTR fieldPtr; - CSSM_X509_ALGORITHM_IDENTIFIER *algId; - CSSM_ALGORITHMS sigAlg; - - /* - * Extract the full signature algorithm OID - */ - *signerAlg = CSSM_ALGID_NONE; - ortn = SecCertificateCopyFirstFieldValue(certRef, - &CSSMOID_X509V1SignatureAlgorithm, - &fieldPtr); - if(ortn) { - return ortn; - } - if(fieldPtr->Length != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) { - sslErrorLog("sslCertSignerAlg() length error\n"); - ortn = errSSLCrypto; - goto errOut; - } - algId = (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldPtr->Data; - if(!cssmOidToAlg(&algId->algorithm, &sigAlg)) { - /* Only way this could happen is if we're given a bad cert */ - sslErrorLog("sslCertSignerAlg() bad sigAlg OID\n"); - ortn = errSecParam; - goto errOut; - } - - /* - * OK we have the full signature algorithm as a CSSM_ALGORITHMS. - * Extract the core signature alg. - */ - switch(sigAlg) { - case CSSM_ALGID_RSA: - case CSSM_ALGID_MD2WithRSA: - case CSSM_ALGID_MD5WithRSA: - case CSSM_ALGID_SHA1WithRSA: - case CSSM_ALGID_SHA224WithRSA: - case CSSM_ALGID_SHA256WithRSA: - case CSSM_ALGID_SHA384WithRSA: - case CSSM_ALGID_SHA512WithRSA: - *signerAlg = CSSM_ALGID_RSA; - break; - case CSSM_ALGID_SHA1WithECDSA: - case CSSM_ALGID_SHA224WithECDSA: - case CSSM_ALGID_SHA256WithECDSA: - case CSSM_ALGID_SHA384WithECDSA: - case CSSM_ALGID_SHA512WithECDSA: - case CSSM_ALGID_ECDSA: - case CSSM_ALGID_ECDSA_SPECIFIED: - *signerAlg = CSSM_ALGID_ECDSA; - break; - case CSSM_ALGID_DSA: - case CSSM_ALGID_SHA1WithDSA: - *signerAlg = CSSM_ALGID_DSA; - break; - default: - sslErrorLog("sslCertSignerAlg() unknown sigAlg\n"); - ortn = errSecParam; - break; - } -errOut: - SecCertificateReleaseFirstFieldValue(certRef, - &CSSMOID_X509V1SignatureAlgorithm, fieldPtr); - 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 errSecParam; - } - if(CFGetTypeID(identity) != SecIdentityGetTypeID()) { - sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); - return errSecParam; - } - - /* - * 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; certnext = certChain; - certChain = thisSslCert; - } - - /* SUCCESS */ - *destCert = certChain; - return errSecSuccess; - - /* free certChain, everything in it, other vars, return ortn */ - sslDeleteCertificateChain(certChain, ctx); - /* FIXME - anything else? */ - return ortn; -} - -#else /* !USE_SSLCERTIFICATE */ - -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 */ - - 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 = 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. */ - certChain = CFArrayCreateMutable(kCFAllocatorDefault, numCerts, - &kCFTypeArrayCallBacks); - if (!certChain) { - ortn = errSecAllocate; - 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 = errSecParam; - goto errOut; - } - if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) { - sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); - ortn = errSecParam; - goto errOut; - } - - CFArrayAppendValue(certChain, intermediate); - } - - /* Obtain public key from cert */ -#if TARGET_OS_IPHONE - 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; - } - - -#if !TARGET_OS_IPHONE - /* This is not required on iOS, but still required on osx */ - SecTrustResultType trustResult; - ortn = SecTrustEvaluate(trust, &trustResult); - if (ortn) { - sslErrorLog("parseIncomingCerts: SecTrustEvaluate err %d\n", - (int)ortn); - goto errOut; - } -#endif - - - pubKey = SecTrustCopyPublicKey(trust); - if (!pubKey) { - /* We parsed the private key succesfully but could not get the public key: return an error */ - sslErrorLog("parseIncomingCerts: SecTrustCopyPublicKey failed\n"); - ortn = errSecParam; - 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; -} -#endif /* !USE_SSLCERTIFICATE */