PolarSSL is now part of ARM Official announcement and rebranded as mbed TLS.

About ssl_write_certificate_verify


Dec 8, 2017 10:04
tomson

Dear Ron Eldor, my hero! I've just learned mbedtls sourcecode soon. In the part of ssl_write_certificate_verify (seen the file ssl_cli.c,line 3137~3219),i can't understand how the client calculate the signature of handshake message clearly and what's the difference of this step between TLS1.2 with other versions? Can you give me a specific description of the process? thanks very much!!

/*
 * Make an RSA signature of the handshake digests
 */
ssl->handshake->calc_verify( ssl, hash );
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
{
    /*
     * digitally-signed struct {
     *     opaque md5_hash[16];
     *     opaque sha_hash[20];
     * };
     *
     * md5_hash
     *     MD5(handshake_messages);
     *
     * sha_hash
     *     SHA(handshake_messages);
     */
    hashlen = 36;
    md_alg = MBEDTLS_MD_NONE;

    /*
     * For ECDSA, default hash is SHA-1 only
     */
    if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) )
    {
        hash_start += 16;
        hashlen -= 16;
        md_alg = MBEDTLS_MD_SHA1;
    }
}
else
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
    /*
     * digitally-signed struct {
     *     opaque handshake_messages[handshake_messages_length];
     * };
     *
     * Taking shortcut here. We assume that the server always allows the
     * PRF Hash function and has sent it in the allowed signature
     * algorithms list received in the Certificate Request message.
     *
     * Until we encounter a server that does not, we will take this
     * shortcut.
     *
     * Reason: Otherwise we should have running hashes for SHA512 and SHA224
     *         in order to satisfy 'weird' needs from the server side.
     */
    if( ssl->transform_negotiate->ciphersuite_info->mac ==
        MBEDTLS_MD_SHA384 )
    {
        md_alg = MBEDTLS_MD_SHA384;
        ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384;
    }
    else
    {
        md_alg = MBEDTLS_MD_SHA256;
        ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256;
    }
    ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) );

    /* Info from md_alg will be used instead */
    hashlen = 0;
    offset = 2;
}
else
 
Dec 10, 2017 12:41
Ron Eldor

Hi Tomson,
I recomend you read the TLS 1.1 RFC and TLS1.2 RFC for better understanding these protocols.
The key to understanding the difference, according to the source code, IMHO, is the line

ssl->handshake->calc_verify( ssl, hash );

Which creates the digest message to sign.
For TLS 1.0 and TLS 1.1, this callback function is ssl_calc_verify_tls() generates a 36 byte digest built from md5(16bytes) and sha1(20 bytes). For TLS 1.2, the callback function are either ssl_calc_verify_tls_sha384() or ssl_calc_verify_tls_sha256() depending what was negotiated.
After that, in the code you have shown, according to the TLS protocol used, and digest algorithm used, the hashlen and size is calculated, to be sent later to mbedtls_pk_sign()
Regards,
Mbed TLS Team member
Ron