#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>
#if _APPLE_CDSA_
typedef CSSM_KEY_PTR SSLRSAPrivateKey;
#endif
static SSLErr SSLEncodeRSAServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx);
static SSLErr SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx);
static SSLErr SSLProcessRSAServerKeyExchange(SSLBuffer message, SSLContext *ctx);
static SSLErr SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx);
static SSLErr SSLEncodeRSAKeyExchange(SSLRecord *keyExchange, SSLContext *ctx);
#if APPLE_DH
static SSLErr SSLEncodeDHanonServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx);
static SSLErr SSLEncodeDHanonKeyExchange(SSLRecord *keyExchange, SSLContext *ctx);
static SSLErr SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange, SSLContext *ctx);
static SSLErr SSLProcessDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx);
#endif
SSLErr
SSLEncodeServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
{ SSLErr err;
switch (ctx->selectedCipherSpec->keyExchangeMethod)
{ case SSL_RSA:
case SSL_RSA_EXPORT:
if (ERR(err = SSLEncodeRSAServerKeyExchange(keyExch, ctx)) != 0)
return err;
break;
#if APPLE_DH
case SSL_DH_anon:
if (ERR(err = SSLEncodeDHanonServerKeyExchange(keyExch, ctx)) != 0)
return err;
break;
#endif
default:
return ERR(SSLUnsupportedErr);
}
return SSLNoErr;
}
static SSLErr
SSLEncodeRSAServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
{ SSLErr err;
UInt8 *progress;
int length;
UInt32 outputLen, localKeyModulusLen;
UInt8 hashes[36];
SSLBuffer exportKey,clientRandom,serverRandom,hashCtx, hash;
exportKey.data = 0;
hashCtx.data = 0;
#if _APPLE_CDSA_
CASSERT(ctx->encryptPubKey != NULL);
CASSERT(ctx->protocolSide == SSL_ServerSide);
if ((err = SSLEncodeRSAKeyParams(&exportKey, &ctx->encryptPubKey, ctx)) != 0)
#else
if (ERR(err = SSLEncodeRSAKeyParams(&exportKey, &ctx->exportKey, ctx)) != 0)
#endif
goto fail;
#if RSAREF
localKeyModulusLen = (ctx->localKey.bits + 7)/8;
#elif BSAFE
{ A_RSA_KEY *keyInfo;
int rsaResult;
if ((rsaResult = B_GetKeyInfo((POINTER*)&keyInfo, ctx->localKey, KI_RSAPublic)) != 0)
return SSLUnknownErr;
localKeyModulusLen = keyInfo->modulus.len;
}
#elif _APPLE_CDSA_
CASSERT(ctx->signingPubKey != NULL);
localKeyModulusLen = sslKeyLengthInBytes(ctx->signingPubKey);
#else
#error No Asymmetric crypto specified
#endif
length = exportKey.length + 2 + localKeyModulusLen;
keyExch->protocolVersion = SSL_Version_3_0;
keyExch->contentType = SSL_handshake;
if (ERR(err = SSLAllocBuffer(&keyExch->contents, length+4, &ctx->sysCtx)) != 0)
goto fail;
progress = keyExch->contents.data;
*progress++ = SSL_server_key_exchange;
progress = SSLEncodeInt(progress, length, 3);
memcpy(progress, exportKey.data, exportKey.length);
progress += exportKey.length;
clientRandom.data = ctx->clientRandom;
clientRandom.length = 32;
serverRandom.data = ctx->serverRandom;
serverRandom.length = 32;
hash.data = &hashes[0];
hash.length = 16;
if (ERR(err = ReadyHash(&SSLHashMD5, &hashCtx, ctx)) != 0)
goto fail;
if (ERR(err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
goto fail;
if (ERR(err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
goto fail;
if (ERR(err = SSLHashMD5.update(hashCtx, exportKey)) != 0)
goto fail;
if (ERR(err = SSLHashMD5.final(hashCtx, hash)) != 0)
goto fail;
if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
goto fail;
hash.data = &hashes[16];
hash.length = 20;
if (ERR(err = ReadyHash(&SSLHashSHA1, &hashCtx, ctx)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.update(hashCtx, exportKey)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.final(hashCtx, hash)) != 0)
goto fail;
if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
goto fail;
progress = SSLEncodeInt(progress, localKeyModulusLen, 2);
#if RSAREF
if (RSAPrivateEncrypt(progress, &outputLen, hashes, 36, &ctx->localKey) != 0)
return ERR(SSLUnknownErr);
#elif BSAFE
{ B_ALGORITHM_OBJ rsa;
B_ALGORITHM_METHOD *chooser[] = { &AM_RSA_ENCRYPT, &AM_RSA_CRT_ENCRYPT, 0 };
int rsaResult;
UInt32 encryptedOut;
if ((rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPrivate, 0)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_EncryptInit(rsa, ctx->localKey, chooser, NO_SURR)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_EncryptUpdate(rsa, progress,
&encryptedOut, localKeyModulusLen, hashes, 36, 0, NO_SURR)) != 0)
return SSLUnknownErr;
outputLen = encryptedOut;
if ((rsaResult = B_EncryptFinal(rsa, progress+outputLen,
&encryptedOut, localKeyModulusLen-outputLen, 0, NO_SURR)) != 0)
return SSLUnknownErr;
outputLen += encryptedOut;
B_DestroyAlgorithmObject(&rsa);
}
#elif _APPLE_CDSA_
err = sslRsaRawSign(ctx,
ctx->signingPrivKey,
ctx->signingKeyCsp,
hashes,
36,
progress,
length,
&outputLen);
if(err) {
goto fail;
}
#endif
CASSERT(outputLen == localKeyModulusLen);
err = SSLNoErr;
fail:
ERR(SSLFreeBuffer(&hashCtx, &ctx->sysCtx));
ERR(SSLFreeBuffer(&exportKey, &ctx->sysCtx));
return err;
}
static SSLErr
SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx)
{ SSLErr err;
SSLBuffer modulus, exponent;
UInt8 *progress;
#if RSAREF
keyParams->data = 0;
modulus.length = (key->bits + 7) / 8;
modulus.data = key->modulus + MAX_RSA_MODULUS_LEN - modulus.length;
exponent.length = MAX_RSA_MODULUS_LEN;
exponent.data = key->publicExponent;
while (*exponent.data == 0)
{ ++exponent.data;
--exponent.length;
}
#elif BSAFE
{ A_RSA_KEY *keyInfo;
int rsaResult;
if ((rsaResult = B_GetKeyInfo((POINTER*)&keyInfo, *key, KI_RSAPublic)) != 0)
return SSLUnknownErr;
modulus.data = keyInfo->modulus.data;
modulus.length = keyInfo->modulus.len;
exponent.data = keyInfo->exponent.data;
exponent.length = keyInfo->exponent.len;
}
#elif _APPLE_CDSA_
err = sslGetPubKeyBits(ctx,
*key,
ctx->encryptKeyCsp,
&modulus,
&exponent);
if(err) {
SSLFreeBuffer(&modulus, &ctx->sysCtx);
SSLFreeBuffer(&exponent, &ctx->sysCtx);
return err;
}
#else
#error No assymetric crypto specified
#endif
if (ERR(err = SSLAllocBuffer(keyParams, modulus.length + exponent.length + 4, &ctx->sysCtx)) != 0)
return err;
progress = keyParams->data;
progress = SSLEncodeInt(progress, modulus.length, 2);
memcpy(progress, modulus.data, modulus.length);
progress += modulus.length;
progress = SSLEncodeInt(progress, exponent.length, 2);
memcpy(progress, exponent.data, exponent.length);
#if _APPLE_CDSA_
SSLFreeBuffer(&modulus, &ctx->sysCtx);
SSLFreeBuffer(&exponent, &ctx->sysCtx);
#endif
return SSLNoErr;
}
#if APPLE_DH
static SSLErr
SSLEncodeDHanonServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
{ SSLErr err;
UInt32 length;
UInt8 *progress;
SSLRandomCtx random;
int rsaErr;
#if RSAREF
length = 6 + ctx->dhAnonParams.primeLen + ctx->dhAnonParams.generatorLen +
ctx->dhExchangePublic.length;
keyExch->protocolVersion = SSL_Version_3_0;
keyExch->contentType = SSL_handshake;
if (ERR(err = SSLAllocBuffer(&keyExch->contents, length+4, &ctx->sysCtx)) != 0)
return err;
progress = keyExch->contents.data;
*progress++ = SSL_server_key_exchange;
progress = SSLEncodeInt(progress, length, 3);
progress = SSLEncodeInt(progress, ctx->dhAnonParams.primeLen, 2);
memcpy(progress, ctx->dhAnonParams.prime, ctx->dhAnonParams.primeLen);
progress += ctx->dhAnonParams.primeLen;
progress = SSLEncodeInt(progress, ctx->dhAnonParams.generatorLen, 2);
memcpy(progress, ctx->dhAnonParams.generator, ctx->dhAnonParams.generatorLen);
progress += ctx->dhAnonParams.generatorLen;
if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
return err;
if (ERR(err = SSLAllocBuffer(&ctx->dhPrivate, ctx->dhExchangePublic.length - 16, &ctx->sysCtx)) != 0)
return err;
if (ERR(err = ReadyRandom(&random, ctx)) != 0)
return err;
if ((rsaErr = R_SetupDHAgreement(ctx->dhExchangePublic.data, ctx->dhPrivate.data,
ctx->dhPrivate.length, &ctx->dhAnonParams, &random)) != 0)
{ err = SSLUnknownErr;
return err;
}
progress = SSLEncodeInt(progress, ctx->dhExchangePublic.length, 2);
memcpy(progress, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
progress += ctx->dhExchangePublic.length;
#elif BSAFE
{ A_DH_KEY_AGREE_PARAMS *params;
unsigned int outputLen;
if ((rsaErr = B_GetAlgorithmInfo((POINTER*)¶ms, ctx->dhAnonParams, AI_DHKeyAgree)) != 0)
return SSLUnknownErr;
if (ERR(err = ReadyRandom(&random, ctx)) != 0)
return err;
if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, 128, &ctx->sysCtx)) != 0)
return err;
if ((rsaErr = B_KeyAgreePhase1(ctx->dhAnonParams, ctx->dhExchangePublic.data,
&outputLen, 128, random, NO_SURR)) != 0)
{ err = SSLUnknownErr;
return err;
}
ctx->dhExchangePublic.length = outputLen;
length = 6 + params->prime.len + params->base.len + ctx->dhExchangePublic.length;
keyExch->protocolVersion = SSL_Version_3_0;
keyExch->contentType = SSL_handshake;
if (ERR(err = SSLAllocBuffer(&keyExch->contents, length+4, &ctx->sysCtx)) != 0)
return err;
progress = keyExch->contents.data;
*progress++ = SSL_server_key_exchange;
progress = SSLEncodeInt(progress, length, 3);
progress = SSLEncodeInt(progress, params->prime.len, 2);
memcpy(progress, params->prime.data, params->prime.len);
progress += params->prime.len;
progress = SSLEncodeInt(progress, params->base.len, 2);
memcpy(progress, params->base.data, params->base.len);
progress += params->base.len;
progress = SSLEncodeInt(progress, ctx->dhExchangePublic.length, 2);
memcpy(progress, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
progress += ctx->dhExchangePublic.length;
}
#endif
ASSERT(progress == keyExch->contents.data + keyExch->contents.length);
return SSLNoErr;
}
#endif
SSLErr
SSLProcessServerKeyExchange(SSLBuffer message, SSLContext *ctx)
{ SSLErr err;
switch (ctx->selectedCipherSpec->keyExchangeMethod)
{ case SSL_RSA:
case SSL_RSA_EXPORT:
if (ERR(err = SSLProcessRSAServerKeyExchange(message, ctx)) != 0)
return err;
break;
#if APPLE_DH
case SSL_DH_anon:
if (ERR(err = SSLProcessDHanonServerKeyExchange(message, ctx)) != 0)
return err;
break;
#endif
default:
return ERR(SSLUnsupportedErr);
}
return SSLNoErr;
}
static SSLErr
SSLProcessRSAServerKeyExchange(SSLBuffer message, SSLContext *ctx)
{
SSLErr err;
SSLBuffer tempPubKey, hashOut, hashCtx, clientRandom, serverRandom;
UInt16 modulusLen, exponentLen, signatureLen;
UInt8 *progress, *modulus, *exponent, *signature;
#if _APPLE_CDSA_
UInt8 hash[36];
#else
UInt8 hash[20];
UInt32 outputLen;
#endif
SSLBuffer signedHashes;
signedHashes.data = 0;
hashCtx.data = 0;
if (message.length < 2) {
errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
return ERR(SSLProtocolErr);
}
progress = message.data;
modulusLen = SSLDecodeInt(progress, 2);
modulus = progress + 2;
progress += 2+modulusLen;
if (message.length < 4 + modulusLen) {
errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
return ERR(SSLProtocolErr);
}
exponentLen = SSLDecodeInt(progress, 2);
exponent = progress + 2;
progress += 2+exponentLen;
if (message.length < 6 + modulusLen + exponentLen) {
errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
return ERR(SSLProtocolErr);
}
signatureLen = SSLDecodeInt(progress, 2);
signature = progress + 2;
if (message.length != 6 + modulusLen + exponentLen + signatureLen) {
errorLog0("SSLProcessRSAServerKeyExchange: msg len error 3\n");
return ERR(SSLProtocolErr);
}
#if RSAREF
{
if (ERR(err = SSLAllocBuffer(&signedHashes, (ctx->peerKey.bits + 7)/8, &ctx->sysCtx)) != 0)
return err;
if ((RSAPublicDecrypt(signedHashes.data, &outputLen, signature, signatureLen,
&ctx->peerKey)) != 0)
{ ERR(err = SSLUnknownErr);
goto fail;
}
}
#elif BSAFE
{ B_ALGORITHM_OBJ rsa;
B_ALGORITHM_METHOD *chooser[] = { &AM_MD2, &AM_MD5, &AM_RSA_DECRYPT, 0 };
int rsaResult;
unsigned int decryptLen;
if (ERR(err = SSLAllocBuffer(&signedHashes, 36, &ctx->sysCtx)) != 0)
return err;
if ((rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPublic, 0)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_DecryptInit(rsa, ctx->peerKey, chooser, NO_SURR)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_DecryptUpdate(rsa, signedHashes.data, &decryptLen, 36,
signature, signatureLen, 0, NO_SURR)) != 0)
return SSLUnknownErr;
outputLen = decryptLen;
if ((rsaResult = B_DecryptFinal(rsa, signedHashes.data+outputLen,
&decryptLen, 36-outputLen, 0, NO_SURR)) != 0)
return SSLUnknownErr;
outputLen += decryptLen;
B_DestroyAlgorithmObject(&rsa);
}
#elif _APPLE_CDSA_
#else
#error No Asymmetric crypto module
#endif
#ifndef _APPLE_CDSA_
if (outputLen != 36)
{ ERR(err = SSLProtocolErr);
goto fail;
}
#endif
clientRandom.data = ctx->clientRandom;
clientRandom.length = 32;
serverRandom.data = ctx->serverRandom;
serverRandom.length = 32;
tempPubKey.data = message.data;
tempPubKey.length = modulusLen + exponentLen + 4;
hashOut.data = hash;
hashOut.length = 16;
if (ERR(err = ReadyHash(&SSLHashMD5, &hashCtx, ctx)) != 0)
goto fail;
if (ERR(err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
goto fail;
if (ERR(err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
goto fail;
if (ERR(err = SSLHashMD5.update(hashCtx, tempPubKey)) != 0)
goto fail;
if (ERR(err = SSLHashMD5.final(hashCtx, hashOut)) != 0)
goto fail;
#if _APPLE_CDSA_
hashOut.data = hash + 16;
#else
if ((memcmp(hash, signedHashes.data, 16)) != 0)
{ ERR(err = SSLProtocolErr);
goto fail;
}
#endif
hashOut.length = 20;
if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
goto fail;
if (ERR(err = ReadyHash(&SSLHashSHA1, &hashCtx, ctx)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.update(hashCtx, tempPubKey)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.final(hashCtx, hashOut)) != 0)
goto fail;
#if _APPLE_CDSA_
err = sslRsaRawVerify(ctx,
ctx->peerPubKey,
ctx->peerPubKeyCsp,
hash,
36,
signature,
signatureLen);
if(err) {
errorLog1("SSLProcessRSAServerKeyExchange: sslRsaRawVerify returned %d\n",
err);
goto fail;
}
#else
if ((memcmp(hash, signedHashes.data + 16, 20)) != 0)
{ ERR(err = SSLProtocolErr);
goto fail;
}
#endif
#if RSAREF
memset(&ctx->peerKey, 0, sizeof(R_RSA_PUBLIC_KEY));
memcpy(ctx->peerKey.modulus + (MAX_RSA_MODULUS_LEN - modulusLen),
modulus, modulusLen);
memcpy(ctx->peerKey.exponent + (MAX_RSA_MODULUS_LEN - exponentLen),
exponent, exponentLen);
{ unsigned int bitAdjust;
UInt8 c;
c = modulus[0];
bitAdjust = 8;
while (c != 0)
{ --bitAdjust;
c >>= 1;
}
ctx->peerKey.bits = modulusLen * 8 - bitAdjust;
}
err = SSLNoErr;
#elif BSAFE
{ A_RSA_KEY pubKeyInfo;
int rsaErr;
pubKeyInfo.modulus.data = modulus;
pubKeyInfo.modulus.len = modulusLen;
pubKeyInfo.exponent.data = exponent;
pubKeyInfo.exponent.len = exponentLen;
if ((rsaErr = B_CreateKeyObject(&ctx->peerKey)) != 0)
return SSLUnknownErr;
if ((rsaErr = B_SetKeyInfo(ctx->peerKey, KI_RSAPublic, (POINTER)&pubKeyInfo)) != 0)
return SSLUnknownErr;
}
err = SSLNoErr;
#elif _APPLE_CDSA_
{
SSLBuffer modBuf;
SSLBuffer expBuf;
sslFreeKey(ctx->peerPubKeyCsp,
&ctx->peerPubKey,
NULL);
modBuf.data = modulus;
modBuf.length = modulusLen;
expBuf.data = exponent;
expBuf.length = exponentLen;
err = sslGetPubKeyFromBits(ctx,
&modBuf,
&expBuf,
&ctx->peerPubKey,
&ctx->peerPubKeyCsp);
}
#else
#error No Assymmetric crypto module
#endif
fail:
ERR(SSLFreeBuffer(&signedHashes, &ctx->sysCtx));
ERR(SSLFreeBuffer(&hashCtx, &ctx->sysCtx));
return err;
}
#if APPLE_DH
static SSLErr
SSLProcessDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx)
{ SSLErr err;
UInt8 *progress;
unsigned int totalLength;
if (message.length < 6) {
errorLog1("SSLProcessDHanonServerKeyExchange error: msg len %d\n",
message.length);
return ERR(SSLProtocolErr);
}
progress = message.data;
totalLength = 0;
#if RSAREF
{ SSLBuffer alloc;
UInt8 *prime, *generator, *publicVal;
ctx->peerDHParams.primeLen = SSLDecodeInt(progress, 2);
progress += 2;
prime = progress;
progress += ctx->peerDHParams.primeLen;
totalLength += ctx->peerDHParams.primeLen;
if (message.length < 6 + totalLength)
return ERR(SSLProtocolErr);
ctx->peerDHParams.generatorLen = SSLDecodeInt(progress, 2);
progress += 2;
generator = progress;
progress += ctx->peerDHParams.generatorLen;
totalLength += ctx->peerDHParams.generatorLen;
if (message.length < 6 + totalLength)
return ERR(SSLProtocolErr);
ctx->dhPeerPublic.length = SSLDecodeInt(progress, 2);
progress += 2;
publicVal = progress;
progress += ctx->dhPeerPublic.length;
totalLength += ctx->dhPeerPublic.length;
if (message.length != 6 + totalLength)
return ERR(SSLProtocolErr);
ASSERT(progress == message.data + message.length);
if (ERR(err = SSLAllocBuffer(&alloc, ctx->peerDHParams.primeLen +
ctx->peerDHParams.generatorLen, &ctx->sysCtx)) != 0)
return err;
ctx->peerDHParams.prime = alloc.data;
memcpy(ctx->peerDHParams.prime, prime, ctx->peerDHParams.primeLen);
ctx->peerDHParams.generator = alloc.data + ctx->peerDHParams.primeLen;
memcpy(ctx->peerDHParams.generator, generator, ctx->peerDHParams.generatorLen);
if (ERR(err = SSLAllocBuffer(&ctx->dhPeerPublic,
ctx->dhPeerPublic.length, &ctx->sysCtx)) != 0)
return err;
memcpy(ctx->dhPeerPublic.data, publicVal, ctx->dhPeerPublic.length);
}
#elif BSAFE
{ int rsaErr;
unsigned char *publicVal;
A_DH_KEY_AGREE_PARAMS params;
B_ALGORITHM_METHOD *chooser[] = { &AM_DH_KEY_AGREE, 0 };
params.prime.len = SSLDecodeInt(progress, 2);
progress += 2;
params.prime.data = progress;
progress += params.prime.len;
totalLength += params.prime.len;
if (message.length < 6 + totalLength)
return ERR(SSLProtocolErr);
params.base.len = SSLDecodeInt(progress, 2);
progress += 2;
params.base.data = progress;
progress += params.base.len;
totalLength += params.base.len;
if (message.length < 6 + totalLength)
return ERR(SSLProtocolErr);
ctx->dhPeerPublic.length = SSLDecodeInt(progress, 2);
if (ERR(err = SSLAllocBuffer(&ctx->dhPeerPublic, ctx->dhPeerPublic.length, &ctx->sysCtx)) != 0)
return err;
progress += 2;
publicVal = progress;
progress += ctx->dhPeerPublic.length;
totalLength += ctx->dhPeerPublic.length;
memcpy(ctx->dhPeerPublic.data, publicVal, ctx->dhPeerPublic.length);
if (message.length != 6 + totalLength)
return ERR(SSLProtocolErr);
params.exponentBits = 8 * ctx->dhPeerPublic.length - 1;
if ((rsaErr = B_CreateAlgorithmObject(&ctx->peerDHParams)) != 0)
return SSLUnknownErr;
if ((rsaErr = B_SetAlgorithmInfo(ctx->peerDHParams, AI_DHKeyAgree, (POINTER)¶ms)) != 0)
return SSLUnknownErr;
if ((rsaErr = B_KeyAgreeInit(ctx->peerDHParams, (B_KEY_OBJ) 0, chooser, NO_SURR)) != 0)
return SSLUnknownErr;
}
#endif
return SSLNoErr;
}
#endif
SSLErr
SSLProcessKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
{ SSLErr err;
switch (ctx->selectedCipherSpec->keyExchangeMethod)
{ case SSL_RSA:
case SSL_RSA_EXPORT:
if (ERR(err = SSLDecodeRSAKeyExchange(keyExchange, ctx)) != 0)
return err;
break;
#if APPLE_DH
case SSL_DH_anon:
if (ERR(err = SSLDecodeDHanonKeyExchange(keyExchange, ctx)) != 0)
return err;
break;
#endif
default:
return ERR(SSLUnsupportedErr);
}
return SSLNoErr;
}
static SSLErr
SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
{ SSLErr err;
SSLBuffer result;
UInt32 outputLen, localKeyModulusLen;
SSLRSAPrivateKey *key;
SSLProtocolVersion version;
Boolean useEncryptKey = false;
#if _APPLE_CDSA_
CSSM_CSP_HANDLE cspHand;
CASSERT(ctx->protocolSide == SSL_ServerSide);
#if SSL_SERVER_KEYEXCH_HACK
if((ctx->selectedCipherSpec->keyExchangeMethod == SSL_RSA_EXPORT) &&
(ctx->encryptPrivKey != NULL)) {
useEncryptKey = true;
}
#else
if (ctx->encryptPrivKey) {
useEncryptKey = true;
}
#endif
if (useEncryptKey) {
key = &ctx->encryptPrivKey;
cspHand = ctx->encryptKeyCsp;
}
else {
key = &ctx->signingPrivKey;
cspHand = ctx->signingKeyCsp;
}
#else
if (ctx->selectedCipherSpec->keyExchangeMethod == SSL_RSA_EXPORT)
key = &ctx->exportKey;
else
key = &ctx->localKey;
#endif
result.data = 0;
#if RSAREF
localKeyModulusLen = (key->bits + 7)/8;
#elif BSAFE
{ A_RSA_KEY *keyInfo;
int rsaResult;
if ((rsaResult = B_GetKeyInfo((POINTER*)&keyInfo, *key, KI_RSAPublic)) != 0)
return SSLUnknownErr;
localKeyModulusLen = keyInfo->modulus.len;
}
#elif _APPLE_CDSA_
localKeyModulusLen = sslKeyLengthInBytes(*key);
#else
#error No assymetric crypto module
#endif
if (keyExchange.length != localKeyModulusLen) {
errorLog0("SSLDecodeRSAKeyExchange: length error\n");
return ERR(SSLProtocolErr);
}
#if RSAREF
if (ERR(err = SSLAllocBuffer(&result, localKeyModulusLen, &ctx->sysCtx)) != 0)
return err;
if ((RSAPrivateDecrypt(result.data, &outputLen, keyExchange.data, keyExchange.length, key)) != 0)
{ ERR(err = SSLUnknownErr);
goto fail;
}
#elif BSAFE
{ B_ALGORITHM_OBJ rsa;
B_ALGORITHM_METHOD *chooser[] = { &AM_RSA_DECRYPT, &AM_RSA_CRT_DECRYPT, 0 };
int rsaResult;
unsigned int decryptLen;
if (ERR(err = SSLAllocBuffer(&result, 48, &ctx->sysCtx)) != 0)
return err;
if ((rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPrivate, 0)) != 0)
return SSLUnknownErr;
#ifdef macintosh
if ((rsaResult = B_DecryptInit(rsa, *key, chooser, NO_SURR)) != 0)
return SSLUnknownErr;
#else
if ((rsaResult = B_DecryptInit(rsa, ctx->localKey, chooser, NO_SURR)) != 0)
return SSLUnknownErr;
#endif
if ((rsaResult = B_DecryptUpdate(rsa, result.data, &decryptLen, 48,
keyExchange.data, keyExchange.length, 0, NO_SURR)) != 0)
return SSLUnknownErr;
outputLen = decryptLen;
if ((rsaResult = B_DecryptFinal(rsa, result.data+outputLen,
&decryptLen, 48-outputLen, 0, NO_SURR)) != 0)
return SSLUnknownErr;
outputLen += decryptLen;
B_DestroyAlgorithmObject(&rsa);
}
#elif _APPLE_CDSA_
err = sslRsaDecrypt(ctx,
*key,
cspHand,
keyExchange.data,
keyExchange.length,
result.data,
48,
&outputLen);
if(err) {
goto fail;
}
#endif
if (outputLen != 48)
{
errorLog0("SSLDecodeRSAKeyExchange: outputLen error\n");
ERR(err = SSLProtocolErr);
goto fail;
}
result.length = outputLen;
version = (SSLProtocolVersion)SSLDecodeInt(result.data, 2);
if (version > ctx->negProtocolVersion && version < SSL_Version_3_0) {
errorLog0("SSLDecodeRSAKeyExchange: version error\n");
ERR(err = SSLProtocolErr);
goto fail;
}
if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, 48, &ctx->sysCtx)) != 0)
goto fail;
memcpy(ctx->preMasterSecret.data, result.data, 48);
err = SSLNoErr;
fail:
ERR(SSLFreeBuffer(&result, &ctx->sysCtx));
return err;
}
#if APPLE_DH
static SSLErr
SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
{ SSLErr err;
unsigned int publicLen;
int rsaResult;
publicLen = SSLDecodeInt(keyExchange.data, 2);
#if RSAREF
if (keyExchange.length != publicLen + 2 ||
publicLen != ctx->dhAnonParams.primeLen)
return ERR(SSLProtocolErr);
if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, ctx->dhAnonParams.primeLen, &ctx->sysCtx)) != 0)
return err;
if ((rsaResult = R_ComputeDHAgreedKey (ctx->preMasterSecret.data, ctx->dhPeerPublic.data,
ctx->dhPrivate.data, ctx->dhPrivate.length, &ctx->dhAnonParams)) != 0)
{ err = SSLUnknownErr;
return err;
}
#elif BSAFE
{ unsigned int amount;
if (keyExchange.length != publicLen + 2)
return ERR(SSLProtocolErr);
if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, 128, &ctx->sysCtx)) != 0)
return err;
if ((rsaResult = B_KeyAgreePhase2(ctx->dhAnonParams, ctx->preMasterSecret.data,
&amount, 128, keyExchange.data+2, publicLen, NO_SURR)) != 0)
return err;
ctx->preMasterSecret.length = amount;
}
#endif
return SSLNoErr;
}
#endif
SSLErr
SSLEncodeKeyExchange(SSLRecord *keyExchange, SSLContext *ctx)
{ SSLErr err;
CASSERT(ctx->protocolSide == SSL_ClientSide);
switch (ctx->selectedCipherSpec->keyExchangeMethod)
{ case SSL_RSA:
case SSL_RSA_EXPORT:
if (ERR(err = SSLEncodeRSAKeyExchange(keyExchange, ctx)) != 0)
return err;
break;
#if APPLE_DH
case SSL_DH_anon:
if (ERR(err = SSLEncodeDHanonKeyExchange(keyExchange, ctx)) != 0)
return err;
break;
#endif
default:
return ERR(SSLUnsupportedErr);
}
return SSLNoErr;
}
static SSLErr
SSLEncodeRSAKeyExchange(SSLRecord *keyExchange, SSLContext *ctx)
{ SSLErr err;
UInt32 outputLen, peerKeyModulusLen;
#if !_APPLE_CDSA_
SSLRandomCtx rsaRandom;
int rsaResult;
#endif
if (ERR(err = SSLEncodeRSAPremasterSecret(ctx)) != 0)
return err;
#if !_APPLE_CDSA_
if (ERR(err = ReadyRandom(&rsaRandom, ctx)) != 0)
return err;
#endif
keyExchange->contentType = SSL_handshake;
keyExchange->protocolVersion = SSL_Version_3_0;
#if RSAREF
peerKeyModulusLen = (ctx->peerKey.bits + 7)/8;
#elif BSAFE
{ A_RSA_KEY *keyInfo;
if ((rsaResult = B_GetKeyInfo((POINTER*)&keyInfo, ctx->peerKey, KI_RSAPublic)) != 0)
return SSLUnknownErr;
peerKeyModulusLen = keyInfo->modulus.len;
}
#elif _APPLE_CDSA_
peerKeyModulusLen = sslKeyLengthInBytes(ctx->peerPubKey);
#else
#error No Assymetric Crypto
#endif
if (ERR(err = SSLAllocBuffer(&keyExchange->contents,peerKeyModulusLen + 4,&ctx->sysCtx)) != 0)
{
#if RSAREF
R_RandomFinal(&rsaRandom);
#elif BSAFE
B_DestroyAlgorithmObject(&rsaRandom);
#endif
return err;
}
keyExchange->contents.data[0] = SSL_client_key_exchange;
SSLEncodeInt(keyExchange->contents.data + 1, peerKeyModulusLen, 3);
#if RSAREF
if ((rsaResult = RSAPublicEncrypt(keyExchange->contents.data+4, &outputLen,
ctx->preMasterSecret.data, 48,
&ctx->peerKey,&rsaRandom)) != 0)
{ R_RandomFinal(&rsaRandom);
return ERR(SSLUnknownErr);
}
R_RandomFinal(&rsaRandom);
#elif BSAFE
{ B_ALGORITHM_OBJ rsa;
B_ALGORITHM_METHOD *chooser[] = { &AM_RSA_ENCRYPT, 0 };
int rsaResult;
unsigned int encryptedOut;
if ((rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPublic, 0)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_EncryptInit(rsa, ctx->peerKey, chooser, NO_SURR)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_EncryptUpdate(rsa, keyExchange->contents.data+4,
&encryptedOut, peerKeyModulusLen, ctx->preMasterSecret.data, 48, rsaRandom, NO_SURR)) != 0)
return SSLUnknownErr;
outputLen = encryptedOut;
if ((rsaResult = B_EncryptFinal(rsa, keyExchange->contents.data+4+outputLen,
&encryptedOut, peerKeyModulusLen-outputLen, rsaRandom, NO_SURR)) != 0)
return SSLUnknownErr;
outputLen += encryptedOut;
B_DestroyAlgorithmObject(&rsa);
}
B_DestroyAlgorithmObject(&rsaRandom);
#elif _APPLE_CDSA_
err = sslRsaEncrypt(ctx,
ctx->peerPubKey,
ctx->peerPubKeyCsp,
ctx->preMasterSecret.data,
48,
keyExchange->contents.data+4,
peerKeyModulusLen,
&outputLen);
if(err) {
return err;
}
#endif
CASSERT(outputLen + 4 == keyExchange->contents.length);
return SSLNoErr;
}
#if APPLE_DH
static SSLErr
SSLEncodeDHanonKeyExchange(SSLRecord *keyExchange, SSLContext *ctx)
{ SSLErr err;
unsigned int outputLen;
if (ERR(err = SSLEncodeDHPremasterSecret(ctx)) != 0)
return err;
outputLen = ctx->dhExchangePublic.length + 2;
keyExchange->contentType = SSL_handshake;
keyExchange->protocolVersion = SSL_Version_3_0;
if (ERR(err = SSLAllocBuffer(&keyExchange->contents,outputLen + 4,&ctx->sysCtx)) != 0)
return err;
keyExchange->contents.data[0] = SSL_client_key_exchange;
SSLEncodeInt(keyExchange->contents.data+1, ctx->dhExchangePublic.length+2, 3);
SSLEncodeInt(keyExchange->contents.data+4, ctx->dhExchangePublic.length, 2);
memcpy(keyExchange->contents.data+6, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
return SSLNoErr;
}
#endif