hdskhelo.c

来自「Netscape公司提供的安全套接字层」· C语言 代码 · 共 279 行

C
279
字号
/*  *********************************************************************
    File: hdskhelo.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: hdskhelo.c   Support for client hello and server hello messages

    Also, encoding of Random structures and initializing the message
    hashes used for calculating finished and certificate verify messages.

    ****************************************************************** */

#ifndef _SSLCTX_H_
#include "sslctx.h"
#endif

#ifndef _SSLHDSHK_H_
#include "sslhdshk.h"
#endif

#ifndef _SSLALLOC_H_
#include "sslalloc.h"
#endif

#ifndef _SSLSESS_H_
#include "sslsess.h"
#endif

#include <string.h>

static SSLErr SSLEncodeRandom(unsigned char *p, SSLContext *ctx);

SSLErr
SSLEncodeServerHello(SSLRecord *serverHello, SSLContext *ctx)
{   SSLErr          err;
    uint8           *progress;
    int             sessionIDLen;
    
    sessionIDLen = 0;
    if (ctx->sessionID.data != 0)
        sessionIDLen = (uint8)ctx->sessionID.length;
    serverHello->protocolVersion = SSL_Version_3_0;
    serverHello->contentType = SSL_handshake;
    if ((err = SSLAllocBuffer(&serverHello->contents, 42 + sessionIDLen, &ctx->sysCtx)) != 0)
        return err;
    
    progress = serverHello->contents.data;
    *progress++ = SSL_server_hello;
    progress = SSLEncodeInt(progress, 38 + sessionIDLen, 3);
    progress = SSLEncodeInt(progress, SSL_Version_3_0, 2);
    if ((err = SSLEncodeRandom(progress, ctx)) != 0)
        return err;
    memcpy(ctx->serverRandom, progress, 32);
    progress += 32;
    *(progress++) = (uint8)sessionIDLen;
    if (sessionIDLen > 0)
        memcpy(progress, ctx->sessionID.data, sessionIDLen);
    progress += sessionIDLen;
    progress = SSLEncodeInt(progress, ctx->selectedCipher, 2);
    *(progress++) = 0;      /* Null compression */
    
    ASSERT(progress == serverHello->contents.data + serverHello->contents.length);
    
    return SSLNoErr;
}

SSLErr
SSLProcessServerHello(SSLBuffer message, SSLContext *ctx)
{   SSLErr              err;
    SSLProtocolVersion  protocolVersion;
    unsigned int        sessionIDLen;
    uint8               *p;
    
    ASSERT(ctx->protocolSide == SSL_ClientSide);
    
    if (message.length < 38 || message.length > 70)
        return SSLProtocolErr;
    p = message.data;
    
    protocolVersion = (SSLProtocolVersion)SSLDecodeInt(p, 2);
    p += 2;
    if (protocolVersion != SSL_Version_3_0)
        return SSLUnsupportedErr;
    ctx->protocolVersion = protocolVersion;
    
    memcpy(ctx->serverRandom, p, 32);
    p += 32;
    
    sessionIDLen = *p++;
    if (message.length != 38 + sessionIDLen)
        return SSLProtocolErr;
    
    if (sessionIDLen > 0 && ctx->peerID.data != 0)
    {   /* Don't die on error; just treat it as an uncached session */
        err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen, &ctx->sysCtx);
        if (err == 0)
            memcpy(ctx->sessionID.data, p, sessionIDLen);
    }
    p += sessionIDLen;
    
    ctx->selectedCipher = (uint16)SSLDecodeInt(p,2);
    p += 2;
    if ((err = FindCipherSpec(ctx->selectedCipher, &ctx->selectedCipherSpec)) != 0)
        return err;
    
    if (*p++ != 0)      /* Compression */
        return SSLUnsupportedErr;
    
    ASSERT(p == message.data + message.length);
    return SSLNoErr;
}

SSLErr
SSLEncodeClientHello(SSLRecord *clientHello, SSLContext *ctx)
{   int             length, i;
    SSLErr          err;
    unsigned char   *p;
    SSLBuffer       sessionIdentifier;
    uint16          sessionIDLen;
    
    ASSERT(ctx->protocolSide == SSL_ClientSide);
    
    sessionIDLen = 0;
    if (ctx->resumableSession.data != 0)
    {   if (ERR(err = SSLRetrieveSessionIDIdentifier(ctx->resumableSession, &sessionIdentifier, ctx)) != 0)
        {   return err;
        }
        sessionIDLen = sessionIdentifier.length;
    }
    
    length = 39 + 2*CipherSpecCount + sessionIDLen;
    
    clientHello->protocolVersion = SSL_Version_3_0;
    clientHello->contentType = SSL_handshake;
    if ((err = SSLAllocBuffer(&clientHello->contents, length + 4, &ctx->sysCtx)) != 0)
        return err;
    
    p = clientHello->contents.data;
    *p++ = SSL_client_hello;
    p = SSLEncodeInt(p, length, 3);
    p = SSLEncodeInt(p, SSL_Version_3_0, 2);
    if ((err = SSLEncodeRandom(p, ctx)) != 0)
    {   SSLFreeBuffer(&clientHello->contents, &ctx->sysCtx);
        return err;
    }
    memcpy(ctx->clientRandom, p, 32);
    p += 32;
    *p++ = sessionIDLen;    /* 1 byte vector length */
    if (sessionIDLen > 0)
    {   memcpy(p, sessionIdentifier.data, sessionIDLen);
        if ((err = SSLFreeBuffer(&sessionIdentifier, &ctx->sysCtx)) != 0)
            return err;
    }
    p += sessionIDLen;
    p = SSLEncodeInt(p, 2*CipherSpecCount, 2);  /* 2 byte long vector length */
    for (i = 0; i < CipherSpecCount; ++i)
        p = SSLEncodeInt(p, KnownCipherSpecs[i].cipherSpec, 2);
    *p++ = 1;                               /* 1 byte long vector */
    *p++ = 0;                               /* null compression */
    
    ASSERT(p == clientHello->contents.data + clientHello->contents.length);
    
    if ((err = SSLInitMessageHashes(ctx)) != 0)
        return err;
    
    return SSLNoErr;
}

