]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_ssl/lib/tls1Callouts.c
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_ssl / lib / tls1Callouts.c
diff --git a/libsecurity_ssl/lib/tls1Callouts.c b/libsecurity_ssl/lib/tls1Callouts.c
deleted file mode 100644 (file)
index 9c873f7..0000000
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * Copyright (c) 2002,2005-2007,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@
- */
-
-/*
- * tls1Callouts.c - TLSv1-specific routines for SslTlsCallouts.
- */
-
-#include "SecureTransport.h"
-
-#include "tls_ssl.h"
-#include "sslMemory.h"
-#include "sslUtils.h"
-#include "sslDigests.h"
-#include "sslAlertMessage.h"
-#include "sslCrypto.h"
-#include "sslDebug.h"
-#include "tls_hmac.h"
-#include <assert.h>
-#include <strings.h>
-
-#define TLS_ENC_DEBUG          0
-#if            TLS_ENC_DEBUG
-#define tlsDebug(format, args...)      printf(format , ## args)
-static void tlsDump(const char *name, void *b, unsigned len)
-{
-       unsigned char *cp = (unsigned char *)b;
-       unsigned i, dex;
-
-       printf("%s\n", name);
-       for(dex=0; dex<len; dex++) {
-               i = cp[dex];
-               printf("%02X ", i);
-               if((dex % 16) == 15) {
-                       printf("\n");
-               }
-       }
-       printf("\n");
-}
-
-#else
-#define tlsDebug(s, ...)
-#define tlsDump(name, b, len)
-#endif /* TLS_ENC_DEBUG */
-
-// MARK: -
-// MARK: PRF label strings
-/*
- * Note we could optimize away a bunch of mallocs and frees if we, like openSSL,
- * just mallocd buffers for inputs to SSLInternal_PRF() on the stack,
- * with "known" max values for all of the inputs.
- *
- * At least we hard-code string lengths here instead of calling strlen at runtime...
- */
-#define PLS_MASTER_SECRET                      "master secret"
-#define PLS_MASTER_SECRET_LEN          13
-#define PLS_KEY_EXPAND                         "key expansion"
-#define PLS_KEY_EXPAND_LEN                     13
-#define PLS_CLIENT_FINISH                      "client finished"
-#define PLS_CLIENT_FINISH_LEN          15
-#define PLS_SERVER_FINISH                      "server finished"
-#define PLS_SERVER_FINISH_LEN          15
-#define PLS_EXPORT_CLIENT_WRITE                "client write key"
-#define PLS_EXPORT_CLIENT_WRITE_LEN    16
-#define PLS_EXPORT_SERVER_WRITE                "server write key"
-#define PLS_EXPORT_SERVER_WRITE_LEN    16
-#define PLS_EXPORT_IV_BLOCK                    "IV block"
-#define PLS_EXPORT_IV_BLOCK_LEN                8
-
-// MARK: -
-// MARK: private functions
-
-/*
- * P_Hash function defined in RFC2246, section 5.
- */
-static OSStatus tlsPHash(
-       SSLContext                      *ctx,
-       const HMACReference *hmac,      // &TlsHmacSHA1, TlsHmacMD5
-       const uint8_t       *secret,
-       size_t              secretLen,
-       const uint8_t       *seed,
-       size_t              seedLen,
-       uint8_t             *out,       // mallocd by caller, size >= outLen
-       size_t              outLen)     // desired output size
-{
-       unsigned char aSubI[TLS_HMAC_MAX_SIZE];         /* A(i) */
-       unsigned char digest[TLS_HMAC_MAX_SIZE];
-       HMACContextRef hmacCtx;
-       OSStatus serr;
-       size_t digestLen = hmac->macSize;
-       
-       serr = hmac->alloc(hmac, secret, secretLen, &hmacCtx);
-       if(serr) {
-               return serr;
-       }
-
-       /* A(0) = seed */
-       /* A(1) := HMAC_hash(secret, seed) */
-       serr = hmac->hmac(hmacCtx, seed, seedLen, aSubI, &digestLen);
-       if(serr) {
-               goto fail;
-       }
-       assert(digestLen = hmac->macSize);
-
-       /* starting at loopNum 1... */
-       for (;;) {
-               /*
-                * This loop's chunk = HMAC_hash(secret, A(loopNum) + seed))
-                */
-               serr = hmac->init(hmacCtx);
-               if(serr) {
-                       break;
-               }
-               serr = hmac->update(hmacCtx, aSubI, digestLen);
-               if(serr) {
-                       break;
-               }
-               serr = hmac->update(hmacCtx, seed, seedLen);
-               if(serr) {
-                       break;
-               }
-               serr = hmac->final(hmacCtx, digest, &digestLen);
-               if(serr) {
-                       break;
-               }
-               assert(digestLen = hmac->macSize);
-
-               if(outLen <= digestLen) {
-                       /* last time, possible partial digest */
-                       memmove(out, digest, outLen);
-                       break;
-               }
-
-               memmove(out, digest, digestLen);
-               out += digestLen;
-               outLen -= digestLen;
-
-               /*
-                * A(i) = HMAC_hash(secret, A(i-1))
-                * Note there is a possible optimization involving obtaining this
-                * hmac by cloning the state of hmacCtx above after updating with
-                * aSubI, and getting the final version of that here. However CDSA
-                * does not support cloning of a MAC context (only for digest contexts).
-                */
-               serr = hmac->hmac(hmacCtx, aSubI, digestLen,
-                       aSubI, &digestLen);
-               if(serr) {
-                       break;
-               }
-               assert(digestLen = hmac->macSize);
-       }
-fail:
-       hmac->free(hmacCtx);
-       memset(aSubI, 0, TLS_HMAC_MAX_SIZE);
-       memset(digest, 0, TLS_HMAC_MAX_SIZE);
-       return serr;
-}
-
-/*
- * The TLS pseudorandom function, defined in RFC2246, section 5.
- * This takes as its input a secret block, a label, and a seed, and produces
- * a caller-specified length of pseudorandom data.
- *
- * Optimization TBD: make label optional, avoid malloc and two copies if it's
- * not there, so callers can take advantage of fixed-size seeds.
- */
-OSStatus SSLInternal_PRF(
-       SSLContext *ctx,
-       const void *vsecret,
-       size_t secretLen,
-       const void *label,                      // optional, NULL implies that seed contains
-                                                               //   the label
-       size_t labelLen,
-       const void *seed,
-       size_t seedLen,
-       void *vout,                                     // mallocd by caller, length >= outLen
-       size_t outLen)
-{
-       OSStatus serr = errSSLInternal;
-       const unsigned char *S1, *S2;           // the two seeds
-       size_t sLen;                                            // effective length of each seed
-       unsigned char *labelSeed = NULL;        // label + seed, passed to tlsPHash
-       size_t labelSeedLen;
-       unsigned char *tmpOut = NULL;           // output of P_SHA1
-       size_t i;
-       const unsigned char *secret = (const unsigned char *)vsecret;
-
-       if(label != NULL) {
-               /* concatenate label and seed */
-               labelSeedLen = labelLen + seedLen;
-               labelSeed = (unsigned char *)sslMalloc(labelSeedLen);
-               if(labelSeed == NULL) {
-                       return errSecAllocate;
-               }
-               memmove(labelSeed, label, labelLen);
-               memmove(labelSeed + labelLen, seed, seedLen);
-       }
-       else {
-               /* fast track - just use seed as is */
-               labelSeed = (unsigned char *)seed;
-               labelSeedLen = seedLen;
-       }
-
-    unsigned char *out = (unsigned char *)vout;
-    if(sslVersionIsLikeTls12(ctx)) {
-        const HMACReference *mac = &TlsHmacSHA256;
-        if (ctx->selectedCipherSpecParams.macAlg == HA_SHA384) {
-            mac = &TlsHmacSHA384;
-        }
-        serr = tlsPHash(ctx, mac, secret, secretLen, labelSeed, labelSeedLen,
-                        out, outLen);
-        if(serr) {
-            goto fail;
-        }
-    } else {
-        /* two seeds for tlsPHash */
-        sLen = secretLen / 2;                  // for partitioning
-        S1 = secret;
-        S2 = &secret[sLen];
-        sLen += (secretLen & 1);               // secret length odd, increment effective size
-
-        /* temporary output for SHA1, to be XORd with MD5 */
-        tmpOut = (unsigned char *)sslMalloc(outLen);
-        if(tmpOut == NULL) {
-            serr = errSecAllocate;
-            goto fail;
-        }
-
-        serr = tlsPHash(ctx, &TlsHmacMD5, S1, sLen, labelSeed, labelSeedLen,
-            out, outLen);
-        if(serr) {
-            goto fail;
-        }
-        serr = tlsPHash(ctx, &TlsHmacSHA1, S2, sLen, labelSeed, labelSeedLen,
-            tmpOut, outLen);
-        if(serr) {
-            goto fail;
-        }
-
-        /* XOR together to get final result */
-        for(i=0; i<outLen; i++) {
-            out[i] ^= tmpOut[i];
-        }
-       }
-
-    serr = errSecSuccess;
-fail:
-       if((labelSeed != NULL) && (label != NULL)) {
-               sslFree(labelSeed);
-       }
-       if(tmpOut != NULL) {
-               sslFree(tmpOut);
-       }
-       return serr;
-}
-
-/*
- * On input, the following are valid:
- *             MasterSecret[48]
- *             ClientHello.random[32]
- *      ServerHello.random[32]
- *
- *      key_block = PRF(SecurityParameters.master_secret,
- *                         "key expansion",
- *                         SecurityParameters.server_random +
- *                         SecurityParameters.client_random);
- */
-
-#define GKM_SEED_LEN   (PLS_KEY_EXPAND_LEN + (2 * SSL_CLIENT_SRVR_RAND_SIZE))
-
-static OSStatus tls1GenerateKeyMaterial (
-       SSLBuffer key,                                  // caller mallocs and specifies length of
-                                                                       //   required key material here
-       SSLContext *ctx)
-{
-       unsigned char seedBuf[GKM_SEED_LEN];
-       OSStatus serr;
-
-       /* use optimized label-less PRF */
-       memmove(seedBuf, PLS_KEY_EXPAND, PLS_KEY_EXPAND_LEN);
-       memmove(seedBuf + PLS_KEY_EXPAND_LEN, ctx->serverRandom,
-               SSL_CLIENT_SRVR_RAND_SIZE);
-       memmove(seedBuf + PLS_KEY_EXPAND_LEN + SSL_CLIENT_SRVR_RAND_SIZE,
-               ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE);
-       serr = SSLInternal_PRF(ctx,
-               ctx->masterSecret,
-               SSL_MASTER_SECRET_SIZE,
-               NULL,                                           // no label
-               0,
-               seedBuf,
-               GKM_SEED_LEN,
-               key.data,                                       // destination
-               key.length);
-       tlsDump("key expansion", key.data, key.length);
-       return serr;
-}
-
-/*
- * On entry: clientRandom, serverRandom, preMasterSecret valid
- * On return: masterSecret valid
- *
- * master_secret = PRF(pre_master_secret, "master secret",
- *                                             ClientHello.random + ServerHello.random)
- *      [0..47];
- */
-
-static OSStatus tls1GenerateMasterSecret (
-       SSLContext *ctx)
-{
-       unsigned char randBuf[2 * SSL_CLIENT_SRVR_RAND_SIZE];
-       OSStatus serr;
-
-       memmove(randBuf, ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE);
-       memmove(randBuf + SSL_CLIENT_SRVR_RAND_SIZE,
-               ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE);
-       serr = SSLInternal_PRF(ctx,
-               ctx->preMasterSecret.data,
-               ctx->preMasterSecret.length,
-               (const unsigned char *)PLS_MASTER_SECRET,
-               PLS_MASTER_SECRET_LEN,
-               randBuf,
-               2 * SSL_CLIENT_SRVR_RAND_SIZE,
-               ctx->masterSecret,              // destination
-               SSL_MASTER_SECRET_SIZE);
-       tlsDump("master secret", ctx->masterSecret, SSL_MASTER_SECRET_SIZE);
-       return serr;
-}
-
-/*
- * Given digests contexts representing the running total of all handshake messages,
- * calculate mac for "finished" message.
- *
- *                     verify_data = 12 bytes =
- *                             PRF(master_secret, finished_label, MD5(handshake_messages) +
- *                                     SHA-1(handshake_messages)) [0..11];
- */
-static OSStatus tls1ComputeFinishedMac (
-       SSLContext *ctx,
-       SSLBuffer finished,             // output - mallocd by caller
-       Boolean isServer)
-{
-       unsigned char digests[SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN];
-       SSLBuffer digBuf;
-       char *finLabel;
-       unsigned finLabelLen;
-       OSStatus serr;
-    SSLBuffer shaMsgState, md5MsgState;
-
-    shaMsgState.data = 0;
-    md5MsgState.data = 0;
-    if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0)
-        goto fail;
-    if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0)
-        goto fail;
-
-       if(isServer) {
-               finLabel = PLS_SERVER_FINISH;
-               finLabelLen = PLS_SERVER_FINISH_LEN;
-       }
-       else {
-               finLabel = PLS_CLIENT_FINISH;
-               finLabelLen = PLS_CLIENT_FINISH_LEN;
-       }
-
-       /* concatenate two digest results */
-       digBuf.data = digests;
-       digBuf.length = SSL_MD5_DIGEST_LEN;
-       serr = SSLHashMD5.final(&md5MsgState, &digBuf);
-       if(serr) {
-               return serr;
-       }
-       digBuf.data += SSL_MD5_DIGEST_LEN;
-       digBuf.length = SSL_SHA1_DIGEST_LEN;
-       serr = SSLHashSHA1.final(&shaMsgState, &digBuf);
-       if(serr) {
-               return serr;
-       }
-    serr = SSLInternal_PRF(ctx,
-               ctx->masterSecret,
-               SSL_MASTER_SECRET_SIZE,
-               (const unsigned char *)finLabel,
-               finLabelLen,
-               digests,
-               SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN,
-               finished.data,                          // destination
-               finished.length);
-
-fail:
-    SSLFreeBuffer(&shaMsgState);
-    SSLFreeBuffer(&md5MsgState);
-
-    return serr;
-}
-
-/*
- * Given digests contexts representing the running total of all handshake messages,
- * calculate mac for "finished" message.
- *
- *                     verify_data = 12 bytes =
- *                             PRF(master_secret, finished_label, SHA256(handshake_messages)) [0..11];
- */
-static OSStatus tls12ComputeFinishedMac (
-                                        SSLContext *ctx,
-                                        SSLBuffer finished,            // output - mallocd by caller
-                                        Boolean isServer)
-{
-       unsigned char digest[SSL_MAX_DIGEST_LEN];
-       SSLBuffer digBuf;
-       char *finLabel;
-       unsigned finLabelLen;
-       OSStatus serr;
-    SSLBuffer hashState;
-    const HashReference *hashRef;
-    const SSLBuffer *ctxHashState;
-
-    /* The PRF used in the finished message is based on the cipherspec */
-    if (ctx->selectedCipherSpecParams.macAlg == HA_SHA384) {
-        hashRef = &SSLHashSHA384;
-        ctxHashState = &ctx->sha512State;
-    } else {
-        hashRef = &SSLHashSHA256;
-        ctxHashState = &ctx->sha256State;
-    }
-
-    hashState.data = 0;
-    if ((serr = CloneHashState(hashRef, ctxHashState, &hashState)) != 0)
-        goto fail;
-       if(isServer) {
-               finLabel = PLS_SERVER_FINISH;
-               finLabelLen = PLS_SERVER_FINISH_LEN;
-       }
-       else {
-               finLabel = PLS_CLIENT_FINISH;
-               finLabelLen = PLS_CLIENT_FINISH_LEN;
-       }
-
-       /* concatenate two digest results */
-       digBuf.data = digest;
-       digBuf.length = hashRef->digestSize;
-       if ((serr = hashRef->final(&hashState, &digBuf)) != 0)
-        goto fail;
-       serr = SSLInternal_PRF(ctx,
-                           ctx->masterSecret,
-                           SSL_MASTER_SECRET_SIZE,
-                           (const unsigned char *)finLabel,
-                           finLabelLen,
-                           digBuf.data,
-                           digBuf.length,
-                           finished.data,                              // destination
-                           finished.length);
-fail:
-    SSLFreeBuffer(&hashState);
-    return serr;
-}
-
-/*
- * This one is trivial.
- *
- * mac := MD5(handshake_messages) + SHA(handshake_messages);
- *
- * I don't know why this one doesn't use an HMAC or the master secret (as SSLv3
- * does).
- */
-static OSStatus tls1ComputeCertVfyMac (
-       SSLContext *ctx,
-       SSLBuffer *finished,            // output - mallocd by caller
-    SSL_HashAlgorithm hash)     //unused in this one
-{
-       SSLBuffer digBuf, shaMsgState, md5MsgState;
-       OSStatus serr;
-
-    shaMsgState.data = 0;
-    md5MsgState.data = 0;
-
-    if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0)
-        goto fail;
-    if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0)
-        goto fail;
-
-    if ((ctx->protocolSide == kSSLServerSide && sslPubKeyGetAlgorithmID(ctx->peerPubKey) == kSecECDSAAlgorithmID) ||
-        (ctx->protocolSide == kSSLClientSide && ctx->negAuthType == SSLClientAuth_ECDSASign)) {
-               /* Only take SHA1 regardless of TLSv1.0 or TLSv1.1 If we are the server
-           and our peer signed with an ECDSA key, or if we are the client and
-           are about to sign with ECDSA. */
-        assert(finished->length >= SSL_SHA1_DIGEST_LEN);
-        digBuf.data = finished->data;
-        finished->length = SSL_SHA1_DIGEST_LEN;
-    } else {
-        /* Put MD5 follow by SHA1 hash in buffer. */
-        assert(finished->length >= (SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN));
-        digBuf.data = finished->data;
-        digBuf.length = SSL_MD5_DIGEST_LEN;
-        if ((serr = SSLHashMD5.final(&md5MsgState, &digBuf)) != 0)
-            goto fail;
-        digBuf.data = finished->data + SSL_MD5_DIGEST_LEN;
-        finished->length = SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN;
-    }
-
-       digBuf.length = SSL_SHA1_DIGEST_LEN;
-       serr = SSLHashSHA1.final(&shaMsgState, &digBuf);
-
-fail:
-    SSLFreeBuffer(&shaMsgState);
-    SSLFreeBuffer(&md5MsgState);
-
-    return serr;
-}
-
-static OSStatus tls12ComputeCertVfyMac (
-    SSLContext *ctx,
-    SSLBuffer *finished,               // output - mallocd by caller
-    SSL_HashAlgorithm hash)
-{
-       const SSLBuffer *ctxHashState;
-    const HashReference *hashRef;
-       SSLBuffer hashState;
-       OSStatus serr;
-
-    hashState.data = 0;
-
-    switch (hash) {
-        case SSL_HashAlgorithmSHA1:
-            hashRef = &SSLHashSHA1;
-            ctxHashState = &ctx->shaState;
-            break;
-        case SSL_HashAlgorithmSHA256:
-            hashRef = &SSLHashSHA256;
-            ctxHashState = &ctx->sha256State;
-            break;
-        case SSL_HashAlgorithmSHA384:
-            hashRef = &SSLHashSHA384;
-            ctxHashState = &ctx->sha512State;
-            break;
-        default:
-            return errSSLInternal;
-            break;
-    }
-
-    if ((serr = CloneHashState(hashRef, ctxHashState, &hashState)) != 0)
-        goto fail;
-
-       assert(finished->length >= (hashRef->digestSize));
-       finished->length = hashRef->digestSize;
-       serr = hashRef->final(&hashState, finished);
-
-fail:
-    SSLFreeBuffer(&hashState);
-
-    return serr;
-}
-
-
-const SslTlsCallouts Tls1Callouts = {
-       tls1GenerateKeyMaterial,
-       tls1GenerateMasterSecret,
-       tls1ComputeFinishedMac,
-       tls1ComputeCertVfyMac
-};
-
-const SslTlsCallouts Tls12Callouts = {
-       tls1GenerateKeyMaterial,
-       tls1GenerateMasterSecret,
-       tls12ComputeFinishedMac,
-       tls12ComputeCertVfyMac
-};