hdskkyex.c

来自「Netscape公司提供的安全套接字层」· C语言 代码 · 共 884 行 · 第 1/3 页

C
884
字号
/*  *********************************************************************
    File: hdskkyex.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: hdskkyex.c   Support for key exchange and server key exchange

    Encoding and decoding of key exchange and server key exchange
    messages in both the Diffie-Hellman and RSA variants; also, includes
    the necessary crypto library calls to support this negotiation.

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

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

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

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

#include <string.h>

static SSLErr SSLEncodeRSAServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx);
static SSLErr SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx);
static SSLErr SSLEncodeDHanonServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx);
static SSLErr SSLProcessRSAServerKeyExchange(SSLBuffer message, SSLContext *ctx);
static SSLErr SSLProcessDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx);
static SSLErr SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx);
static SSLErr SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange, SSLContext *ctx);
static SSLErr SSLEncodeRSAKeyExchange(SSLRecord *keyExchange, SSLContext *ctx);
static SSLErr SSLEncodeDHanonKeyExchange(SSLRecord *keyExchange, SSLContext *ctx);

SSLErr
SSLEncodeServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
{   SSLErr      err;
    
    switch (ctx->selectedCipherSpec->keyExchangeMethod)
    {   case SSL_RSA:
        case SSL_RSA_EXPORT:
            if (ERR(err = SSLEncodeRSAServerKeyExchange(keyExch, ctx)) != 0)
                return err;
            break;
        case SSL_DH_anon:
            if (ERR(err = SSLEncodeDHanonServerKeyExchange(keyExch, ctx)) != 0)
                return err;
            break;
        default:
            return ERR(SSLUnsupportedErr);
    }
    
    return SSLNoErr;
}

static SSLErr
SSLEncodeRSAServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
{   SSLErr          err;
    uint8           *progress;
    int             length;
    unsigned int    outputLen, localKeyModulusLen;
    uint8           hashes[36];
    SSLBuffer       exportKey,clientRandom,serverRandom,hashCtx, hash;
    
    exportKey.data = 0;
    hashCtx.data = 0;
    
    if (ERR(err = SSLEncodeRSAKeyParams(&exportKey, &ctx->exportKey, ctx)) != 0)
        goto fail;
    
#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 */
    
    length = exportKey.length + 2 + localKeyModulusLen;     /* RSA ouputs a block as long as the modulus */
    
    keyExch->protocolVersion = SSL_Version_3_0;
    keyExch->contentType = SSL_handshake;
    if (ERR(err = SSLAllocBuffer(&keyExch->contents, length+4, &ctx->sysCtx)) != 0)
        goto fail;
    
    progress = keyExch->contents.data;
    *progress++ = SSL_server_key_exchange;
    progress = SSLEncodeInt(progress, length, 3);
    
    memcpy(progress, exportKey.data, exportKey.length);
    progress += exportKey.length;
    
    clientRandom.data = ctx->clientRandom;
    clientRandom.length = 32;
    serverRandom.data = ctx->serverRandom;
    serverRandom.length = 32;
    
    hash.data = &hashes[0];
    hash.length = 16;
    if (ERR(err = ReadyHash(&SSLHashMD5, &hashCtx, ctx)) != 0)
        goto fail;
    if (ERR(err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
        goto fail;
    if (ERR(err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
        goto fail;
    if (ERR(err = SSLHashMD5.update(hashCtx, exportKey)) != 0)
        goto fail;
    if (ERR(err = SSLHashMD5.final(hashCtx, hash)) != 0)
        goto fail;
    if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
        goto fail;
    
    hash.data = &hashes[16];
    hash.length = 20;
    if (ERR(err = ReadyHash(&SSLHashSHA1, &hashCtx, ctx)) != 0)
        goto fail;
    if (ERR(err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
        goto fail;
    if (ERR(err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
        goto fail;
    if (ERR(err = SSLHashSHA1.update(hashCtx, exportKey)) != 0)
        goto fail;
    if (ERR(err = SSLHashSHA1.final(hashCtx, hash)) != 0)
        goto fail;
    if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
        goto fail;
    
    progress = SSLEncodeInt(progress, localKeyModulusLen, 2);
#if RSAREF
    if (RSAPrivateEncrypt(progress, &outputLen, hashes, 36, &ctx->localKey) != 0)   /* Sign the structure */
        return ERR(SSLUnknownErr);
#elif BSAFE
    {   B_ALGORITHM_OBJ     rsa;
        B_ALGORITHM_METHOD  *chooser[] = { &AM_RSA_ENCRYPT, &AM_RSA_CRT_ENCRYPT, 0 };
        int                 rsaResult;
        unsigned int        encryptedOut;
        
        if ((rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPrivate, 0)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_EncryptInit(rsa, ctx->localKey, chooser, NO_SURR)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_EncryptUpdate(rsa, progress,
                    &encryptedOut, localKeyModulusLen, hashes, 36, 0, NO_SURR)) != 0)
            return SSLUnknownErr;
        outputLen = encryptedOut;
        if ((rsaResult = B_EncryptFinal(rsa, progress+outputLen,
                    &encryptedOut, localKeyModulusLen-outputLen, 0, NO_SURR)) != 0)
            return SSLUnknownErr;
        outputLen += encryptedOut;
        B_DestroyAlgorithmObject(&rsa);
    }
#endif /* RSAREF / BSAFE */
    ASSERT(outputLen == localKeyModulusLen);
    
    err = SSLNoErr;
    
fail:
    ERR(SSLFreeBuffer(&hashCtx, &ctx->sysCtx));
    ERR(SSLFreeBuffer(&exportKey, &ctx->sysCtx));
    
    return err;
}

static SSLErr
SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx)
{   SSLErr      err;
    SSLBuffer   modulus, exponent;
    uint8       *progress;
    
#if RSAREF
    keyParams->data = 0;
    modulus.length = (key->bits + 7) / 8;
    modulus.data = key->modulus + MAX_RSA_MODULUS_LEN - modulus.length;
    
    exponent.length = MAX_RSA_MODULUS_LEN;
    exponent.data = key->publicExponent;            /* Point at first byte */
    
    while (*exponent.data == 0)
    {   ++exponent.data;
        --exponent.length;
    }
#elif BSAFE
    {   A_RSA_KEY   *keyInfo;
        int         rsaResult;
        
        if ((rsaResult = B_GetKeyInfo((POINTER*)&keyInfo, *key, KI_RSAPublic)) != 0)
            return SSLUnknownErr;
        modulus.data = keyInfo->modulus.data;
        modulus.length = keyInfo->modulus.len;
        exponent.data = keyInfo->exponent.data;
        exponent.length = keyInfo->exponent.len;
    }   
#endif /* RSAREF / BSAFE */
    
    if (ERR(err = SSLAllocBuffer(keyParams, modulus.length + exponent.length + 4, &ctx->sysCtx)) != 0)
        return err;
    progress = keyParams->data;
    progress = SSLEncodeInt(progress, modulus.length, 2);
    memcpy(progress, modulus.data, modulus.length);
    progress += modulus.length;
    progress = SSLEncodeInt(progress, exponent.length, 2);
    memcpy(progress, exponent.data, exponent.length);
    
    return SSLNoErr;
}

static SSLErr
SSLEncodeDHanonServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
{   SSLErr              err;
    unsigned int        length;
    uint8               *progress;
    SSLRandomCtx        random;
    int                 rsaErr;
    
#if RSAREF
    length = 6 + ctx->dhAnonParams.primeLen + ctx->dhAnonParams.generatorLen +
                    ctx->dhExchangePublic.length;
    
    keyExch->protocolVersion = SSL_Version_3_0;
    keyExch->contentType = SSL_handshake;
    if (ERR(err = SSLAllocBuffer(&keyExch->contents, length+4, &ctx->sysCtx)) != 0)
        return err;
    
    progress = keyExch->contents.data;
    *progress++ = SSL_server_key_exchange;
    progress = SSLEncodeInt(progress, length, 3);
    
    progress = SSLEncodeInt(progress, ctx->dhAnonParams.primeLen, 2);
    memcpy(progress, ctx->dhAnonParams.prime, ctx->dhAnonParams.primeLen);
    progress += ctx->dhAnonParams.primeLen;
    
    progress = SSLEncodeInt(progress, ctx->dhAnonParams.generatorLen, 2);
    memcpy(progress, ctx->dhAnonParams.generator, ctx->dhAnonParams.generatorLen);
    progress += ctx->dhAnonParams.generatorLen;
    
    if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
        return err;
    if (ERR(err = SSLAllocBuffer(&ctx->dhPrivate, ctx->dhExchangePublic.length - 16, &ctx->sysCtx)) != 0)
        return err;

    if (ERR(err = ReadyRandom(&random, ctx)) != 0)
        return err;
    
    if ((rsaErr = R_SetupDHAgreement(ctx->dhExchangePublic.data, ctx->dhPrivate.data,
                    ctx->dhPrivate.length, &ctx->dhAnonParams, &random)) != 0)
    {   err = SSLUnknownErr;
        return err;
    }
    
    progress = SSLEncodeInt(progress, ctx->dhExchangePublic.length, 2);
    memcpy(progress, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
    progress += ctx->dhExchangePublic.length;
    
#elif BSAFE
    {   A_DH_KEY_AGREE_PARAMS   *params;
        unsigned int            outputLen;
        
        if ((rsaErr = B_GetAlgorithmInfo((POINTER*)&params, ctx->dhAnonParams, AI_DHKeyAgree)) != 0)
            return SSLUnknownErr;
        if (ERR(err = ReadyRandom(&random, ctx)) != 0)
            return err;
        if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, 128, &ctx->sysCtx)) != 0)
            return err;
        if ((rsaErr = B_KeyAgreePhase1(ctx->dhAnonParams, ctx->dhExchangePublic.data,
                            &outputLen, 128, random, NO_SURR)) != 0)
        {   err = SSLUnknownErr;
            return err;
        }
        ctx->dhExchangePublic.length = outputLen;
        
        length = 6 + params->prime.len + params->base.len + ctx->dhExchangePublic.length;
        
        keyExch->protocolVersion = SSL_Version_3_0;
        keyExch->contentType = SSL_handshake;

⌨️ 快捷键说明

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