+++ /dev/null
-/*
- * 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@
- */
-
-/*
- * ssl3Callouts.c - SSLv3-specific routines for SslTlsCallouts.
- */
-
-#include "sslMemory.h"
-#include "tls_ssl.h"
-#include "sslUtils.h"
-#include "sslDigests.h"
-#include "sslDebug.h"
-#include "sslAlertMessage.h"
-
-#include <assert.h>
-#include <strings.h>
-#include <stddef.h>
-
-#define LOG_GEN_KEY 0
-
-/*
- * On input, the following are valid:
- * MasterSecret[48]
- * ClientHello.random[32]
- * ServerHello.random[32]
- *
- * key_block =
- * MD5(master_secret + SHA(`A' + master_secret +
- * ServerHello.random +
- * ClientHello.random)) +
- * MD5(master_secret + SHA(`BB' + master_secret +
- * ServerHello.random +
- * ClientHello.random)) +
- * MD5(master_secret + SHA(`CCC' + master_secret +
- * ServerHello.random +
- * ClientHello.random)) + [...];
- */
-static OSStatus ssl3GenerateKeyMaterial (
- SSLBuffer key, // caller mallocs and specifies length of
- // required key material here
- SSLContext *ctx)
-{
- OSStatus err;
- UInt8 leaderData[10]; /* Max of 10 hashes
- * (* 16 bytes/hash = 160 bytes of key) */
- UInt8 shaHashData[20], md5HashData[16];
- SSLBuffer shaContext, md5Context;
- UInt8 *keyProgress;
- size_t i,j,remaining, satisfied;
- SSLBuffer leader, masterSecret, serverRandom, clientRandom, shaHash, md5Hash;
-
- #if LOG_GEN_KEY
- printf("GenerateKey: master ");
- for(i=0; i<SSL_MASTER_SECRET_SIZE; i++) {
- printf("%02X ", ctx->masterSecret[i]);
- }
- printf("\n");
- #endif
-
- assert(key.length <= 16 * sizeof(leaderData));
-
- leader.data = leaderData;
- masterSecret.data = ctx->masterSecret;
- masterSecret.length = SSL_MASTER_SECRET_SIZE;
- serverRandom.data = ctx->serverRandom;
- serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
- clientRandom.data = ctx->clientRandom;
- clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
- shaHash.data = shaHashData;
- shaHash.length = 20;
- md5Hash.data = md5HashData;
- md5Hash.length = 16;
-
- md5Context.data = 0;
- shaContext.data = 0;
- if ((err = ReadyHash(&SSLHashMD5, &md5Context)) != 0)
- goto fail;
- if ((err = ReadyHash(&SSLHashSHA1, &shaContext)) != 0)
- goto fail;
-
- keyProgress = key.data;
- remaining = key.length;
-
- for (i = 0; remaining > 0; ++i)
- { for (j = 0; j <= i; j++)
- leaderData[j] = 0x41 + i; /* 'A', 'BB', 'CCC', etc. */
- leader.length = i+1;
-
- if ((err = SSLHashSHA1.update(&shaContext, &leader)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaContext, &masterSecret)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaContext, &serverRandom)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaContext, &clientRandom)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.final(&shaContext, &shaHash)) != 0)
- goto fail;
- if ((err = SSLHashMD5.update(&md5Context, &masterSecret)) != 0)
- goto fail;
- if ((err = SSLHashMD5.update(&md5Context, &shaHash)) != 0)
- goto fail;
- if ((err = SSLHashMD5.final(&md5Context, &md5Hash)) != 0)
- goto fail;
-
- satisfied = 16;
- if (remaining < 16)
- satisfied = remaining;
- memcpy(keyProgress, md5HashData, satisfied);
- remaining -= satisfied;
- keyProgress += satisfied;
-
- if(remaining > 0) {
- /* at top of loop, this was done in ReadyHash() */
- if ((err = SSLHashMD5.init(&md5Context)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.init(&shaContext)) != 0)
- goto fail;
- }
- }
-
- assert(remaining == 0 && keyProgress == (key.data + key.length));
- err = errSecSuccess;
-fail:
- SSLFreeBuffer(&md5Context);
- SSLFreeBuffer(&shaContext);
-
- #if LOG_GEN_KEY
- printf("GenerateKey: DONE\n");
- #endif
- return err;
-}
-
-/*
- * On entry: clientRandom, serverRandom, preMasterSecret valid
- * On return: masterSecret valid
- */
-static OSStatus ssl3GenerateMasterSecret (
- SSLContext *ctx)
-{
- OSStatus err;
- SSLBuffer shaState, md5State, clientRandom,
- serverRandom, shaHash, md5Hash, leader;
- UInt8 *masterProgress, shaHashData[20], leaderData[3];
- int i;
-
- md5State.data = shaState.data = 0;
- if ((err = SSLAllocBuffer(&md5State, SSLHashMD5.contextSize)))
- goto fail;
- if ((err = SSLAllocBuffer(&shaState, SSLHashSHA1.contextSize)))
- goto fail;
-
- clientRandom.data = ctx->clientRandom;
- clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
- serverRandom.data = ctx->serverRandom;
- serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
- shaHash.data = shaHashData;
- shaHash.length = 20;
-
- masterProgress = ctx->masterSecret;
-
- for (i = 1; i <= 3; i++)
- { if ((err = SSLHashMD5.init(&md5State)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.init(&shaState)) != 0)
- goto fail;
-
- leaderData[0] = leaderData[1] = leaderData[2] = 0x40 + i; /* 'A', 'B', etc. */
- leader.data = leaderData;
- leader.length = i;
-
- if ((err = SSLHashSHA1.update(&shaState, &leader)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaState, &ctx->preMasterSecret)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaState, &clientRandom)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaState, &serverRandom)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.final(&shaState, &shaHash)) != 0)
- goto fail;
- if ((err = SSLHashMD5.update(&md5State, &ctx->preMasterSecret)) != 0)
- goto fail;
- if ((err = SSLHashMD5.update(&md5State, &shaHash)) != 0)
- goto fail;
- md5Hash.data = masterProgress;
- md5Hash.length = 16;
- if ((err = SSLHashMD5.final(&md5State, &md5Hash)) != 0)
- goto fail;
- masterProgress += 16;
- }
-
- err = errSecSuccess;
-fail:
- SSLFreeBuffer(&shaState);
- SSLFreeBuffer(&md5State);
- return err;
-}
-
-/* common routine to compute a Mac for finished message and cert verify message */
-static OSStatus
-ssl3CalculateFinishedMessage(
- SSLContext *ctx,
- SSLBuffer finished, // mallocd by caller
- SSLBuffer shaMsgState, // running total
- SSLBuffer md5MsgState, // ditto
- UInt32 senderID) // optional, nonzero for finished message
-{
- OSStatus err;
- SSLBuffer hash, input;
- UInt8 sender[4], md5Inner[16], shaInner[20];
-
- // assert(finished.length == 36);
-
- if (senderID != 0) {
- SSLEncodeInt(sender, senderID, 4);
- input.data = sender;
- input.length = 4;
- if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
- goto fail;
- }
- input.data = ctx->masterSecret;
- input.length = SSL_MASTER_SECRET_SIZE;
- if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
- goto fail;
- input.data = (UInt8 *)SSLMACPad1;
- input.length = SSLHashMD5.macPadSize;
- if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
- goto fail;
- input.length = SSLHashSHA1.macPadSize;
- if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
- goto fail;
- hash.data = md5Inner;
- hash.length = 16;
- if ((err = SSLHashMD5.final(&md5MsgState, &hash)) != 0)
- goto fail;
- hash.data = shaInner;
- hash.length = 20;
- if ((err = SSLHashSHA1.final(&shaMsgState, &hash)) != 0)
- goto fail;
- if ((err = SSLHashMD5.init(&md5MsgState)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.init(&shaMsgState)) != 0)
- goto fail;
- input.data = ctx->masterSecret;
- input.length = SSL_MASTER_SECRET_SIZE;
- if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
- goto fail;
- if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
- goto fail;
- input.data = (UInt8 *)SSLMACPad2;
- input.length = SSLHashMD5.macPadSize;
- if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
- goto fail;
- input.length = SSLHashSHA1.macPadSize;
- if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
- goto fail;
- input.data = md5Inner;
- input.length = 16;
- if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
- goto fail;
- hash.data = finished.data;
- hash.length = 16;
- if ((err = SSLHashMD5.final(&md5MsgState, &hash)) != 0)
- goto fail;
- input.data = shaInner;
- input.length = 20;
- if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
- goto fail;
- hash.data = finished.data + 16;
- hash.length = 20;
- if ((err = SSLHashSHA1.final(&shaMsgState, &hash)) != 0)
- goto fail;
-
-fail:
- return err;
-}
-
-
-static OSStatus ssl3ComputeFinishedMac (
- SSLContext *ctx,
- SSLBuffer finished, // output - mallocd by caller
- Boolean isServer) // refers to message, not us
-{
- 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;
-
- serr = ssl3CalculateFinishedMessage(ctx, finished, shaMsgState, md5MsgState,
- isServer ? SSL_Finished_Sender_Server : SSL_Finished_Sender_Client);
-
-fail:
- SSLFreeBuffer(&shaMsgState);
- SSLFreeBuffer(&md5MsgState);
-
- return serr;
-}
-
-/* TODO: Factor this and ssl3ComputeFinishedMac to share more common code. */
-static OSStatus ssl3ComputeCertVfyMac (
- SSLContext *ctx,
- SSLBuffer *finished, // output - mallocd by caller
- SSL_HashAlgorithm hash) //unused in this one
-{
- 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;
-
- assert(finished->length >= SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN);
- finished->length = SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN;
-
- serr = ssl3CalculateFinishedMessage(ctx, *finished, shaMsgState, md5MsgState, 0);
-
-fail:
- SSLFreeBuffer(&shaMsgState);
- SSLFreeBuffer(&md5MsgState);
-
- return serr;
-}
-
-const SslTlsCallouts Ssl3Callouts = {
- ssl3GenerateKeyMaterial,
- ssl3GenerateMasterSecret,
- ssl3ComputeFinishedMac,
- ssl3ComputeCertVfyMac
-};