📄 ssl2prot.c
字号:
/* *********************************************************************
File: ssl2prot.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: ssl2prot.c Protocol engine for SSL 2
This is the heart of the SSL 2 implementation, including the state
engine for proceeding through the handshake and the necessary code
for installing negotiated keys and algorithms.
****************************************************************** */
#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 _SSLHDSHK_H_
#include "sslhdshk.h"
#endif
#ifndef _SSLSESS_H_
#include "sslsess.h"
#endif
#ifndef _SSLALERT_H_
#include "sslalert.h"
#endif
#include <string.h>
SSLErr
SSL2ProcessMessage(SSLRecord rec, SSLContext *ctx)
{ SSLErr err;
SSL2MessageType msg;
SSLBuffer contents;
if (rec.contents.length < 2)
return ERR(SSLProtocolErr);
msg = (SSL2MessageType)rec.contents.data[0];
contents.data = rec.contents.data + 1;
contents.length = rec.contents.length - 1;
switch (msg)
{ case ssl2_mt_error:
break;
case ssl2_mt_client_hello:
if (ctx->state != HandshakeServerIdle)
return ERR(SSLProtocolErr);
ERR(err = SSL2ProcessClientHello(contents, ctx));
if (err == SSLNegotiationErr)
ERR(SSL2SendError(ssl2_pe_no_cipher, ctx));
break;
case ssl2_mt_client_master_key:
if (ctx->state != HandshakeSSL2ClientMasterKey)
return ERR(SSLProtocolErr);
ERR(err = SSL2ProcessClientMasterKey(contents, ctx));
break;
case ssl2_mt_client_finished:
if (ctx->state != HandshakeSSL2ClientFinished)
return ERR(SSLProtocolErr);
ERR(err = SSL2ProcessClientFinished(contents, ctx));
break;
case ssl2_mt_server_hello:
if (ctx->state != HandshakeSSL2ServerHello &&
ctx->state != HandshakeServerHelloUnknownVersion)
return ERR(SSLProtocolErr);
ERR(err = SSL2ProcessServerHello(contents, ctx));
if (err == SSLNegotiationErr)
ERR(SSL2SendError(ssl2_pe_no_cipher, ctx));
break;
case ssl2_mt_server_verify:
if (ctx->state != HandshakeSSL2ServerVerify)
return ERR(SSLProtocolErr);
ERR(err = SSL2ProcessServerVerify(contents, ctx));
break;
case ssl2_mt_server_finished:
if (ctx->state != HandshakeSSL2ServerFinished)
return ERR(SSLProtocolErr);
ERR(err = SSL2ProcessServerFinished(contents, ctx));
break;
case ssl2_mt_request_certificate:
/* Don't process the request; we don't support client certification */
break;
case ssl2_mt_client_certificate:
return ERR(SSLProtocolErr);
break;
default:
DEBUGVAL1("Unknown message %d", msg);
return ERR(SSLProtocolErr);
break;
}
if (err == 0)
{ if (msg == ssl2_mt_client_hello && ctx->protocolVersion == SSL_Version_3_0)
{ /* Promote this message to SSL 3 protocol */
if (ERR(err = SSL3ReceiveSSL2ClientHello(rec, ctx)) != 0)
return err;
}
else
ERR(err = SSL2AdvanceHandshake(msg, ctx));
}
return err;
}
SSLErr
SSL2AdvanceHandshake(SSL2MessageType msg, SSLContext *ctx)
{ SSLErr err;
err = SSLNoErr;
switch (msg)
{ case ssl2_mt_kickstart_handshake:
if (ctx->protocolVersion == SSL_Version_3_0_With_2_0_Hello ||
ctx->protocolVersion == SSL_Version_Undetermined)
if (ERR(err = SSLInitMessageHashes(ctx)) != 0)
return err;
if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeClientHello, ctx)) != 0)
return err;
switch (ctx->protocolVersion)
{ case SSL_Version_Undetermined:
ctx->state = HandshakeServerHelloUnknownVersion;
break;
case SSL_Version_3_0_With_2_0_Hello:
ctx->protocolVersion = SSL_Version_3_0;
ctx->state = HandshakeServerHello;
break;
case SSL_Version_2_0:
ctx->state = HandshakeSSL2ServerHello;
break;
case SSL_Version_3_0_Only:
case SSL_Version_3_0:
default:
ASSERTMSG("Bad protocol version for sending SSL 2 Client Hello");
break;
}
break;
case ssl2_mt_client_hello:
if (ERR(err = SSL2CompareSessionIDs(ctx)) != 0)
return err;
if (ctx->ssl2SessionMatch == 0)
if (ERR(err = SSL2GenerateSessionID(ctx)) != 0)
return err;
if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeServerHello, ctx)) != 0)
return err;
if (ctx->ssl2SessionMatch == 0)
{ ctx->state = HandshakeSSL2ClientMasterKey;
break;
}
if (ERR(err = SSL2InstallSessionKey(ctx)) != 0)
return err;
/* Fall through for matching session; lame, but true */
case ssl2_mt_client_master_key:
if (ERR(err = SSL2InitCiphers(ctx)) != 0)
return err;
if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeServerVerify, ctx)) != 0)
return err;
if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeServerFinished, ctx)) != 0)
return err;
ctx->state = HandshakeSSL2ClientFinished;
break;
case ssl2_mt_server_hello:
if (ctx->ssl2SessionMatch == 0)
{ if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeClientMasterKey, ctx)) != 0)
return err;
}
else
{ if (ERR(err = SSL2InstallSessionKey(ctx)) != 0)
return err;
}
if (ERR(err = SSL2InitCiphers(ctx)) != 0)
return err;
if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeClientFinished, ctx)) != 0)
return err;
ctx->state = HandshakeSSL2ServerVerify;
break;
case ssl2_mt_client_finished:
/* Handshake is complete; turn ciphers on */
ctx->writeCipher.ready = 1;
ctx->readCipher.ready = 1;
if (ctx->peerID.data != 0)
ERR(SSLAddSessionID(ctx));
break;
case ssl2_mt_server_verify:
ctx->state = HandshakeSSL2ServerFinished;
break;
case ssl2_mt_request_certificate:
if (ERR(err = SSL2SendError(ssl2_pe_no_certificate, ctx)) != 0)
return err;
break;
case ssl2_mt_server_finished:
/* Handshake is complete; turn ciphers on */
ctx->writeCipher.ready = 1;
ctx->readCipher.ready = 1;
if (ctx->peerID.data != 0)
ERR(SSLAddSessionID(ctx));
break;
case ssl2_mt_error:
case ssl2_mt_client_certificate:
return ERR(SSLProtocolErr);
break;
}
return SSLNoErr;
}
SSLErr
SSL2PrepareAndQueueMessage(EncodeSSL2MessageFunc encodeFunc, SSLContext *ctx)
{ SSLErr err;
SSLRecord rec;
rec.contentType = SSL_version_2_0_record;
rec.protocolVersion = SSL_Version_2_0;
if (ERR(err = encodeFunc(&rec.contents, ctx)) != 0)
return err;
if (ERR(err = SSLWriteRecord(rec, ctx)) != 0)
{ ERR(SSLFreeBuffer(&rec.contents, &ctx->sysCtx));
return err;
}
if (ctx->protocolVersion == SSL_Version_3_0_With_2_0_Hello ||
ctx->protocolVersion == SSL_Version_Undetermined)
if (ERR(err = SSLHashSHA1.update(ctx->shaState, rec.contents)) != 0 ||
ERR(err = SSLHashMD5.update(ctx->md5State, rec.contents)) != 0)
return err;
ERR(err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx));
return err;
}
SSLErr
SSL2CompareSessionIDs(SSLContext *ctx)
{ SSLErr err;
SSLBuffer sessionIdentifier;
ctx->ssl2SessionMatch = 0;
if (ctx->resumableSession.data == 0)
return SSLNoErr;
if (ERR(err = SSLRetrieveSessionIDIdentifier(ctx->resumableSession,
&sessionIdentifier, ctx)) != 0)
return err;
if (sessionIdentifier.length == ctx->sessionID.length &&
memcmp(sessionIdentifier.data, ctx->sessionID.data, sessionIdentifier.length) == 0)
ctx->ssl2SessionMatch = 1;
if (ERR(err = SSLFreeBuffer(&sessionIdentifier, &ctx->sysCtx)) != 0)
return err;
return SSLNoErr;
}
SSLErr
SSL2InstallSessionKey(SSLContext *ctx)
{ SSLErr err;
ASSERT(ctx->ssl2SessionMatch != 0);
ASSERT(ctx->resumableSession.data != 0);
if (ERR(err = SSLInstallSessionID(ctx->resumableSession, ctx)) != 0)
return err;
return SSLNoErr;
}
SSLErr
SSL2GenerateSessionID(SSLContext *ctx)
{ SSLErr err;
if (ERR(err = SSLFreeBuffer(&ctx->sessionID, &ctx->sysCtx)) != 0)
return err;
if (ERR(err = SSLAllocBuffer(&ctx->sessionID, SSL_SESSION_ID_LEN, &ctx->sysCtx)) != 0)
return err;
if (ERR(err = ctx->sysCtx.random(ctx->sessionID, ctx->sysCtx.randomRef)) != 0)
return err;
return SSLNoErr;
}
SSLErr
SSL2InitCiphers(SSLContext *ctx)
{ SSLErr err;
int keyMaterialLen;
SSLBuffer keyData;
uint8 variantChar, *progress, *readKey, *writeKey, *iv;
SSLBuffer hashDigest, hashContext, masterKey, challenge, connectionID, variantData;
keyMaterialLen = 2 * ctx->selectedCipherSpec->cipher->keySize;
if (ERR(err = SSLAllocBuffer(&keyData, keyMaterialLen, &ctx->sysCtx)) != 0)
return err;
ASSERT(keyMaterialLen % SSLHashMD5.digestSize == 0);
masterKey.data = ctx->masterSecret;
masterKey.length = ctx->selectedCipherSpec->cipher->keySize;
challenge.data = ctx->clientRandom + 32 - ctx->ssl2ChallengeLength;
challenge.length = ctx->ssl2ChallengeLength;
connectionID.data = ctx->serverRandom;
connectionID.length = ctx->ssl2ConnectionIDLength;
variantData.data = &variantChar;
variantData.length = 1;
if (ERR(err = SSLAllocBuffer(&hashContext, SSLHashMD5.contextSize, &ctx->sysCtx)) != 0)
{ ERR(SSLFreeBuffer(&keyData, &ctx->sysCtx));
return err;
}
variantChar = 0x30; /* '0' */
progress = keyData.data;
while (keyMaterialLen)
{ hashDigest.data = progress;
hashDigest.length = SSLHashMD5.digestSize;
if (ERR(err = SSLHashMD5.init(hashContext)) != 0 ||
ERR(err = SSLHashMD5.update(hashContext, masterKey)) != 0 ||
ERR(err = SSLHashMD5.update(hashContext, variantData)) != 0 ||
ERR(err = SSLHashMD5.update(hashContext, challenge)) != 0 ||
ERR(err = SSLHashMD5.update(hashContext, connectionID)) != 0 ||
ERR(err = SSLHashMD5.final(hashContext, hashDigest)) != 0)
{ SSLFreeBuffer(&keyData, &ctx->sysCtx);
SSLFreeBuffer(&hashContext, &ctx->sysCtx);
return err;
}
progress += hashDigest.length;
++variantChar;
keyMaterialLen -= hashDigest.length;
}
ASSERT(progress == keyData.data + keyData.length);
if (ERR(err = SSLFreeBuffer(&hashContext, &ctx->sysCtx)) != 0)
{ ERR(SSLFreeBuffer(&keyData, &ctx->sysCtx));
return err;
}
ctx->readPending.hash = ctx->selectedCipherSpec->macAlgorithm;
ctx->writePending.hash = ctx->selectedCipherSpec->macAlgorithm;
ctx->readPending.symCipher = ctx->selectedCipherSpec->cipher;
ctx->writePending.symCipher = ctx->selectedCipherSpec->cipher;
ctx->readPending.sequenceNum = ctx->readCipher.sequenceNum;
ctx->writePending.sequenceNum = ctx->writeCipher.sequenceNum;
if (ctx->protocolSide == SSL_ServerSide)
{ writeKey = keyData.data;
readKey = keyData.data + ctx->selectedCipherSpec->cipher->keySize;
}
else
{ readKey = keyData.data;
writeKey = keyData.data + ctx->selectedCipherSpec->cipher->keySize;
}
iv = ctx->masterSecret + ctx->selectedCipherSpec->cipher->keySize;
if (ERR(err = ctx->readPending.symCipher->initialize(readKey, iv,
&ctx->readPending.symCipherState, ctx)) != 0 ||
ERR(err = ctx->writePending.symCipher->initialize(writeKey, iv,
&ctx->writePending.symCipherState, ctx)) != 0)
{ ERR(SSLFreeBuffer(&keyData, &ctx->sysCtx));
return err;
}
memcpy(ctx->readPending.macSecret, readKey, ctx->selectedCipherSpec->cipher->keySize);
memcpy(ctx->writePending.macSecret, writeKey, ctx->selectedCipherSpec->cipher->keySize);
if (ERR(err = SSLFreeBuffer(&keyData, &ctx->sysCtx)) != 0)
return err;
ctx->readCipher = ctx->readPending;
ctx->writeCipher = ctx->writePending;
memset(&ctx->readPending, 0, sizeof(CipherContext)); /* Zero out old data */
memset(&ctx->writePending, 0, sizeof(CipherContext)); /* Zero out old data */
return SSLNoErr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -