📄 ssl2mesg.c
字号:
/* *********************************************************************
File: ssl2mesg.c
SSLRef 3.0 Final -- 11/19/96
Copyright (c)1996 by Netscape Communications Corp.
By retrieving this software you are bound by the licensing terms
disclosed in the file "LICENSE.txt". Please read it, and if you don't
accept the terms, delete this software.
SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
View, California <http://home.netscape.com/> and Consensus Development
Corporation of Berkeley, California <http://www.consensus.com/>.
*********************************************************************
File: ssl2mesg.c Message encoding and decoding functions for SSL 2
The necessary message encoding and decoding for all SSL 2 handshake
messages.
****************************************************************** */
#ifndef _SSL_H_
#include "ssl.h"
#endif
#ifndef _SSL2_H_
#include "ssl2.h"
#endif
#ifndef _SSLREC_H_
#include "sslrec.h"
#endif
#ifndef _SSLALLOC_H_
#include "sslalloc.h"
#endif
#ifndef _SSLCTX_H_
#include "sslctx.h"
#endif
#ifndef _SSLALERT_H_
#include "sslalert.h"
#endif
#ifndef _SSLHDSHK_H_
#include "sslhdshk.h"
#endif
#ifndef _SSLSESS_H_
#include "sslsess.h"
#endif
#ifndef _X509_H_
#include "x509.h"
#endif
#include <string.h>
SSLErr
SSL2ProcessClientHello(SSLBuffer msg, SSLContext *ctx)
{ SSLErr err;
uint8 *progress, *cipherList;
int i, j, cipherKindCount, sessionIDLen, challengeLen;
SSL2CipherKind cipherKind;
CipherSuite matchingCipher, selectedCipher;
SSLProtocolVersion version;
if (msg.length < 27)
return ERR(SSLProtocolErr);
progress = msg.data;
version = (SSLProtocolVersion)SSLDecodeInt(progress, 2);
if (ctx->protocolVersion == SSL_Version_Undetermined)
{ if (version > SSL_Version_3_0)
version = SSL_Version_3_0;
ctx->protocolVersion = version;
}
else if (ctx->protocolVersion == SSL_Version_3_0_With_2_0_Hello)
{ if (version < SSL_Version_3_0)
return ERR(SSLProtocolErr);
ctx->protocolVersion = SSL_Version_3_0;
}
progress += 2;
cipherKindCount = SSLDecodeInt(progress, 2);
progress += 2;
if (cipherKindCount % 3 != 0)
return ERR(SSLProtocolErr);
cipherKindCount /= 3;
sessionIDLen = SSLDecodeInt(progress, 2);
progress += 2;
challengeLen = SSLDecodeInt(progress, 2);
progress += 2;
if (msg.length != 8 + 3*cipherKindCount + sessionIDLen + challengeLen ||
(sessionIDLen != 0 && sessionIDLen != 16) ||
challengeLen < 16 || challengeLen > 32 )
return ERR(SSLProtocolErr);
cipherList = progress;
selectedCipher = SSL_NO_SUCH_CIPHERSUITE;
if (ctx->protocolVersion == SSL_Version_3_0) /* If we're negotiating an SSL 3.0 session, use SSL 3.0 suites first */
{ for (i = 0; i < cipherKindCount; i++)
{ cipherKind = (SSL2CipherKind)SSLDecodeInt(progress, 3);
progress += 3;
if (selectedCipher != SSL_NO_SUCH_CIPHERSUITE)
continue;
if ((((uint32)cipherKind) & 0xFF0000) != 0)
continue; /* Skip SSL 2 suites */
matchingCipher = (CipherSuite)((uint32)cipherKind & 0x00FFFF);
for (j = 0; j < CipherSpecCount; j++)
if (KnownCipherSpecs[j].cipherSpec == matchingCipher)
{ selectedCipher = matchingCipher;
break;
}
}
}
progress = cipherList;
for (i = 0; i < cipherKindCount; i++)
{ cipherKind = (SSL2CipherKind)SSLDecodeInt(progress, 3);
progress += 3;
if (selectedCipher == SSL_NO_SUCH_CIPHERSUITE) /* After we find one, just keep advancing progress past the unused ones */
{ if ((((uint32)cipherKind) & 0xFF0000) != 0) /* If it's a real SSL2 spec, look for it in the list */
{ matchingCipher = SSL_NO_SUCH_CIPHERSUITE;
for (j = 0; j < SSL2CipherMapCount; j++)
if (cipherKind == SSL2CipherMap[j].cipherKind)
{ matchingCipher = SSL2CipherMap[j].cipherSuite;
break;
}
}
else /* if the first byte is zero, it's an encoded SSL 3 CipherSuite */
matchingCipher = (CipherSuite)((uint32)cipherKind & 0x00FFFF);
if (matchingCipher != SSL_NO_SUCH_CIPHERSUITE)
for (j = 0; j < CipherSpecCount; j++)
if (KnownCipherSpecs[j].cipherSpec == matchingCipher)
{ selectedCipher = matchingCipher;
break;
}
}
}
if (selectedCipher == SSL_NO_SUCH_CIPHERSUITE)
return ERR(SSLNegotiationErr);
ctx->selectedCipher = selectedCipher;
if (ERR(err = FindCipherSpec(ctx->selectedCipher, &ctx->selectedCipherSpec)) != 0)
return err;
if (sessionIDLen > 0 && ctx->peerID.data != 0)
{ /* Don't die on error; just treat it as an uncacheable session */
ERR(err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen, &ctx->sysCtx));
if (err == 0)
memcpy(ctx->sessionID.data, progress, sessionIDLen);
}
progress += sessionIDLen;
ctx->ssl2ChallengeLength = challengeLen;
memset(ctx->clientRandom, 0, 32);
memcpy(ctx->clientRandom+32 - challengeLen, progress, challengeLen);
progress += challengeLen;
ASSERT(progress == msg.data + msg.length);
return SSLNoErr;
}
SSLErr
SSL2EncodeClientHello(SSLBuffer *msg, SSLContext *ctx)
{ SSLErr err;
uint8 *progress;
int i, j, useSSL3Ciphers, totalCipherCount;
int sessionIDLen;
uint16 version;
SSLBuffer sessionIdentifier, randomData;
switch (ctx->protocolVersion)
{ case SSL_Version_Undetermined:
case SSL_Version_3_0_With_2_0_Hello:
useSSL3Ciphers = 1;
version = SSL_Version_3_0;
break;
case SSL_Version_2_0:
useSSL3Ciphers = 0;
version = SSL_Version_2_0;
break;
case SSL_Version_3_0_Only:
case SSL_Version_3_0:
default:
ASSERTMSG("Bad protocol version for sending SSL 2 Client Hello");
break;
}
if (useSSL3Ciphers != 0)
totalCipherCount = CipherSpecCount;
else
totalCipherCount = 0;
for (i = 0; i < SSL2CipherMapCount; i++)
for (j = 0; j < CipherSpecCount; j++)
if (KnownCipherSpecs[j].cipherSpec == SSL2CipherMap[i].cipherSuite)
{ totalCipherCount++;
break;
}
sessionIDLen = 0;
sessionIdentifier.data = 0;
if (ctx->resumableSession.data != 0)
{ if (ERR(err = SSLRetrieveSessionIDIdentifier(ctx->resumableSession, &sessionIdentifier, ctx)) != 0)
return err;
sessionIDLen = sessionIdentifier.length;
}
/* msg length = 9 + 3 * totalCipherCount + sessionIDLen + 16 bytes of challenge
* Use exactly 16 bytes of challenge because Netscape products have a bug
* that requires this length
*/
if (ERR(err = SSLAllocBuffer(msg, 9 + (3*totalCipherCount) + sessionIDLen + 16, &ctx->sysCtx)) != 0)
{ ERR(SSLFreeBuffer(&sessionIdentifier, &ctx->sysCtx));
return err;
}
progress = msg->data;
*progress++ = ssl2_mt_client_hello;
progress = SSLEncodeInt(progress, version, 2);
progress = SSLEncodeInt(progress, 3*totalCipherCount, 2);
progress = SSLEncodeInt(progress, sessionIDLen, 2);
progress = SSLEncodeInt(progress, 16, 2);
/* If we can send SSL3 ciphers, encode the two-byte cipher specs into three-byte
* CipherKinds which have a leading 0.
*/
if (useSSL3Ciphers != 0)
for (i = 0; i < CipherSpecCount; i++)
progress = SSLEncodeInt(progress, KnownCipherSpecs[i].cipherSpec, 3);
/* Now send those SSL2 specs for which we have implementations */
for (i = 0; i < SSL2CipherMapCount; i++)
for (j = 0; j < CipherSpecCount; j++)
if (KnownCipherSpecs[j].cipherSpec == SSL2CipherMap[i].cipherSuite)
{ progress = SSLEncodeInt(progress, SSL2CipherMap[i].cipherKind, 3);
break;
}
if (sessionIDLen > 0)
{ memcpy(progress, sessionIdentifier.data, sessionIDLen);
progress += sessionIDLen;
ERR(SSLFreeBuffer(&sessionIdentifier, &ctx->sysCtx));
}
randomData.data = progress;
randomData.length = 16;
if (ERR(err = ctx->sysCtx.random(randomData, ctx->sysCtx.randomRef)) != 0)
{ ERR(SSLFreeBuffer(msg, &ctx->sysCtx));
return err;
}
progress += 16;
/* Zero out the first 16 bytes of clientRandom, and store the challenge in the
second 16 bytes */
memset(ctx->clientRandom, 0, 16);
memcpy(ctx->clientRandom+16, randomData.data, 16);
ctx->ssl2ChallengeLength = 16;
ASSERT(progress == msg->data + msg->length);
return SSLNoErr;
}
SSLErr
SSL2ProcessClientMasterKey(SSLBuffer msg, SSLContext *ctx)
{ SSLErr err;
SSL2CipherKind cipherKind;
SSLBuffer secretData;
int clearLength, encryptedLength, keyArgLength;
unsigned int secretLength, localKeyModulusLen;
uint8 *progress;
if (msg.length < 9)
return ERR(SSLProtocolErr);
progress = msg.data;
cipherKind = (SSL2CipherKind)SSLDecodeInt(progress, 3);
progress += 3;
clearLength = SSLDecodeInt(progress, 2);
progress += 2;
encryptedLength = SSLDecodeInt(progress, 2);
progress += 2;
keyArgLength = SSLDecodeInt(progress, 2);
progress += 2;
if (msg.length != 9 + clearLength + encryptedLength + keyArgLength)
return ERR(SSLProtocolErr);
/* Master key == CLEAR_DATA || SECRET_DATA */
memcpy(ctx->masterSecret, progress, clearLength);
progress += clearLength;
#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;
}
#endif /* RSAREF / BSAFE */
if (encryptedLength != localKeyModulusLen)
return ERR(SSLProtocolErr);
/* Allocate enough room to hold any decrypted value */
if (ERR(err = SSLAllocBuffer(&secretData, encryptedLength, &ctx->sysCtx)) != 0)
return err;
#if RSAREF
/* Replace this with code to do decryption at lower level & check PKCS1 padding
for rollback attack */
if ((RSAPrivateDecrypt(secretData.data, &secretLength, progress, encryptedLength, &ctx->localKey)) != 0)
{ ERR(err = SSLFreeBuffer(&secretData, &ctx->sysCtx));
return ERR(SSLUnknownErr);
}
#elif BSAFE
{ B_ALGORITHM_OBJ rsa;
B_ALGORITHM_METHOD *chooser[] = { &AM_RSA_CRT_DECRYPT, 0 };
int rsaResult;
unsigned int decryptLen;
if ((rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPrivate, 0)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_DecryptInit(rsa, ctx->localKey, chooser, NO_SURR)) != 0)
return SSLUnknownErr;
if ((rsaResult = B_DecryptUpdate(rsa, secretData.data, &decryptLen, encryptedLength,
progress, encryptedLength, 0, NO_SURR)) != 0)
return SSLUnknownErr;
secretLength = decryptLen;
if ((rsaResult = B_DecryptFinal(rsa, secretData.data+secretLength,
&decryptLen, encryptedLength-secretLength, 0, NO_SURR)) != 0)
return SSLUnknownErr;
secretLength += decryptLen;
B_DestroyAlgorithmObject(&rsa);
}
#endif /* RSAREF / BSAFE */
progress += encryptedLength;
if (clearLength + secretLength != ctx->selectedCipherSpec->cipher->keySize)
return ERR(SSLProtocolErr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -