#ifndef _SSLCTX_H_
#include "sslctx.h"
#endif
#ifndef _SSLHDSHK_H_
#include "sslhdshk.h"
#endif
#ifndef _SSLALLOC_H_
#include "sslalloc.h"
#endif
#ifndef _SSL_DEBUG_H_
#include "sslDebug.h"
#endif
#ifndef _SSLUTIL_H_
#include "sslutil.h"
#endif
#ifndef _APPLE_CDSA_H_
#include "appleCdsa.h"
#endif
#ifndef _DIGESTS_H_
#include "digests.h"
#endif
#include <string.h>
#include <assert.h>
SSLErr
SSLEncodeRSAPremasterSecret(SSLContext *ctx)
{ SSLBuffer randData;
SSLErr err;
if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret,
SSL_RSA_PREMASTER_SECRET_SIZE, &ctx->sysCtx)) != 0)
return err;
assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
(ctx->negProtocolVersion == TLS_Version_1_0));
SSLEncodeInt(ctx->preMasterSecret.data, ctx->maxProtocolVersion, 2);
randData.data = ctx->preMasterSecret.data+2;
randData.length = SSL_RSA_PREMASTER_SECRET_SIZE - 2;
if ((err = sslRand(ctx, &randData)) != 0)
return err;
DUMP_BUFFER_NAME("premaster secret", ctx->preMasterSecret);
return SSLNoErr;
}
#if APPLE_DH
SSLErr
SSLEncodeDHPremasterSecret(SSLContext *ctx)
{
#if !APPLE_DH
return SSLUnsupportedErr;
#else
SSLErr err;
int rsaResult;
SSLRandomCtx rsaRandom;
if (ERR(err = ReadyRandom(&rsaRandom, ctx)) != 0)
return err;
#if RSAREF
{ privateValue.data = 0;
if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
goto fail;
if (ERR(err = SSLAllocBuffer(&privateValue, ctx->dhExchangePublic.length - 16, &ctx->sysCtx)) != 0)
goto fail;
if ((rsaResult = R_SetupDHAgreement(ctx->dhExchangePublic.data, privateValue.data,
privateValue.length, &ctx->peerDHParams, &rsaRandom)) != 0)
{ err = SSLUnknownErr;
goto fail;
}
if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
goto fail;
if ((rsaResult = R_ComputeDHAgreedKey (ctx->preMasterSecret.data, ctx->dhPeerPublic.data,
privateValue.data, privateValue.length, &ctx->peerDHParams)) != 0)
{ err = SSLUnknownErr;
goto fail;
}
}
#elif BSAFE
{ unsigned int outputLen;
if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, 128, &ctx->sysCtx)) != 0)
goto fail;
if ((rsaResult = B_KeyAgreePhase1(ctx->peerDHParams, ctx->dhExchangePublic.data,
&outputLen, 128, rsaRandom, NO_SURR)) != 0)
{ err = SSLUnknownErr;
goto fail;
}
ctx->dhExchangePublic.length = outputLen;
if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, 128, &ctx->sysCtx)) != 0)
goto fail;
if ((rsaResult = B_KeyAgreePhase2(ctx->peerDHParams, ctx->preMasterSecret.data,
&outputLen, 128, ctx->dhPeerPublic.data, ctx->dhPeerPublic.length,
NO_SURR)) != 0)
{ err = SSLUnknownErr;
goto fail;
}
ctx->preMasterSecret.length = outputLen;
}
#endif
DUMP_BUFFER_NAME("premaster secret", ctx->preMasterSecret);
err = SSLNoErr;
fail:
#if RSAREF
ERR(SSLFreeBuffer(&privateValue, &ctx->sysCtx));
R_RandomFinal(&rsaRandom);
#elif BSAFE
B_DestroyAlgorithmObject(&rsaRandom);
#endif
return err;
#endif
}
#endif
SSLErr
SSLInitPendingCiphers(SSLContext *ctx)
{ SSLErr err;
SSLBuffer key;
UInt8 *keyDataProgress, *keyPtr, *ivPtr;
int keyDataLen;
CipherContext *serverPending, *clientPending;
key.data = 0;
ctx->readPending.macRef = ctx->selectedCipherSpec->macAlgorithm;
ctx->writePending.macRef = ctx->selectedCipherSpec->macAlgorithm;
ctx->readPending.symCipher = ctx->selectedCipherSpec->cipher;
ctx->writePending.symCipher = ctx->selectedCipherSpec->cipher;
ctx->readPending.sequenceNum.high = ctx->readPending.sequenceNum.low = 0;
ctx->writePending.sequenceNum.high = ctx->writePending.sequenceNum.low = 0;
keyDataLen = ctx->selectedCipherSpec->macAlgorithm->hash->digestSize +
ctx->selectedCipherSpec->cipher->secretKeySize;
if (ctx->selectedCipherSpec->isExportable == NotExportable)
keyDataLen += ctx->selectedCipherSpec->cipher->ivSize;
keyDataLen *= 2;
if ((err = SSLAllocBuffer(&key, keyDataLen, &ctx->sysCtx)) != 0)
return err;
assert(ctx->sslTslCalls != NULL);
if ((err = ctx->sslTslCalls->generateKeyMaterial(key, ctx)) != 0)
goto fail;
if (ctx->protocolSide == SSL_ServerSide)
{ serverPending = &ctx->writePending;
clientPending = &ctx->readPending;
}
else
{ serverPending = &ctx->readPending;
clientPending = &ctx->writePending;
}
keyDataProgress = key.data;
memcpy(clientPending->macSecret, keyDataProgress,
ctx->selectedCipherSpec->macAlgorithm->hash->digestSize);
keyDataProgress += ctx->selectedCipherSpec->macAlgorithm->hash->digestSize;
memcpy(serverPending->macSecret, keyDataProgress,
ctx->selectedCipherSpec->macAlgorithm->hash->digestSize);
keyDataProgress += ctx->selectedCipherSpec->macAlgorithm->hash->digestSize;
err = ctx->sslTslCalls->initMac(clientPending, ctx);
if(err) {
goto fail;
}
err = ctx->sslTslCalls->initMac(serverPending, ctx);
if(err) {
goto fail;
}
if (ctx->selectedCipherSpec->isExportable == NotExportable)
{ keyPtr = keyDataProgress;
keyDataProgress += ctx->selectedCipherSpec->cipher->secretKeySize;
ivPtr = keyDataProgress + ctx->selectedCipherSpec->cipher->secretKeySize;
if ((err = ctx->selectedCipherSpec->cipher->initialize(keyPtr, ivPtr,
clientPending, ctx)) != 0)
goto fail;
keyPtr = keyDataProgress;
keyDataProgress += ctx->selectedCipherSpec->cipher->secretKeySize;
ivPtr = keyDataProgress + ctx->selectedCipherSpec->cipher->ivSize;
if ((err = ctx->selectedCipherSpec->cipher->initialize(keyPtr, ivPtr,
serverPending, ctx)) != 0)
goto fail;
}
else {
UInt8 clientExportKey[16], serverExportKey[16],
clientExportIV[16], serverExportIV[16];
SSLBuffer clientWrite, serverWrite;
SSLBuffer finalClientWrite, finalServerWrite;
SSLBuffer finalClientIV, finalServerIV;
assert(ctx->selectedCipherSpec->cipher->keySize <= 16);
assert(ctx->selectedCipherSpec->cipher->ivSize <= 16);
clientWrite.data = keyDataProgress;
clientWrite.length = ctx->selectedCipherSpec->cipher->secretKeySize;
serverWrite.data = keyDataProgress + clientWrite.length;
serverWrite.length = ctx->selectedCipherSpec->cipher->secretKeySize;
finalClientWrite.data = clientExportKey;
finalServerWrite.data = serverExportKey;
finalClientIV.data = clientExportIV;
finalServerIV.data = serverExportIV;
finalClientWrite.length = 16;
finalServerWrite.length = 16;
finalClientIV.length = ctx->selectedCipherSpec->cipher->ivSize;
finalServerIV.length = ctx->selectedCipherSpec->cipher->ivSize;
assert(ctx->sslTslCalls != NULL);
err = ctx->sslTslCalls->generateExportKeyAndIv(ctx, clientWrite, serverWrite,
finalClientWrite, finalServerWrite, finalClientIV, finalServerIV);
if(err) {
goto fail;
}
if ((err = ctx->selectedCipherSpec->cipher->initialize(clientExportKey,
clientExportIV, clientPending, ctx)) != 0)
goto fail;
if ((err = ctx->selectedCipherSpec->cipher->initialize(serverExportKey,
serverExportIV, serverPending, ctx)) != 0)
goto fail;
}
ctx->writePending.ready = 1;
ctx->readPending.ready = 1;
err = SSLNoErr;
fail:
SSLFreeBuffer(&key, &ctx->sysCtx);
return err;
}