SSLErr
SSLProcessClientHello(SSLBuffer message, SSLContext *ctx)
{   SSLErr              err;
    SSLProtocolVersion  clientVersion;
    uint16              cipherListLen, cipherCount, desiredSpec, cipherSpec;
    uint8               sessionIDLen, compressionCount;
    uint8               *progress;
    int                 i;
    
    if (message.length < 41)
        return SSLProtocolErr;
    
    progress = message.data;
    clientVersion = (SSLProtocolVersion)SSLDecodeInt(progress, 2);
    progress += 2;
    if (clientVersion < SSL_Version_3_0)
        return SSLUnsupportedErr;
    ctx->protocolVersion = SSL_Version_3_0;
    
    memcpy(ctx->clientRandom, progress, 32);
    progress += 32;
    sessionIDLen = *(progress++);
    if (message.length < 41 + sessionIDLen)
        return SSLProtocolErr;
    if (sessionIDLen > 0 && ctx->peerID.data != 0)
    {   /* Don't die on error; just treat it as an uncacheable session */
        err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen, &ctx->sysCtx);
        if (err == 0)
            memcpy(ctx->sessionID.data, progress, sessionIDLen);
    }
    progress += sessionIDLen;
    
    cipherListLen = (uint16)SSLDecodeInt(progress, 2);  /* Count of cipherSpecs, must be even & >= 2 */
    progress += 2;
    if ((cipherListLen & 1) || cipherListLen < 2 || message.length < 39 + sessionIDLen + cipherListLen)
        return SSLProtocolErr;
    cipherCount = cipherListLen/2;
    cipherSpec = 0xFFFF;        /* No match marker */
    while (cipherSpec == 0xFFFF && cipherCount--)
    {   desiredSpec = (uint16)SSLDecodeInt(progress, 2);
        progress += 2;
        for (i = 0; i < CipherSpecCount; i++)
        {   if (KnownCipherSpecs[i].cipherSpec == desiredSpec)
            {   cipherSpec = desiredSpec;
                break;
            }
        }
    }
    
    if (cipherSpec == 0xFFFF)
        return SSLNegotiationErr;
    progress += 2 * cipherCount;    /* Advance past unchecked cipherCounts */
    ctx->selectedCipher = cipherSpec;
    if ((err = FindCipherSpec(ctx->selectedCipher, &ctx->selectedCipherSpec)) != 0)
        return err;
    
    compressionCount = *(progress++);
/* message.length restriction relaxed to allow too-long messages for future expansion
    following recommendation of TLS meeting 5/29/96 */
    if (compressionCount < 1 || message.length < 38 + sessionIDLen + cipherListLen + compressionCount)
        return SSLProtocolErr;
    /* Ignore list; we're doing null */
    
    if ((err = SSLInitMessageHashes(ctx)) != 0)
        return err;
    
    return SSLNoErr;
}

static SSLErr
SSLEncodeRandom(unsigned char *p, SSLContext *ctx)
{   SSLBuffer   randomData;
    SSLErr      err;
    uint32      time;
    
    if ((err = ctx->sysCtx.time(&time, ctx->sysCtx.timeRef)) != 0)
        return err;
    SSLEncodeInt(p, time, 4);
    randomData.data = p+4;
    randomData.length = 28;
    if ((err = ctx->sysCtx.random(randomData, ctx->sysCtx.randomRef)) != 0)
        return err;
    return SSLNoErr;
}

SSLErr
SSLInitMessageHashes(SSLContext *ctx)
{   SSLErr          err;
    if ((err = SSLFreeBuffer(&ctx->shaState, &ctx->sysCtx)) != 0)
        return err;
    if ((err = SSLFreeBuffer(&ctx->md5State, &ctx->sysCtx)) != 0)
        return err;
    if ((err = ReadyHash(&SSLHashSHA1, &ctx->shaState, ctx)) != 0)
        return err;
    if ((err = ReadyHash(&SSLHashMD5, &ctx->md5State, ctx)) != 0)
        return err;
    return SSLNoErr;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?