Fix SSLv3 MAC computation

In a previous PR (Fix heap corruption in implementation of truncated HMAC
extension #425) the place where MAC is computed was changed from the end of
the SSL I/O buffer to a local buffer (then (part of) the content of the local
buffer is either copied to the output buffer of compare to the input buffer).

Unfortunately, this change was made only for TLS 1.0 and later, leaving SSL
3.0 in an inconsistent state due to ssl_mac() still writing to the old,
hard-coded location, which, for MAC verification, resulted in later comparing
the end of the input buffer (containing the computed MAC) to the local buffer
(uninitialised), most likely resulting in MAC verification failure, hence no
interop (even with ourselves).

This commit completes the move to using a local buffer by using this strategy
for SSL 3.0 too. Fortunately ssl_mac() was static so it's not a problem to
change its signature.
This commit is contained in:
Manuel Pégourié-Gonnard 2017-12-18 18:04:59 +01:00
parent 917969e533
commit 3ea75b3a9b

View File

@ -1050,9 +1050,11 @@ int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex )
/*
* SSLv3.0 MAC functions
*/
static void ssl_mac( md_context_t *md_ctx, unsigned char *secret,
unsigned char *buf, size_t len,
unsigned char *ctr, int type )
static void ssl_mac( md_context_t *md_ctx,
const unsigned char *secret,
const unsigned char *buf, size_t len,
const unsigned char *ctr, int type,
unsigned char out[20] )
{
unsigned char header[11];
unsigned char padding[48];
@ -1077,14 +1079,14 @@ static void ssl_mac( md_context_t *md_ctx, unsigned char *secret,
md_update( md_ctx, padding, padlen );
md_update( md_ctx, header, 11 );
md_update( md_ctx, buf, len );
md_finish( md_ctx, buf + len );
md_finish( md_ctx, out );
memset( padding, 0x5C, padlen );
md_starts( md_ctx );
md_update( md_ctx, secret, md_size );
md_update( md_ctx, padding, padlen );
md_update( md_ctx, buf + len, md_size );
md_finish( md_ctx, buf + len );
md_update( md_ctx, out, md_size );
md_finish( md_ctx, out );
}
#endif /* POLARSSL_SSL_PROTO_SSL3 */
@ -1130,10 +1132,15 @@ static int ssl_encrypt_buf( ssl_context *ssl )
#if defined(POLARSSL_SSL_PROTO_SSL3)
if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
{
unsigned char mac[20]; /* SHA-1 at most */
ssl_mac( &ssl->transform_out->md_ctx_enc,
ssl->transform_out->mac_enc,
ssl->out_msg, ssl->out_msglen,
ssl->out_ctr, ssl->out_msgtype );
ssl->out_ctr, ssl->out_msgtype,
mac );
memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen );
}
else
#endif
@ -1790,7 +1797,8 @@ static int ssl_decrypt_buf( ssl_context *ssl )
ssl_mac( &ssl->transform_in->md_ctx_dec,
ssl->transform_in->mac_dec,
ssl->in_msg, ssl->in_msglen,
ssl->in_ctr, ssl->in_msgtype );
ssl->in_ctr, ssl->in_msgtype,
mac_expect );
}
else
#endif /* POLARSSL_SSL_PROTO_SSL3 */