diff options
| author | jsing <> | 2014-09-22 12:36:06 +0000 |
|---|---|---|
| committer | jsing <> | 2014-09-22 12:36:06 +0000 |
| commit | bc9843be364dd752ca9220e38960425978b2ad77 (patch) | |
| tree | 2d6ce4054b3f35aec05209d0b9a3f8a375250cf1 /src/lib/libssl/s3_both.c | |
| parent | 5d237272df7ccfde22003cad538e834fac8137de (diff) | |
| download | openbsd-bc9843be364dd752ca9220e38960425978b2ad77.tar.gz openbsd-bc9843be364dd752ca9220e38960425978b2ad77.tar.bz2 openbsd-bc9843be364dd752ca9220e38960425978b2ad77.zip | |
It is possible (although unlikely in practice) for peer_finish_md_len to
end up with a value of zero, primarily since ssl3_take_mac() fails to check
the return value from the final_finish_mac() call. This would then mean that
an SSL finished message with a zero-byte payload would successfully match
against the calculated finish MAC.
Avoid this by checking the length of peer_finish_md_len and the SSL
finished message payload, against the known length already stored in
the SSL3_ENC_METHOD finish_mac_length field (making use of a previously
unused field).
ok miod@ (a little while back)
Diffstat (limited to 'src/lib/libssl/s3_both.c')
| -rw-r--r-- | src/lib/libssl/s3_both.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/src/lib/libssl/s3_both.c b/src/lib/libssl/s3_both.c index 6ba3d4bfce..17368f1107 100644 --- a/src/lib/libssl/s3_both.c +++ b/src/lib/libssl/s3_both.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: s3_both.c,v 1.28 2014/08/07 20:02:23 miod Exp $ */ | 1 | /* $OpenBSD: s3_both.c,v 1.29 2014/09/22 12:36:06 jsing Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -223,7 +223,7 @@ ssl3_take_mac(SSL *s) | |||
| 223 | int | 223 | int |
| 224 | ssl3_get_finished(SSL *s, int a, int b) | 224 | ssl3_get_finished(SSL *s, int a, int b) |
| 225 | { | 225 | { |
| 226 | int al, i, ok; | 226 | int al, ok, md_len; |
| 227 | long n; | 227 | long n; |
| 228 | unsigned char *p; | 228 | unsigned char *p; |
| 229 | 229 | ||
| @@ -247,33 +247,31 @@ ssl3_get_finished(SSL *s, int a, int b) | |||
| 247 | } | 247 | } |
| 248 | s->s3->change_cipher_spec = 0; | 248 | s->s3->change_cipher_spec = 0; |
| 249 | 249 | ||
| 250 | md_len = s->method->ssl3_enc->finish_mac_length; | ||
| 250 | p = (unsigned char *)s->init_msg; | 251 | p = (unsigned char *)s->init_msg; |
| 251 | i = s->s3->tmp.peer_finish_md_len; | ||
| 252 | 252 | ||
| 253 | if (i != n) { | 253 | if (s->s3->tmp.peer_finish_md_len != md_len || n != md_len) { |
| 254 | al = SSL_AD_DECODE_ERROR; | 254 | al = SSL_AD_DECODE_ERROR; |
| 255 | SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_BAD_DIGEST_LENGTH); | 255 | SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_BAD_DIGEST_LENGTH); |
| 256 | goto f_err; | 256 | goto f_err; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | if (timingsafe_memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) { | 259 | if (timingsafe_memcmp(p, s->s3->tmp.peer_finish_md, md_len) != 0) { |
| 260 | al = SSL_AD_DECRYPT_ERROR; | 260 | al = SSL_AD_DECRYPT_ERROR; |
| 261 | SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_DIGEST_CHECK_FAILED); | 261 | SSLerr(SSL_F_SSL3_GET_FINISHED, SSL_R_DIGEST_CHECK_FAILED); |
| 262 | goto f_err; | 262 | goto f_err; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | /* Copy the finished so we can use it for | 265 | /* Copy finished so we can use it for renegotiation checks. */ |
| 266 | renegotiation checks */ | 266 | OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); |
| 267 | if (s->type == SSL_ST_ACCEPT) { | 267 | if (s->type == SSL_ST_ACCEPT) { |
| 268 | OPENSSL_assert(i <= EVP_MAX_MD_SIZE); | ||
| 269 | memcpy(s->s3->previous_client_finished, | 268 | memcpy(s->s3->previous_client_finished, |
| 270 | s->s3->tmp.peer_finish_md, i); | 269 | s->s3->tmp.peer_finish_md, md_len); |
| 271 | s->s3->previous_client_finished_len = i; | 270 | s->s3->previous_client_finished_len = md_len; |
| 272 | } else { | 271 | } else { |
| 273 | OPENSSL_assert(i <= EVP_MAX_MD_SIZE); | ||
| 274 | memcpy(s->s3->previous_server_finished, | 272 | memcpy(s->s3->previous_server_finished, |
| 275 | s->s3->tmp.peer_finish_md, i); | 273 | s->s3->tmp.peer_finish_md, md_len); |
| 276 | s->s3->previous_server_finished_len = i; | 274 | s->s3->previous_server_finished_len = md_len; |
| 277 | } | 275 | } |
| 278 | 276 | ||
| 279 | return (1); | 277 | return (1); |
