📄 hdskkyex.c
字号:
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 /* RSAREF / BSAFE */
ASSERT(progress == keyExch->contents.data + keyExch->contents.length);
return SSLNoErr;
}
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;
case SSL_DH_anon:
if (ERR(err = SSLProcessDHanonServerKeyExchange(message, ctx)) != 0)
return err;
break;
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;
uint8 hash[20];
unsigned int outputLen;
SSLBuffer signedHashes;
signedHashes.data = 0;
hashCtx.data = 0;
if (message.length < 2)
return ERR(SSLProtocolErr);
progress = message.data;
modulusLen = SSLDecodeInt(progress, 2);
modulus = progress + 2;
progress += 2+modulusLen;
if (message.length < 4 + modulusLen)
return ERR(SSLProtocolErr);
exponentLen = SSLDecodeInt(progress, 2);
exponent = progress + 2;
progress += 2+exponentLen;
if (message.length < 6 + modulusLen + exponentLen)
return ERR(SSLProtocolErr);
signatureLen = SSLDecodeInt(progress, 2);
signature = progress + 2;
if (message.length != 6 + modulusLen + exponentLen + signatureLen)
return ERR(SSLProtocolErr);
#if RSAREF
{ /* Allocate room for the signed hashes; RSA can encrypt data
as long as the modulus */
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;
/* Allocate room for the signed hashes; BSAFE makes sure we don't decode too much data */
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);
}
#endif
if (outputLen != 36)
{ ERR(err = SSLProtocolErr);
goto fail;
}
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 ((memcmp(hash, signedHashes.data, 16)) != 0)
{ ERR(err = SSLProtocolErr);
goto fail;
}
if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
goto fail;
hashOut.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, tempPubKey)) != 0)
goto fail;
if (ERR(err = SSLHashSHA1.final(hashCtx, hashOut)) != 0)
goto fail;
if ((memcmp(hash, signedHashes.data + 16, 20)) != 0)
{ ERR(err = SSLProtocolErr);
goto fail;
}
/* Signature matches; now replace server key with new key */
#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);
/* Adjust bit length for leading zeros in value; assume no more than 8 leading zero bits */
{ unsigned int bitAdjust;
uint8 c;
c = modulus[0];
bitAdjust = 8;
while (c != 0)
{ --bitAdjust;
c >>= 1;
}
ctx->peerKey.bits = modulusLen * 8 - bitAdjust;
}
#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;
}
#endif /* RSAREF / BSAFE */
err = SSLNoErr;
fail:
ERR(SSLFreeBuffer(&signedHashes, &ctx->sysCtx));
ERR(SSLFreeBuffer(&hashCtx, &ctx->sysCtx));
return err;
}
static SSLErr
SSLProcessDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx)
{ SSLErr err;
uint8 *progress;
unsigned int totalLength;
if (message.length < 6)
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -