summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2014-09-22 12:36:06 +0000
committerjsing <>2014-09-22 12:36:06 +0000
commitf0cda88b271cabe457d56240d785628f22bb3992 (patch)
tree2d6ce4054b3f35aec05209d0b9a3f8a375250cf1 /src
parenta8592cce042623e644ebf9efa4c148c78b46d064 (diff)
downloadopenbsd-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.c24
-rw-r--r--src/lib/libssl/src/ssl/s3_both.c24
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)
223int 223int
224ssl3_get_finished(SSL *s, int a, int b) 224ssl3_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)
223int 223int
224ssl3_get_finished(SSL *s, int a, int b) 224ssl3_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);