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

📄 ssl_tls_c.htm

📁 ssl和tls的源代码实现
💻 HTM
📖 第 1 页 / 共 3 页
字号:
                                 ssl->out_msg, ssl->out_msglen );
                break;
#endif

            default:
                return( ERR_SSL_FEATURE_UNAVAILABLE );
        }

    }

    return( 0 );
}

static int ssl_decrypt_buf( ssl_context *ssl )
{
    int i, padlen;
    unsigned char tmp[20];

    if( ssl->in_msglen < ssl->minlen )
        return( ERR_SSL_INVALID_MAC );

    if( ssl->ivlen == 0 )
    {
#if !defined(NO_ARC4)
        padlen = 0;
        arc4_crypt( (arc4_context *) ssl->ctx_dec,
                    ssl->in_msg, ssl->in_msglen );
#else
        return( ERR_SSL_FEATURE_UNAVAILABLE );
#endif
    }
    else
    {
        /*
         * Decrypt and check the padding
         */
        if( ssl->in_msglen % ssl->ivlen != 0 )
            return( ERR_SSL_INVALID_MAC );

        switch( ssl->ivlen )
        {
#if !defined(NO_DES)
            case  8:
                des3_cbc_decrypt( (des3_context *) ssl->ctx_dec,
                                  ssl->iv_dec, ssl->in_msg,
                                  ssl->in_msg, ssl->in_msglen );
                break;
#endif

#if !defined(NO_AES)
            case 16:
                 aes_cbc_decrypt( (aes_context *) ssl->ctx_dec,
                                  ssl->iv_dec, ssl->in_msg,
                                  ssl->in_msg, ssl->in_msglen );
                 break;
#endif

            default:
                return( ERR_SSL_FEATURE_UNAVAILABLE );
        }

        padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];

        if( ssl->minor_ver == SSLV3_MINOR_VERSION )
        {
            if( padlen > ssl->ivlen )
                padlen = 0;
        }
        else
        {
            for( i = 1; i <= (int) padlen; i++ )
                if( ssl->in_msg[ssl->in_msglen - i] != padlen - 1 )
                    padlen = 0;
        }
    }

    /*
     * Always compute the MAC (RFC4346, CBCTIME).
     */
    ssl->in_msglen -= ( ssl->maclen + padlen );

    ssl->in_hdr[3] = ssl->in_msglen >> 8;
    ssl->in_hdr[4] = ssl->in_msglen;

    memcpy( tmp, ssl->in_msg + ssl->in_msglen, 20 );

    if( ssl->minor_ver == SSLV3_MINOR_VERSION )
    {
        if( ssl->maclen == 16 )
             ssl_mac_md5( ssl->mac_dec,
                          ssl->in_msg, ssl->in_msglen,
                          ssl->in_ctr, ssl->in_msgtype );
        else
            ssl_mac_sha1( ssl->mac_dec,
                          ssl->in_msg, ssl->in_msglen,
                          ssl->in_ctr, ssl->in_msgtype );
    }
    else
    {
        if( ssl->maclen == 16 )
             md5_hmac( ssl->mac_dec, 16,
                       ssl->in_ctr,  ssl->in_msglen + 13,
                       ssl->in_msg + ssl->in_msglen );
        else
            sha1_hmac( ssl->mac_dec, 20,
                       ssl->in_ctr,  ssl->in_msglen + 13,
                       ssl->in_msg + ssl->in_msglen );
    }

    if( memcmp( tmp, ssl->in_msg + ssl->in_msglen,
                     ssl->maclen ) != 0 )
        return( ERR_SSL_INVALID_MAC );

    /*
     * Finally verify the padding length; bad padding
     * will produce the same error as an invalid MAC.
     */
    if( ssl->ivlen != 0 && padlen == 0 )
        return( ERR_SSL_INVALID_MAC );

    if( ssl->in_msglen == 0 )
    {
        ssl->nb_zero++;

        /*
         * Three or more empty messages may be a DoS attack.
         */
        if( ssl->nb_zero > 2 )
            return( ERR_SSL_INVALID_MAC );
    }
    else
        ssl->nb_zero = 0;
            
    for( i = 7; i >= 0; i-- )
        if( ++ssl->in_ctr[i] != 0 )
            break;

    return( 0 );
}

/*
 * Record layer functions
 */
int ssl_write_record( ssl_context *ssl, int do_crypt )
{
    int ret, len = ssl->out_msglen;

    ssl->out_hdr[0] = ssl->out_msgtype;
    ssl->out_hdr[1] = ssl->major_ver;
    ssl->out_hdr[2] = ssl->minor_ver;
    ssl->out_hdr[3] = len >> 8;
    ssl->out_hdr[4] = len;

    if( ssl->out_msgtype == SSL_MSG_HANDSHAKE )
    {
        ssl->out_msg[1] = ( len - 4 ) >> 16;
        ssl->out_msg[2] = ( len - 4 ) >>  8;
        ssl->out_msg[3] = ( len - 4 );

         md5_update( &ssl->hs_md5 , ssl->out_msg, len );
        sha1_update( &ssl->hs_sha1, ssl->out_msg, len );
    }

    if( do_crypt != 0 )
    {
        if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 )
            return( ret );

        len = ssl->out_msglen;
        ssl->out_hdr[3] = len >> 8;
        ssl->out_hdr[4] = len;
    }

    ssl->out_left = 5 + ssl->out_msglen;

    return( net_send( ssl->write_fd,
                      ssl->out_hdr,
                     &ssl->out_left ) );
}

int ssl_read_record( ssl_context *ssl, int do_crypt )
{
    int ret, len;

    if( ssl->in_hslen != 0 &&
        ssl->in_hslen < ssl->in_msglen )
    {
        /*
         * Get next Handshake message in the current record
         */
        ssl->in_msglen -= ssl->in_hslen;

        memcpy( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
                ssl->in_msglen );

        if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
            return( ERR_SSL_INVALID_RECORD );

        ssl->in_hslen  = 4;
        ssl->in_hslen += ( (int) ssl->in_msg[2] << 8 )
                       | ( (int) ssl->in_msg[3]      );

        if( ssl->in_msglen < ssl->in_hslen )
            return( ERR_SSL_INVALID_RECORD );

        return( 0 );
    }

    ssl->in_hslen = 0;

    /*
     * Read the record header and validate it
     */
    if( ssl->in_left < 5 )
    {
        len = 5 - ssl->in_left;
        ret = net_recv( ssl->read_fd, ssl->in_hdr
                                    + ssl->in_left, &len );
        ssl->in_left += len;

        if( ret != 0 )
            return( ret );
    }

    ssl->in_msgtype = ssl->in_hdr[0];
    ssl->in_msglen  = ( (int) ssl->in_hdr[3] << 8 )
                    | ( (int) ssl->in_hdr[4]      );

    if( ssl->in_hdr[1] != ssl->major_ver )
        return( ERR_SSL_INVALID_RECORD );

    if( ssl->in_hdr[2] != SSLV3_MINOR_VERSION &&
        ssl->in_hdr[2] != TLS10_MINOR_VERSION )
        return( ERR_SSL_INVALID_RECORD );

    /*
     * Make sure the message length is acceptable
     */
    if( do_crypt == 0 )
    {
        if( ssl->in_msglen < 1 ||
            ssl->in_msglen > SSL_MAX_CONTENT_LEN )
            return( ERR_SSL_INVALID_RECORD );
    }
    else
    {
        if( ssl->in_msglen < ssl->minlen )
            return( ERR_SSL_INVALID_RECORD );

        if( ssl->minor_ver == 0 &&
            ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN )
            return( ERR_SSL_INVALID_RECORD );

        /*
         * TLS encrypted messages can have up to 256 bytes of padding
         */
        if( ssl->minor_ver != 0 &&
            ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN + 256 )
            return( ERR_SSL_INVALID_RECORD );
    }

    /*
     * Read and optionally decrypt the message contents
     */
    len = ssl->in_msglen - ( ssl->in_left - 5 );
    ret = net_recv( ssl->read_fd, ssl->in_hdr
                                + ssl->in_left, &len );
    ssl->in_left += len;

    if( ret != 0 )
        return( ret );

    if( do_crypt != 0 )
    {
        if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
            return( ret );

        if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
            return( ERR_SSL_INVALID_RECORD );
    }

    if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
    {
        /*
         * Additional checks to validate the handshake header
         */
        if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
            return( ERR_SSL_INVALID_RECORD );

        ssl->in_hslen  = 4;
        ssl->in_hslen += ( (int) ssl->in_msg[2] << 8 )
                       | ( (int) ssl->in_msg[3]      );

        if( ssl->in_msglen < ssl->in_hslen )
            return( ERR_SSL_INVALID_RECORD );

          md5_update( &ssl->hs_md5 , ssl->in_msg, ssl->in_msglen );
         sha1_update( &ssl->hs_sha1, ssl->in_msg, ssl->in_msglen );
    }

    if( ssl->in_msgtype == SSL_MSG_ALERT )
    {
        /*
         * Ignore non-fatal alerts, except close_notify
         */
        if( ssl->in_msg[0] == SSL_ALERT_FATAL )
            return( ERR_SSL_FATAL_ALERT_MESSAGE );

        if( ssl->in_msg[0] == SSL_ALERT_WARNING &&
            ssl->in_msg[1] == SSL_ALERT_CLOSE_NOTIFY )
            return( ERR_SSL_PEER_CLOSE_NOTIFY );
    }

    ssl->in_left = 0;

    return( 0 );
}

