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

📄 ssl2mesg.c

📁 Netscape公司提供的安全套接字层
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  *********************************************************************
    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 + -