]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_ssl/lib/sslCrypto.c
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_ssl / lib / sslCrypto.c
diff --git a/libsecurity_ssl/lib/sslCrypto.c b/libsecurity_ssl/lib/sslCrypto.c
deleted file mode 100644 (file)
index b6ad13e..0000000
+++ /dev/null
@@ -1,1269 +0,0 @@
-/*
- * Copyright (c) 2006-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@
- */
-
-/*
- * sslCrypto.c - interface between SSL and crypto libraries
- */
-
-#include "sslCrypto.h"
-
-#include "CipherSuite.h"
-#include "ssl.h"
-#include "sslContext.h"
-#include "sslMemory.h"
-#include "sslUtils.h"
-#include "sslDebug.h"
-#include <libDER/DER_CertCrl.h>
-#include <libDER/DER_Keys.h>
-#include <CoreFoundation/CFString.h>
-#include <Security/SecKey.h>
-#include <Security/SecKeyPriv.h>
-#include <corecrypto/ccdh.h>
-#include <corecrypto/ccec.h>
-#include <corecrypto/ccrng.h>
-#include <Security/SecCertificate.h>
-#include <Security/SecPolicy.h>
-#include <Security/SecTrust.h>
-#include <AssertMacros.h>
-#include "utilities/SecCFRelease.h"
-
-#if TARGET_OS_IPHONE
-#include <Security/SecKeyInternal.h>
-#include <Security/SecRSAKey.h>
-#include <Security/SecECKey.h>
-#endif
-
-#ifndef        _SSL_KEYCHAIN_H_
-#include "sslKeychain.h"
-#endif
-
-#if APPLE_DH
-#include <libDER/libDER.h>
-#include <libDER/DER_Keys.h>
-#include <libDER/DER_Encode.h>
-#include <libDER/asn1Types.h>
-#include <Security/SecRandom.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#if TARGET_OS_IPHONE
-#define CCRNGSTATE ccrng_seckey
-#else
-/* extern struct ccrng_state *ccDRBGGetRngState(); */
-#include <CommonCrypto/CommonRandomSPI.h>
-#define CCRNGSTATE ccDRBGGetRngState()
-#endif
-
-
-/*
- * Free a pubKey object.
- */
-extern OSStatus sslFreePubKey(SSLPubKey **pubKey)
-{
-       if (pubKey && *pubKey) {
-               CFReleaseNull(SECKEYREF(*pubKey));
-       }
-       return errSecSuccess;
-}
-
-/*
- * Free a privKey object.
- */
-extern OSStatus sslFreePrivKey(SSLPrivKey **privKey)
-{
-       if (privKey && *privKey) {
-               CFReleaseNull(SECKEYREF(*privKey));
-       }
-       return errSecSuccess;
-}
-
-/*
- * Get algorithm id for a SSLPubKey object.
- */
-CFIndex sslPubKeyGetAlgorithmID(SSLPubKey *pubKey)
-{
-#if TARGET_OS_IPHONE
-       return SecKeyGetAlgorithmID(SECKEYREF(pubKey));
-#else
-       return SecKeyGetAlgorithmId(SECKEYREF(pubKey));
-#endif
-}
-
-/*
- * Get algorithm id for a SSLPrivKey object.
- */
-CFIndex sslPrivKeyGetAlgorithmID(SSLPrivKey *privKey)
-{
-#if TARGET_OS_IPHONE
-       return SecKeyGetAlgorithmID(SECKEYREF(privKey));
-#else
-       return SecKeyGetAlgorithmId(SECKEYREF(privKey));
-#endif
-}
-
-/*
- * Raw RSA/DSA sign/verify.
- */
-OSStatus sslRawSign(
-       SSLContext                      *ctx,
-       SSLPrivKey          *privKey,
-       const uint8_t       *plainText,
-       size_t              plainTextLen,
-       uint8_t                         *sig,                   // mallocd by caller; RETURNED
-       size_t              sigLen,         // available
-       size_t              *actualBytes)   // RETURNED
-{
-#if 0
-       RSAStatus rsaStatus;
-#if RSA_SIG_SHARE_GIANT
-       RSASignBuffer *signBuffer = (RSASignBuffer *)sig;
-       assert(sigLen >= sizeof(RSASignBuffer));
-#endif
-       assert(actualBytes != NULL);
-
-       /* @@@ Shouldn't need to init giSigLen according to libgRSA docs. */
-       gi_uint16 giSigLen = sigLen;
-
-       rsaStatus = RSA_Sign(&privKey->rsaKey,
-               RP_PKCS1,
-               plainText,
-               plainTextLen,
-#if RSA_SIG_SHARE_GIANT
-               signBuffer,
-#else
-               sig,
-#endif
-               &giSigLen);
-       *actualBytes = giSigLen;
-
-       return rsaStatus ? rsaStatusToSSL(rsaStatus) : errSecSuccess;
-#else
-
-       size_t inOutSigLen = sigLen;
-
-       assert(actualBytes != NULL);
-
-    OSStatus status = SecKeyRawSign(SECKEYREF(privKey), kSecPaddingPKCS1,
-        plainText, plainTextLen, sig, &inOutSigLen);
-
-       if (status) {
-               sslErrorLog("sslRawSign: SecKeyRawSign failed (error %d)\n", (int)status);
-       }
-
-    /* Since the KeyExchange already allocated modulus size bytes we'll
-        use all of them.  SecureTransport has always sent that many bytes,
-        so we're not going to deviate, to avoid interoperability issues. */
-    if (!status && (inOutSigLen < sigLen)) {
-        size_t offset = sigLen - inOutSigLen;
-        memmove(sig + offset, sig, inOutSigLen);
-        memset(sig, 0, offset);
-        inOutSigLen = sigLen;
-    }
-
-
-       *actualBytes = inOutSigLen;
-       return status;
-#endif
-}
-
-/* TLS 1.2 RSA signature */
-OSStatus sslRsaSign(
-                    SSLContext                 *ctx,
-                    SSLPrivKey          *privKey,
-                    const SecAsn1AlgId  *algId,
-                    const uint8_t       *plainText,
-                    size_t              plainTextLen,
-                    uint8_t                            *sig,                   // mallocd by caller; RETURNED
-                    size_t              sigLen,         // available
-                    size_t              *actualBytes)   // RETURNED
-{
-       size_t inOutSigLen = sigLen;
-
-       assert(actualBytes != NULL);
-
-    OSStatus status = SecKeySignDigest(SECKEYREF(privKey), algId,
-                                    plainText, plainTextLen, sig, &inOutSigLen);
-
-       if (status) {
-               sslErrorLog("sslRsaSign: SecKeySignDigest failed (error %d)\n", (int) status);
-       }
-
-    /* Since the KeyExchange already allocated modulus size bytes we'll
-     use all of them.  SecureTransport has always sent that many bytes,
-     so we're not going to deviate, to avoid interoperability issues. */
-    if (!status && (inOutSigLen < sigLen)) {
-        size_t offset = sigLen - inOutSigLen;
-        memmove(sig + offset, sig, inOutSigLen);
-        memset(sig, 0, offset);
-        inOutSigLen = sigLen;
-    }
-
-       *actualBytes = inOutSigLen;
-       return status;
-}
-
-OSStatus sslRawVerify(
-       SSLContext                      *ctx,
-       SSLPubKey           *pubKey,
-       const uint8_t       *plainText,
-       size_t              plainTextLen,
-       const uint8_t       *sig,
-       size_t              sigLen)         // available
-{
-#if 0
-       RSAStatus rsaStatus;
-
-       rsaStatus = RSA_SigVerify(&pubKey->rsaKey,
-               RP_PKCS1,
-               plainText,
-               plainTextLen,
-               sig,
-               sigLen);
-
-       return rsaStatus ? rsaStatusToSSL(rsaStatus) : errSecSuccess;
-#else
-       OSStatus status = SecKeyRawVerify(SECKEYREF(pubKey), kSecPaddingPKCS1,
-        plainText, plainTextLen, sig, sigLen);
-
-       if (status) {
-               sslErrorLog("sslRawVerify: SecKeyRawVerify failed (error %d)\n", (int) status);
-       }
-
-       return status;
-#endif
-}
-
-/* TLS 1.2 RSA verify */
-OSStatus sslRsaVerify(
-                      SSLContext                 *ctx,
-                      SSLPubKey           *pubKey,
-                      const SecAsn1AlgId  *algId,
-                      const uint8_t       *plainText,
-                      size_t              plainTextLen,
-                      const uint8_t       *sig,
-                      size_t              sigLen)         // available
-{
-       OSStatus status = SecKeyVerifyDigest(SECKEYREF(pubKey), algId,
-                           plainText, plainTextLen, sig, sigLen);
-
-       if (status) {
-               sslErrorLog("sslRsaVerify: SecKeyVerifyDigest failed (error %d)\n", (int) status);
-       }
-
-       return status;
-}
-
-/*
- * Encrypt/Decrypt
- */
-OSStatus sslRsaEncrypt(
-       SSLContext                      *ctx,
-       SSLPubKey           *pubKey,
-       const uint32_t          padding,
-       const uint8_t       *plainText,
-       size_t              plainTextLen,
-       uint8_t                         *cipherText,            // mallocd by caller; RETURNED
-       size_t              cipherTextLen,      // available
-       size_t              *actualBytes)       // RETURNED
-{
-#if 0
-       gi_uint16 giCipherTextLen = cipherTextLen;
-       RSAStatus rsaStatus;
-
-       assert(actualBytes != NULL);
-
-       rsaStatus = RSA_Encrypt(&pubKey->rsaKey,
-               RP_PKCS1,
-               getRandomByte,
-               plainText,
-               plainTextLen,
-               cipherText,
-               &giCipherTextLen);
-       *actualBytes = giCipherTextLen;
-
-       return rsaStatus ? rsaStatusToSSL(rsaStatus) : errSecSuccess;
-#else
-    size_t ctlen = cipherTextLen;
-
-       assert(actualBytes != NULL);
-
-#if RSA_PUB_KEY_USAGE_HACK
-       /* Force key usage to allow encryption with public key */
-       #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
-       CSSM_KEY *cssmKey = NULL;
-       if (SecKeyGetCSSMKey(SECKEYREF(pubKey), (const CSSM_KEY **)&cssmKey)==errSecSuccess && cssmKey)
-               cssmKey->KeyHeader.KeyUsage |= CSSM_KEYUSE_ENCRYPT;
-       #endif
-#endif
-
-    OSStatus status = SecKeyEncrypt(SECKEYREF(pubKey), padding,
-        plainText, plainTextLen, cipherText, &ctlen);
-
-       if (status) {
-               sslErrorLog("sslRsaEncrypt: SecKeyEncrypt failed (error %d)\n", (int)status);
-       }
-
-    /* Since the KeyExchange already allocated modulus size bytes we'll
-        use all of them.  SecureTransport has always sent that many bytes,
-        so we're not going to deviate, to avoid interoperability issues. */
-    if (!status && (ctlen < cipherTextLen)) {
-        size_t offset = cipherTextLen - ctlen;
-        memmove(cipherText + offset, cipherText, ctlen);
-        memset(cipherText, 0, offset);
-        ctlen = cipherTextLen;
-    }
-
-    if (actualBytes)
-        *actualBytes = ctlen;
-
-    if (status) {
-        sslErrorLog("***sslRsaEncrypt: error %d\n", (int)status);
-    }
-    return status;
-#endif
-}
-
-OSStatus sslRsaDecrypt(
-       SSLContext                      *ctx,
-       SSLPrivKey                      *privKey,
-       const uint32_t          padding,
-       const uint8_t       *cipherText,
-       size_t              cipherTextLen,
-       uint8_t                         *plainText,                     // mallocd by caller; RETURNED
-       size_t              plainTextLen,               // available
-       size_t              *actualBytes)               // RETURNED
-{
-#if 0
-       gi_uint16 giPlainTextLen = plainTextLen;
-       RSAStatus rsaStatus;
-
-       assert(actualBytes != NULL);
-
-       rsaStatus = RSA_Decrypt(&privKey->rsaKey,
-               RP_PKCS1,
-               cipherText,
-               cipherTextLen,
-               plainText,
-               &giPlainTextLen);
-       *actualBytes = giPlainTextLen;
-
-       return rsaStatus ? rsaStatusToSSL(rsaStatus) : errSecSuccess;
-#else
-       size_t ptlen = plainTextLen;
-
-       assert(actualBytes != NULL);
-
-    OSStatus status = SecKeyDecrypt(SECKEYREF(privKey), padding,
-        cipherText, cipherTextLen, plainText, &ptlen);
-       *actualBytes = ptlen;
-
-    if (status) {
-        sslErrorLog("sslRsaDecrypt: SecKeyDecrypt failed (error %d)\n", (int)status);
-       }
-
-       return status;
-#endif
-}
-
-/*
- * Obtain size of the modulus of privKey in bytes.
- */
-size_t sslPrivKeyLengthInBytes(SSLPrivKey *privKey)
-{
-#if 0
-       /* Get the length of p + q (which is the size of the modulus) in bits. */
-       gi_uint16 bitLen = bitlen(&privKey->rsaKey.p.g) +
-               bitlen(&privKey->rsaKey.q.g);
-       /* Convert it to bytes. */
-       return (bitLen + 7) / 8;
-#else
-    return SecKeyGetBlockSize(SECKEYREF(privKey));
-#endif
-}
-
-/*
- * Obtain size of the modulus of pubKey in bytes.
- */
-size_t sslPubKeyLengthInBytes(SSLPubKey *pubKey)
-{
-#if 0
-       /* Get the length of the modulus in bytes. */
-       return giantNumBytes(&pubKey->rsaKey.n.g);
-#else
-    return SecKeyGetBlockSize(SECKEYREF(pubKey));
-#endif
-}
-
-
-/*
- * Obtain maximum size of signature in bytes. A bit of a kludge; we could
- * ask the CSP to do this but that would be kind of expensive.
- */
-OSStatus sslGetMaxSigSize(
-       SSLPrivKey *privKey,
-       size_t           *maxSigSize)
-{
-       assert(maxSigSize != NULL);
-
-#if 0
-#if RSA_SIG_SHARE_GIANT
-       *maxSigSize = sizeof(RSASignBuffer);
-#else
-       *maxSigSize = MAX_PRIME_SIZE_BYTES;
-#endif
-#else
-    *maxSigSize = SecKeyGetBlockSize(SECKEYREF(privKey));
-#endif
-
-       return errSecSuccess;
-}
-
-#if 0
-static OSStatus sslGiantToBuffer(
-       SSLContext                      *ctx,                   // Currently unused.
-       giant g,
-       SSLBuffer *buffer)
-{
-       gi_uint8 *chars;
-       gi_uint16 ioLen;
-       gi_uint16 zeroCount;
-       GIReturn giReturn;
-       OSStatus status;
-
-       ioLen = serializeGiantBytes(g);
-       status = SSLAllocBuffer(buffer, ioLen);
-       if (status)
-               return status;
-       chars = buffer->data;
-
-       /* Serialize the giant g into chars. */
-       giReturn = serializeGiant(g, chars, &ioLen);
-       if(giReturn) {
-               SSLFreeBuffer(buffer);
-               return giReturnToSSL(giReturn);
-       }
-
-       /* Trim off leading zeroes (but leave one zero if that's all there is). */
-       for (zeroCount = 0; zeroCount < (ioLen - 1); ++zeroCount)
-               if (chars[zeroCount])
-                       break;
-
-       if (zeroCount > 0) {
-               buffer->length = ioLen - zeroCount;
-               memmove(chars, chars + zeroCount, buffer->length);
-       }
-
-       return status;
-}
-
-/*
- * Get raw key bits from an RSA public key.
- */
-OSStatus sslGetPubKeyBits(
-       SSLContext                      *ctx,                   // Currently unused.
-       SSLPubKey           *pubKey,
-       SSLBuffer                       *modulus,               // data mallocd and RETURNED
-       SSLBuffer                       *exponent)              // data mallocd and RETURNED
-{
-       OSStatus status;
-
-       status = sslGiantToBuffer(ctx, &pubKey->rsaKey.n.g, modulus);
-       if(status)
-               return status;
-
-       status = sslGiantToBuffer(ctx, &pubKey->rsaKey.e.g, exponent);
-       if(status) {
-               SSLFreeBuffer(modulus);
-               return status;
-       }
-
-       return status;
-}
-#endif
-
-/*
- * Given raw RSA key bits, cook up a SSLPubKey. Used in
- * Server-initiated key exchange.
- */
-OSStatus sslGetPubKeyFromBits(
-       SSLContext                      *ctx,
-       const SSLBuffer         *modulus,
-       const SSLBuffer         *exponent,
-       SSLPubKey           **pubKey)        // mallocd and RETURNED
-{
-       if (!pubKey)
-               return errSecParam;
-#if 0
-       SSLPubKey *key;
-       RSAStatus rsaStatus;
-       RSAPubKey apiKey = {
-               modulus->data, modulus->length,
-               NULL, 0,
-               exponent->data, exponent->length
-       };
-
-       key = sslMalloc(sizeof(*key));
-       rsaStatus = rsaInitPubGKey(&apiKey, &key->rsaKey);
-       if (rsaStatus) {
-               sslFree(key);
-               return rsaStatusToSSL(rsaStatus);
-       }
-
-       *pubKey = key;
-       return errSecSuccess;
-#else
-       check(pubKey);
-       SecRSAPublicKeyParams params = {
-               modulus->data, modulus->length,
-               exponent->data, exponent->length
-       };
-#if SSL_DEBUG
-       sslDebugLog("Creating RSA pub key from modulus=%p len=%lu exponent=%p len=%lu\n",
-                       modulus->data, modulus->length,
-                       exponent->data, exponent->length);
-#endif
-       SecKeyRef key = SecKeyCreateRSAPublicKey(NULL, (const uint8_t *)&params,
-                       sizeof(params), kSecKeyEncodingRSAPublicParams);
-       if (!key) {
-               sslErrorLog("sslGetPubKeyFromBits: SecKeyCreateRSAPublicKey failed\n");
-               return errSSLCrypto;
-       }
-#if SSL_DEBUG
-       sslDebugLog("sslGetPubKeyFromBits: RSA pub key block size=%lu\n", SecKeyGetBlockSize(key));
-#endif
-       *pubKey = (SSLPubKey*)key;
-       return errSecSuccess;
-#endif
-}
-
-// MARK: -
-// MARK: Public Certificate Functions
-
-#ifdef USE_SSLCERTIFICATE
-
-/*
- * Given a SSLCertificate cert, obtain its public key as a SSLPubKey.
- * Caller must sslFreePubKey and free the SSLPubKey itself.
- */
-OSStatus sslPubKeyFromCert(
-       SSLContext                              *ctx,
-       const SSLCertificate    *cert,
-       SSLPubKey               **pubKey)               // RETURNED
-{
-    DERItem der;
-    DERSignedCertCrl signedCert;
-    DERTBSCert tbsCert;
-       DERSubjPubKeyInfo pubKeyInfo;
-       DERByte numUnused;
-    DERItem pubKeyPkcs1;
-    SSLPubKey *key;
-       DERReturn drtn;
-    RSAStatus rsaStatus;
-
-    assert(cert);
-       assert(pubKey != NULL);
-
-    der.data = cert->derCert.data;
-    der.length = cert->derCert.length;
-
-       /* top level decode */
-       drtn = DERParseSequence(&der, DERNumSignedCertCrlItemSpecs,
-               DERSignedCertCrlItemSpecs, &signedCert, sizeof(signedCert));
-       if(drtn)
-               return errSSLBadCert;
-
-       /* decode the TBSCert - it was saved in full DER form */
-       drtn = DERParseSequence(&signedCert.tbs,
-               DERNumTBSCertItemSpecs, DERTBSCertItemSpecs,
-               &tbsCert, sizeof(tbsCert));
-       if(drtn)
-               return errSSLBadCert;
-
-       /* sequence we're given: encoded DERSubjPubKeyInfo */
-       drtn = DERParseSequenceContent(&tbsCert.subjectPubKey,
-               DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs,
-               &pubKeyInfo, sizeof(pubKeyInfo));
-       if(drtn)
-               return errSSLBadCert;
-
-       /* @@@ verify that this is an RSA key by decoding the AlgId */
-
-       /*
-        * The contents of pubKeyInfo.pubKey is a bit string whose contents
-        * are a PKCS1 format RSA key.
-        */
-       drtn = DERParseBitString(&pubKeyInfo.pubKey, &pubKeyPkcs1, &numUnused);
-       if(drtn)
-               return errSSLBadCert;
-
-#if TARGET_OS_IPHONE
-    /* Now we have the public key in pkcs1 format.  Let's make a public key
-       object out of it. */
-    key = sslMalloc(sizeof(*key));
-    rsaStatus = RSA_DecodePubKey(pubKeyPkcs1.data, pubKeyPkcs1.length,
-        &key->rsaKey);
-       if (rsaStatus) {
-               sslFree(key);
-       }
-#else
-       SecKeyRef rsaPubKeyRef = SecKeyCreateRSAPublicKey(NULL,
-               pubKeyPkcs1.data, pubKeyPkcs1.length,
-               kSecKeyEncodingRSAPublicParams);
-       rsaStatus = (rsaPubKeyRef) ? 0 : 1;
-       key = (SSLPubKey*)rsaPubKeyRef;
-#endif
-       if (rsaStatus) {
-               return rsaStatusToSSL(rsaStatus);
-       }
-
-       *pubKey = key;
-       return errSecSuccess;
-}
-
-/*
- * Verify a chain of DER-encoded certs.
- * First cert in a chain is root; this must also be present
- * in ctx->trustedCerts.
- *
- * If arePeerCerts is true, host name verification is enabled and we
- * save the resulting SecTrustRef in ctx->peerSecTrust. Otherwise
- * we're just validating our own certs; no host name checking and
- * peerSecTrust is transient.
- */
- OSStatus sslVerifyCertChain(
-       SSLContext                              *ctx,
-       const SSLCertificate    *certChain,
-       bool                                    arePeerCerts)
-{
-       OSStatus ortn = errSecSuccess;
-
-    assert(certChain);
-
-    /* No point checking our own certs, our clients can do that. */
-    if (!arePeerCerts)
-        return errSecSuccess;
-
-    CertVerifyReturn cvrtn;
-    /* @@@ Add real cert checking. */
-    if (certChain->next) {
-        DERItem subject, issuer;
-
-        issuer.data = certChain->derCert.data;
-        issuer.length = certChain->derCert.length;
-        subject.data = certChain->next->derCert.data;
-        subject.length = certChain->next->derCert.length;
-        cvrtn = certVerify(&subject, &issuer);
-        if (cvrtn != CVR_Success)
-            ortn = errSSLBadCert;
-    }
-    else
-    {
-               sslErrorLog("***sslVerifyCertChain: only one cert in chain\n");
-    }
-       return ortn;
-}
-
-#else /* !USE_SSLCERTIFICATE */
-
-OSStatus
-sslCreateSecTrust(
-       SSLContext                              *ctx,
-       CFArrayRef                              certChain,
-       bool                                    arePeerCerts,
-    SecTrustRef             *pTrust)   /* RETURNED */
-{
-       OSStatus status = errSecAllocate;
-       CFStringRef peerDomainName = NULL;
-       CFTypeRef policies = NULL;
-       SecTrustRef trust = NULL;
-
-    if (CFArrayGetCount(certChain) == 0) {
-               status = errSSLBadCert;
-               goto errOut;
-       }
-
-       if (arePeerCerts) {
-               if (ctx->peerDomainNameLen && ctx->peerDomainName) {
-                       CFIndex len = ctx->peerDomainNameLen;
-                       if (ctx->peerDomainName[len - 1] == 0) {
-                               len--;
-                               //secwarning("peerDomainName is zero terminated!");
-                       }
-                       /* @@@ Double check that this is the correct encoding. */
-                       require(peerDomainName = CFStringCreateWithBytes(kCFAllocatorDefault,
-                               (const UInt8 *)ctx->peerDomainName, len,
-                               kCFStringEncodingUTF8, false), errOut);
-               }
-       }
-    /* If we are the client, our peer certificates must satisfy the
-       ssl server policy. */
-    bool server = ctx->protocolSide == kSSLClientSide;
-       require(policies = SecPolicyCreateSSL(server, peerDomainName), errOut);
-
-       require_noerr(status = SecTrustCreateWithCertificates(certChain, policies,
-               &trust), errOut);
-
-       /* If we have trustedAnchors we set them here. */
-    if (ctx->trustedCerts) {
-        require_noerr(status = SecTrustSetAnchorCertificates(trust,
-            ctx->trustedCerts), errOut);
-        require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust,
-            ctx->trustedCertsOnly), errOut);
-    }
-
-    status = errSecSuccess;
-
-errOut:
-       CFReleaseSafe(peerDomainName);
-       CFReleaseSafe(policies);
-
-       *pTrust = trust;
-
-       return status;
-}
-
-/* Return the first certificate reference from the supplied array
- * whose data matches the given certificate, or NULL if none match.
- */
-static
-SecCertificateRef
-sslGetMatchingCertInArray(
-       SecCertificateRef       certRef,
-       CFArrayRef                      certArray)
-{
-       SecCertificateRef matchedCert = NULL;
-
-       if (certRef == NULL || certArray == NULL) {
-               return NULL;
-       }
-
-       CFDataRef certData = SecCertificateCopyData(certRef);
-       if (certData) {
-               CFIndex idx, count = CFArrayGetCount(certArray);
-               for(idx=0; idx<count; idx++) {
-                       SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(certArray, idx);
-                       CFDataRef aData = SecCertificateCopyData(aCert);
-                       if (aData && CFEqual(aData, certData)) {
-                               matchedCert = aCert;
-                       }
-                       CFReleaseSafe(aData);
-                       if (matchedCert)
-                               break;
-               }
-               CFReleaseSafe(certData);
-       }
-
-    return matchedCert;
-}
-
-/*
- * Verify a chain of DER-encoded certs.
- * Last cert in a chain is the leaf; this must also be present
- * in ctx->trustedCerts.
- *
- * If arePeerCerts is true, host name verification is enabled and we
- * save the resulting SecTrustRef in ctx->peerSecTrust. Otherwise
- * we're just validating our own certs; no host name checking and
- * peerSecTrust is transient.
- */
-extern OSStatus sslVerifyCertChain(
-       SSLContext                              *ctx,
-       CFArrayRef                              certChain,
-       bool                                    arePeerCerts)
-{
-       OSStatus status;
-       SecTrustRef trust = NULL;
-
-    assert(certChain);
-
-    if (arePeerCerts) {
-               /* renegotiate - start with a new SecTrustRef */
-        CFReleaseNull(ctx->peerSecTrust);
-    }
-
-       status = sslCreateSecTrust(ctx, certChain, arePeerCerts, &trust);
-
-       if (!ctx->enableCertVerify) {
-               /* trivial case, this is caller's responsibility */
-               status = errSecSuccess;
-               goto errOut;
-       }
-
-       SecTrustResultType secTrustResult;
-       require_noerr(status = SecTrustEvaluate(trust, &secTrustResult), errOut);
-       switch (secTrustResult) {
-        case kSecTrustResultUnspecified:
-            /* cert chain valid, no special UserTrust assignments */
-        case kSecTrustResultProceed:
-            /* cert chain valid AND user explicitly trusts this */
-            status = errSecSuccess;
-            break;
-        case kSecTrustResultDeny:
-        case kSecTrustResultConfirm:
-        case kSecTrustResultRecoverableTrustFailure:
-        default:
-            if(ctx->allowAnyRoot) {
-                sslErrorLog("***Warning: accepting unverified cert chain\n");
-                status = errSecSuccess;
-            }
-            else {
-                               /*
-                                * If the caller provided a list of trusted leaf certs, check them here
-                                */
-                               if(ctx->trustedLeafCerts) {
-                                       if (sslGetMatchingCertInArray((SecCertificateRef)CFArrayGetValueAtIndex(certChain, 0),
-                                                               ctx->trustedLeafCerts)) {
-                                               status = errSecSuccess;
-                                               goto errOut;
-                                       }
-                               }
-                               status = errSSLXCertChainInvalid;
-            }
-            /* Do we really need to return things like:
-                   errSSLNoRootCert
-                   errSSLUnknownRootCert
-                   errSSLCertExpired
-                   errSSLCertNotYetValid
-                   errSSLHostNameMismatch
-               for our client to see what went wrong, or should we just always
-               return
-                   errSSLXCertChainInvalid
-               when something is wrong? */
-            break;
-       }
-
-errOut:
-       if (arePeerCerts)
-               ctx->peerSecTrust = trust;
-       else
-        CFReleaseSafe(trust);
-
-       return status;
-}
-
-/*
- * Given a SecCertificateRef cert, obtain its public key as a SSLPubKey.
- * Caller must sslFreePubKey and free the SSLPubKey itself.
- */
-extern OSStatus sslCopyPeerPubKey(
-       SSLContext                              *ctx,
-       SSLPubKey               **pubKey)
-{
-    check(pubKey);
-    check(ctx->peerSecTrust);
-
-    SecKeyRef key = SecTrustCopyPublicKey(ctx->peerSecTrust);
-    if (!key) {
-               sslErrorLog("sslCopyPeerPubKey: %s, ctx->peerSecTrust=%p\n",
-                       "SecTrustCopyPublicKey failed", ctx->peerSecTrust);
-               return errSSLBadCert;
-       }
-    *pubKey = (SSLPubKey*)key;
-
-    return errSecSuccess;
-}
-
-#endif /* !USE_SSLCERTIFICATE */
-
-#ifndef        NDEBUG
-void stPrintCdsaError(const char *op, OSStatus crtn)
-{
-       assert(FALSE);
-}
-#endif
-
-/*
- * After ciphersuite negotiation is complete, verify that we have
- * the capability of actually performing the selected cipher.
- * Currently we just verify that we have a cert and private signing
- * key, if needed, and that the signing key's algorithm matches the
- * expected key exchange method.
- *
- * This is currently called from FindCipherSpec(), after it sets
- * ctx->selectedCipherSpec to a (supposedly) valid value, and from
- * sslBuildCipherSpecArray(), in server mode (pre-negotiation) only.
- */
-OSStatus sslVerifySelectedCipher(SSLContext *ctx)
-{
-    if(ctx->protocolSide == kSSLClientSide) {
-        return errSecSuccess;
-    }
-#if SSL_PAC_SERVER_ENABLE
-    if((ctx->masterSecretCallback != NULL) &&
-       (ctx->sessionTicket.data != NULL)) {
-            /* EAP via PAC resumption; we can do it */
-       return errSecSuccess;
-    }
-#endif /* SSL_PAC_SERVER_ENABLE */
-
-    CFIndex requireAlg;
-    switch (ctx->selectedCipherSpecParams.keyExchangeMethod) {
-        case SSL_RSA:
-        case SSL_RSA_EXPORT:
-       case SSL_DH_RSA:
-       case SSL_DH_RSA_EXPORT:
-       case SSL_DHE_RSA:
-       case SSL_DHE_RSA_EXPORT:
-            requireAlg = kSecRSAAlgorithmID;
-            break;
-       case SSL_DHE_DSS:
-       case SSL_DHE_DSS_EXPORT:
-       case SSL_DH_DSS:
-       case SSL_DH_DSS_EXPORT:
-            requireAlg = kSecDSAAlgorithmID;
-            break;
-       case SSL_DH_anon:
-       case SSL_DH_anon_EXPORT:
-        case TLS_PSK:
-            requireAlg = kSecNullAlgorithmID; /* no signing key */
-            break;
-        /*
-         * When SSL_ECDSA_SERVER is true and we support ECDSA on the server side,
-         * we'll need to add some logic here...
-         */
-#if SSL_ECDSA_SERVER
-        case SSL_ECDHE_ECDSA:
-        case SSL_ECDHE_RSA:
-        case SSL_ECDH_ECDSA:
-        case SSL_ECDH_RSA:
-        case SSL_ECDH_anon:
-            requireAlg = kSecECDSAAlgorithmID;
-            break;
-#endif
-
-       default:
-            /* needs update per cipherSpecs.c */
-            assert(0);
-            sslErrorLog("sslVerifySelectedCipher: unknown key exchange method\n");
-            return errSSLInternal;
-    }
-
-    if(requireAlg == kSecNullAlgorithmID) {
-       return errSecSuccess;
-    }
-
-    /* private signing key required */
-    if(ctx->signingPrivKeyRef == NULL) {
-       sslErrorLog("sslVerifySelectedCipher: no signing key\n");
-       return errSSLBadConfiguration;
-    }
-
-    /* Check the alg of our signing key. */
-    CFIndex keyAlg = sslPrivKeyGetAlgorithmID(ctx->signingPrivKeyRef);
-    if (requireAlg != keyAlg) {
-       sslErrorLog("sslVerifySelectedCipher: signing key alg mismatch\n");
-       return errSSLBadConfiguration;
-    }
-
-    return errSecSuccess;
-}
-
-#if APPLE_DH
-
-/* FIXME: This is duplicated in SecDH */
-typedef struct {
-       DERItem                         p;
-       DERItem                         g;
-       DERItem                         l;
-} DER_DHParams;
-
-static const DERItemSpec DER_DHParamsItemSpecs[] =
-{
-       { DER_OFFSET(DER_DHParams, p),
-        ASN1_INTEGER,
-        DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT },
-       { DER_OFFSET(DER_DHParams, g),
-        ASN1_INTEGER,
-        DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT },
-       { DER_OFFSET(DER_DHParams, l),
-        ASN1_INTEGER,
-        DER_DEC_OPTIONAL | DER_ENC_SIGNED_INT },
-};
-static const DERSize DER_NumDHParamsItemSpecs =
-sizeof(DER_DHParamsItemSpecs) / sizeof(DERItemSpec);
-
-/* Max encoded size for standard (PKCS3) parameters */
-#define DH_ENCODED_PARAM_SIZE(primeSizeInBytes)                                        \
-DER_MAX_ENCODED_SIZE(                                                                          \
-DER_MAX_ENCODED_SIZE(primeSizeInBytes) +               /* g */         \
-DER_MAX_ENCODED_SIZE(primeSizeInBytes) +               /* p */     \
-DER_MAX_ENCODED_SIZE(4))                        /* l */
-
-
-OSStatus sslDecodeDhParams(
-       const SSLBuffer *blob,                  /* Input - PKCS-3 encoded */
-       SSLBuffer               *prime,                 /* Output - wire format */
-       SSLBuffer               *generator)     /* Output - wire format */
-{
-    OSStatus ortn = errSecSuccess;
-    DERReturn drtn;
-       DERItem paramItem = {(DERByte *)blob->data, blob->length};
-       DER_DHParams decodedParams;
-
-    drtn = DERParseSequence(&paramItem,
-                            DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs,
-                            &decodedParams, sizeof(decodedParams));
-    if(drtn)
-        return drtn;
-
-    prime->data = decodedParams.p.data;
-    prime->length = decodedParams.p.length;
-
-    generator->data = decodedParams.g.data;
-    generator->length = decodedParams.g.length;
-
-    return ortn;
-}
-
-
-OSStatus sslEncodeDhParams(SSLBuffer        *blob,                     /* data mallocd and RETURNED PKCS-3 encoded */
-                           const SSLBuffer     *prime,                 /* Wire format */
-                           const SSLBuffer     *generator)     /* Wire format */
-{
-    OSStatus ortn = errSecSuccess;
-    DER_DHParams derParams =
-    {
-        .p = {
-            .length = prime->length,
-            .data = prime->data,
-        },
-        .g = {
-            .length = generator->length,
-            .data = generator->data,
-        },
-        .l = {
-            .length = 0,
-            .data = NULL,
-        }
-    };
-
-    DERSize ioLen = DH_ENCODED_PARAM_SIZE(derParams.p.length);
-    DERByte *der = sslMalloc(ioLen);
-    // FIXME: What if this fails - we should probably not have a malloc here ?
-    assert(der);
-    ortn = (OSStatus)DEREncodeSequence(ASN1_CONSTR_SEQUENCE,
-                                       &derParams,
-                                       DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs,
-                                       der,
-                                       &ioLen);
-    // This should never fail
-
-    blob->length=ioLen;
-    blob->data=der;
-
-    return ortn;
-}
-
-OSStatus sslDhCreateKey(SSLContext *ctx)
-{
-    if (ctx->secDHContext) {
-        SecDHDestroy(ctx->secDHContext);
-        ctx->secDHContext = NULL;
-    }
-
-    /* Server params are set using encoded dh params */
-    if (!(ctx->dhParamsEncoded.length && ctx->dhParamsEncoded.data))
-        return errSSLInternal;
-
-    if (SecDHCreateFromParameters(ctx->dhParamsEncoded.data,
-        ctx->dhParamsEncoded.length, &ctx->secDHContext))
-            return errSSLCrypto;
-
-    return errSecSuccess;
-}
-
-OSStatus sslDhGenerateKeyPair(SSLContext *ctx)
-{
-    OSStatus ortn = errSecSuccess;
-    
-    require_noerr(ortn = SSLAllocBuffer(&ctx->dhExchangePublic, 
-        SecDHGetMaxKeyLength(ctx->secDHContext)), out);
-    require_noerr(ortn = SecDHGenerateKeypair(ctx->secDHContext, 
-        ctx->dhExchangePublic.data, &ctx->dhExchangePublic.length), out);
-
-out:
-    return ortn;
-}
-
-
-OSStatus sslDhKeyExchange(SSLContext *ctx)
-{
-    OSStatus ortn = errSecSuccess;
-
-       if (ctx == NULL ||
-        ctx->secDHContext == NULL ||
-        ctx->dhPeerPublic.length == 0) {
-               /* comes from peer, don't panic */
-               sslErrorLog("sslDhKeyExchange: null peer public key\n");
-               return errSSLProtocol;
-       }
-
-    require_noerr(ortn = SSLAllocBuffer(&ctx->preMasterSecret, 
-        SecDHGetMaxKeyLength(ctx->secDHContext)), out);
-    require_noerr(ortn = SecDHComputeKey(ctx->secDHContext, 
-        ctx->dhPeerPublic.data, ctx->dhPeerPublic.length, 
-        ctx->preMasterSecret.data, &ctx->preMasterSecret.length), out);
-
-       return ortn;
-out:
-       sslErrorLog("sslDhKeyExchange: failed to compute key (error %d)\n", (int)ortn);
-       return ortn;
-}
-
-#endif /* APPLE_DH */
-
-/*
- * Given an ECDSA key in SecKey format, extract the SSL_ECDSA_NamedCurve
- * from its algorithm parameters.
- */
-OSStatus sslEcdsaPeerCurve(
-       SSLPubKey *pubKey,
-       SSL_ECDSA_NamedCurve *namedCurve)
-{
-    /* Cast is safe because enums are kept in sync. */
-    *namedCurve = (SSL_ECDSA_NamedCurve)SecECKeyGetNamedCurve(SECKEYREF(pubKey));
-    if (*namedCurve == kSecECCurveNone) {
-        sslErrorLog("sslEcdsaPeerCurve: no named curve for public key\n");
-        return errSSLProtocol;
-    }
-    return errSecSuccess;
-}
-
-/*
- * Generate ECDH key pair with the given SSL_ECDSA_NamedCurve.
- * Private key, in ref form, is placed in ctx->ecdhPrivate.
- * Public key, in ECPoint form - which can NOT be used as
- * a key in any CSP ops - is placed in ecdhExchangePublic.
- */
-OSStatus sslEcdhGenerateKeyPair(
-       SSLContext *ctx,
-       SSL_ECDSA_NamedCurve namedCurve)
-{
-       OSStatus ortn = errSecSuccess;
-
-    ccec_const_cp_t cp;
-       switch (namedCurve) {
-    case SSL_Curve_secp256r1:
-        cp = ccec_cp_256();
-        break;
-    case SSL_Curve_secp384r1:
-        cp = ccec_cp_384();
-        break;
-    case SSL_Curve_secp521r1:
-        cp = ccec_cp_521();
-        break;
-    default:
-        /* should not have gotten this far */
-        sslErrorLog("sslEcdhGenerateKeyPair: bad namedCurve (%u)\n",
-            (unsigned)namedCurve);
-        return errSSLInternal;
-       }
-
-    ccec_generate_key(cp, CCRNGSTATE, ctx->ecdhContext);
-    size_t pub_size = ccec_export_pub_size(ctx->ecdhContext);
-    SSLFreeBuffer(&ctx->ecdhExchangePublic);
-    require_noerr(ortn = SSLAllocBuffer(&ctx->ecdhExchangePublic,
-                                        pub_size), errOut);
-    ccec_export_pub(ctx->ecdhContext, ctx->ecdhExchangePublic.data);
-
-       sslDebugLog("sslEcdhGenerateKeyPair: pub key size=%ld, data=%p\n",
-               pub_size, ctx->ecdhExchangePublic.data);
-
-errOut:
-       return ortn;
-}
-
-/*
- * Perform ECDH key exchange. Obtained key material is the same
- * size as our private key.
- *
- * On entry, ecdhPrivate is our private key. The peer's public key
- * is either ctx->ecdhPeerPublic for ECDHE exchange, or
- * ctx->peerPubKey for ECDH exchange.
- */
-OSStatus sslEcdhKeyExchange(
-       SSLContext              *ctx,
-       SSLBuffer               *exchanged)
-{
-       OSStatus ortn = errSecSuccess;
-    CFDataRef pubKeyData = NULL;
-    const unsigned char *pubKeyBits;
-    unsigned long pubKeyLen;
-
-       switch(ctx->selectedCipherSpecParams.keyExchangeMethod) {
-               case SSL_ECDHE_ECDSA:
-               case SSL_ECDHE_RSA:
-                       /* public key passed in as CSSM_DATA *Param */
-                       if(ctx->ecdhPeerPublic.length == 0) {
-                               /* comes from peer, don't panic */
-                               sslErrorLog("sslEcdhKeyExchange: null peer public key\n");
-                               ortn = errSSLProtocol;
-                               goto errOut;
-                       }
-            pubKeyBits = ctx->ecdhPeerPublic.data;
-            pubKeyLen = ctx->ecdhPeerPublic.length;
-                       break;
-               case SSL_ECDH_ECDSA:
-               case SSL_ECDH_RSA:
-                       /* Use the public key provided by the peer. */
-                       if(ctx->peerPubKey == NULL) {
-                          sslErrorLog("sslEcdhKeyExchange: no peer key\n");
-                          ortn = errSSLInternal;
-                          goto errOut;
-                       }
-
-            pubKeyData = SecECKeyCopyPublicBits(SECKEYREF(ctx->peerPubKey));
-            if (!pubKeyData) {
-                               sslErrorLog("sslEcdhKeyExchange: SecECKeyCopyPublicBits failed\n");
-                               ortn = errSSLProtocol;
-                               goto errOut;
-            }
-            pubKeyBits = CFDataGetBytePtr(pubKeyData);
-            pubKeyLen = CFDataGetLength(pubKeyData);
-                       break;
-               default:
-                       /* shouldn't be here */
-                       sslErrorLog("sslEcdhKeyExchange: unknown keyExchangeMethod (%d)\n",
-                               ctx->selectedCipherSpecParams.keyExchangeMethod);
-                       assert(0);
-                       ortn = errSSLInternal;
-                       goto errOut;
-       }
-
-    ccec_const_cp_t cp = ccec_ctx_cp(ctx->ecdhContext);
-    ccec_pub_ctx_decl(ccn_sizeof(521), pubKey);
-    ccec_import_pub(cp, pubKeyLen, pubKeyBits, pubKey);
-    size_t len = 1 + 2 * ccec_ccn_size(cp);
-    require_noerr(ortn = SSLAllocBuffer(exchanged, len), errOut);
-    require_noerr(ccec_compute_key(ctx->ecdhContext, pubKey,  &exchanged->length, exchanged->data), errOut);
-
-       sslDebugLog("sslEcdhKeyExchange: exchanged key length=%ld, data=%p\n",
-               exchanged->length, exchanged->data);
-
-errOut:
-    CFReleaseSafe(pubKeyData);
-       return ortn;
-}