/*
 * Flush any data not yet written
 */
int ssl_flush_output( ssl_context *ssl )
{
    int ret = 0;
    unsigned char *buf;

    if( ssl->out_left > 0 )
    {
        buf = ssl->out_hdr + ssl->out_msglen -
            ( ssl->out_left - 5 );

        ret = net_send( ssl->write_fd, buf,
                       &ssl->out_left );
    }

    return( ret );
}

/*
 * Handshake functions
 */
int ssl_write_certificate( ssl_context *ssl )
{
    int i, n;
    x509_cert *crt;

    if( ssl->endpoint == SSL_IS_CLIENT )
    {
        if( ssl->client_auth == 0 )
        {
            ssl->state++;
            return( 0 );
        }

        /*
         * If using SSLv3 and got no cert, send an Alert message
         * (otherwise an empty Certificate message will be sent).
         */
        if( ssl->own_cert  == NULL &&
            ssl->minor_ver == SSLV3_MINOR_VERSION )
        {
            ssl->out_msglen  = 2;
            ssl->out_msgtype = SSL_MSG_ALERT;
            ssl->out_msg[0]  = SSL_ALERT_WARNING;
            ssl->out_msg[1]  = SSL_ALERT_NO_CERTIFICATE;

            ssl->state++;
            return( ssl_write_record( ssl, 0 ) );
        }
    }
    else /* SSL_IS_SERVER */
        if( ssl->own_cert == NULL )
            return( ERR_SSL_CERTIFICATE_REQUIRED );

    /*
     *     0  .  0    handshake type
     *     1  .  3    handshake length
     *     4  .  6    length of all certs
     *     7  .  9    length of cert. 1
     *    10  . n-1   peer certificate
     *     n  . n+2   length of cert. 2
     *    n+3 . ...   upper level cert, etc.
     */
    i = 7;
    crt = ssl->own_cert;
    while( crt != NULL && crt->next != NULL )
    {
        n = crt->raw.len;
        if( i + 3 + n > SSL_MAX_CONTENT_LEN )
            return( ERR_SSL_CERTIFICATE_TOO_LARGE );

        ssl->out_msg[i    ] = ( n >> 16 );
        ssl->out_msg[i + 1] = ( n >>  8 );
        ssl->out_msg[i + 2] = ( n       );

        i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
        i += n; crt = crt->next;
    }

    ssl->out_msg[4] = ( i - 7 ) >> 16;
    ssl->out_msg[5] = ( i - 7 ) >>  8;
    ssl->out_msg[6] = ( i - 7 )      ;

    ssl->out_msglen  = i;
    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
    ssl->out_msg[0]  = SSL_HS_CERTIFICATE;

    ssl->state++;

    return( ssl_write_record( ssl, 0 ) );
}

