diff options
author | jsing <> | 2014-09-22 12:36:06 +0000 |
---|---|---|
committer | jsing <> | 2014-09-22 12:36:06 +0000 |
commit | f0cda88b271cabe457d56240d785628f22bb3992 (patch) | |
tree | 2d6ce4054b3f35aec05209d0b9a3f8a375250cf1 /src | |
parent | a8592cce042623e644ebf9efa4c148c78b46d064 (diff) | |
download | openbsd-f0cda88b271cabe457d56240d785628f22bb3992.tar.gz openbsd-f0cda88b271cabe457d56240d785628f22bb3992.tar.bz2 openbsd-f0cda88b271cabe457d56240d785628f22bb3992.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')
-rw-r--r-- | src/lib/libssl/s3_both.c | 24 | ||||
-rw-r--r-- | src/lib/libssl/src/ssl/s3_both.c | 24 |
2 files changed, 22 insertions, 26 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); |
diff --git a/src/lib/libssl/src/ssl/s3_both.c b/src/lib/libssl/src/ssl/s3_both.c index 6ba3d4bfce..17368f1107 100644 --- a/src/lib/libssl/src/ssl/s3_both.c +++ b/src/lib/libssl/src/ssl/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); |