⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl2prot.c

📁 Netscape公司提供的安全套接字层
💻 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 + -