int ssl_parse_certificate( ssl_context *ssl )
{
    int ret, i, n;

    if( ssl->endpoint == SSL_IS_SERVER &&
        ssl->authmode == SSL_VERIFY_NONE )
    {
        ssl->state++;
        return( 0 );
    }

    if( ( ret = ssl_read_record( ssl, 0 ) ) != 0 )
        return( ret );

    ssl->state++;

    /*
     * Check if the client sent an empty certificate
     */
    if( ssl->endpoint  == SSL_IS_SERVER &&
        ssl->minor_ver == SSLV3_MINOR_VERSION )
    {
        if( ssl->in_msglen  == 2                    &&
            ssl->in_msgtype == SSL_MSG_ALERT        &&
            ssl->in_msg[0]  == SSL_ALERT_WARNING    &&
            ssl->in_msg[1]  == SSL_ALERT_NO_CERTIFICATE )
        {
            if( ssl->authmode == SSL_VERIFY_OPTIONAL )
                return( 0 );
            else
                return( ERR_SSL_NO_CLIENT_CERTIFICATE );
        }
    }

    if( ssl->endpoint  == SSL_IS_SERVER &&
        ssl->minor_ver != SSLV3_MINOR_VERSION )
    {
        if( ssl->in_hslen   == 7                    &&
            ssl->in_msgtype == SSL_MSG_HANDSHAKE    &&
            ssl->in_msg[0]  == SSL_HS_CERTIFICATE   &&
            memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 )
        {
            if( ssl->authmode == SSL_VERIFY_OPTIONAL )
                return( 0 );
            else
                return( ERR_SSL_NO_CLIENT_CERTIFICATE );
        }
    }

    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
        return( ERR_SSL_UNEXPECTED_MESSAGE );

    if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 )
        return( ERR_SSL_BAD_HS_CERTIFICATE );

    /*
     * Same message structure as shown above
     */
    n = ( (int) ssl->in_msg[5] << 8 )
      | ( (int) ssl->in_msg[6]      );

    if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n )
        return( ERR_SSL_BAD_HS_CERTIFICATE );

    if( ( ssl->peer_cert = (x509_cert *) malloc(
                    sizeof( x509_cert ) ) ) == NULL )
        return( 1 );

    memset( ssl->peer_cert, 0, sizeof( x509_cert ) );
    i = 7;

    while( i < ssl->in_hslen )
    {
        if( ssl->in_msg[i] != 0 )
            return( ERR_SSL_BAD_HS_CERTIFICATE );

        n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
          | ( (unsigned int) ssl->in_msg[i + 2]      );
        i += 3;

        if( n < 128 || i + n > ssl->in_hslen )
            return( ERR_SSL_BAD_HS_CERTIFICATE );

        ret = x509_add_certs( ssl->peer_cert, ssl->in_msg + i, n );
        if( ret != 0 )
            return( ret );

        i += n;
    }

    if( ssl->authmode != SSL_VERIFY_NONE )
    {
        if( ssl->ca_chain == NULL )
            return( ERR_SSL_CA_CHAIN_REQUIRED );

        ret = x509_verify_cert( ssl->peer_cert, ssl->ca_chain,

⌨️ 快捷键说明

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