diff options
Diffstat (limited to 'src/lib/libssl/s3_pkt.c')
-rw-r--r-- | src/lib/libssl/s3_pkt.c | 111 |
1 files changed, 61 insertions, 50 deletions
diff --git a/src/lib/libssl/s3_pkt.c b/src/lib/libssl/s3_pkt.c index adf8c387cc..96ba63262e 100644 --- a/src/lib/libssl/s3_pkt.c +++ b/src/lib/libssl/s3_pkt.c | |||
@@ -290,11 +290,8 @@ static int ssl3_get_record(SSL *s) | |||
290 | unsigned char *p; | 290 | unsigned char *p; |
291 | unsigned char md[EVP_MAX_MD_SIZE]; | 291 | unsigned char md[EVP_MAX_MD_SIZE]; |
292 | short version; | 292 | short version; |
293 | int mac_size; | 293 | unsigned mac_size, orig_len; |
294 | int clear=0; | ||
295 | size_t extra; | 294 | size_t extra; |
296 | int decryption_failed_or_bad_record_mac = 0; | ||
297 | unsigned char *mac = NULL; | ||
298 | 295 | ||
299 | rr= &(s->s3->rrec); | 296 | rr= &(s->s3->rrec); |
300 | sess=s->session; | 297 | sess=s->session; |
@@ -338,7 +335,7 @@ fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); | |||
338 | if (version != s->version) | 335 | if (version != s->version) |
339 | { | 336 | { |
340 | SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); | 337 | SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); |
341 | if ((s->version & 0xFF00) == (version & 0xFF00)) | 338 | if ((s->version & 0xFF00) == (version & 0xFF00) && !s->enc_write_ctx && !s->write_hash) |
342 | /* Send back error using their minor version number :-) */ | 339 | /* Send back error using their minor version number :-) */ |
343 | s->version = (unsigned short)version; | 340 | s->version = (unsigned short)version; |
344 | al=SSL_AD_PROTOCOL_VERSION; | 341 | al=SSL_AD_PROTOCOL_VERSION; |
@@ -403,17 +400,15 @@ fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); | |||
403 | rr->data=rr->input; | 400 | rr->data=rr->input; |
404 | 401 | ||
405 | enc_err = s->method->ssl3_enc->enc(s,0); | 402 | enc_err = s->method->ssl3_enc->enc(s,0); |
406 | if (enc_err <= 0) | 403 | /* enc_err is: |
404 | * 0: (in non-constant time) if the record is publically invalid. | ||
405 | * 1: if the padding is valid | ||
406 | * -1: if the padding is invalid */ | ||
407 | if (enc_err == 0) | ||
407 | { | 408 | { |
408 | if (enc_err == 0) | 409 | al=SSL_AD_DECRYPTION_FAILED; |
409 | /* SSLerr() and ssl3_send_alert() have been called */ | 410 | SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); |
410 | goto err; | 411 | goto f_err; |
411 | |||
412 | /* Otherwise enc_err == -1, which indicates bad padding | ||
413 | * (rec->length has not been changed in this case). | ||
414 | * To minimize information leaked via timing, we will perform | ||
415 | * the MAC computation anyway. */ | ||
416 | decryption_failed_or_bad_record_mac = 1; | ||
417 | } | 412 | } |
418 | 413 | ||
419 | #ifdef TLS_DEBUG | 414 | #ifdef TLS_DEBUG |
@@ -423,53 +418,62 @@ printf("\n"); | |||
423 | #endif | 418 | #endif |
424 | 419 | ||
425 | /* r->length is now the compressed data plus mac */ | 420 | /* r->length is now the compressed data plus mac */ |
426 | if ( (sess == NULL) || | 421 | if ((sess != NULL) && |
427 | (s->enc_read_ctx == NULL) || | 422 | (s->enc_read_ctx != NULL) && |
428 | (EVP_MD_CTX_md(s->read_hash) == NULL)) | 423 | (EVP_MD_CTX_md(s->read_hash) != NULL)) |
429 | clear=1; | ||
430 | |||
431 | if (!clear) | ||
432 | { | 424 | { |
433 | /* !clear => s->read_hash != NULL => mac_size != -1 */ | 425 | /* s->read_hash != NULL => mac_size != -1 */ |
426 | unsigned char *mac = NULL; | ||
427 | unsigned char mac_tmp[EVP_MAX_MD_SIZE]; | ||
434 | mac_size=EVP_MD_CTX_size(s->read_hash); | 428 | mac_size=EVP_MD_CTX_size(s->read_hash); |
435 | OPENSSL_assert(mac_size >= 0); | 429 | OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); |
436 | 430 | ||
437 | if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) | 431 | /* kludge: *_cbc_remove_padding passes padding length in rr->type */ |
432 | orig_len = rr->length+((unsigned int)rr->type>>8); | ||
433 | |||
434 | /* orig_len is the length of the record before any padding was | ||
435 | * removed. This is public information, as is the MAC in use, | ||
436 | * therefore we can safely process the record in a different | ||
437 | * amount of time if it's too short to possibly contain a MAC. | ||
438 | */ | ||
439 | if (orig_len < mac_size || | ||
440 | /* CBC records must have a padding length byte too. */ | ||
441 | (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && | ||
442 | orig_len < mac_size+1)) | ||
438 | { | 443 | { |
439 | #if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */ | 444 | al=SSL_AD_DECODE_ERROR; |
440 | al=SSL_AD_RECORD_OVERFLOW; | 445 | SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); |
441 | SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); | ||
442 | goto f_err; | 446 | goto f_err; |
443 | #else | ||
444 | decryption_failed_or_bad_record_mac = 1; | ||
445 | #endif | ||
446 | } | 447 | } |
447 | /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ | 448 | |
448 | if (rr->length >= (unsigned int)mac_size) | 449 | if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) |
449 | { | 450 | { |
451 | /* We update the length so that the TLS header bytes | ||
452 | * can be constructed correctly but we need to extract | ||
453 | * the MAC in constant time from within the record, | ||
454 | * without leaking the contents of the padding bytes. | ||
455 | * */ | ||
456 | mac = mac_tmp; | ||
457 | ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); | ||
450 | rr->length -= mac_size; | 458 | rr->length -= mac_size; |
451 | mac = &rr->data[rr->length]; | ||
452 | } | 459 | } |
453 | else | 460 | else |
454 | { | 461 | { |
455 | /* record (minus padding) is too short to contain a MAC */ | 462 | /* In this case there's no padding, so |orig_len| |
456 | #if 0 /* OK only for stream ciphers */ | 463 | * equals |rec->length| and we checked that there's |
457 | al=SSL_AD_DECODE_ERROR; | 464 | * enough bytes for |mac_size| above. */ |
458 | SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); | 465 | rr->length -= mac_size; |
459 | goto f_err; | 466 | mac = &rr->data[rr->length]; |
460 | #else | ||
461 | decryption_failed_or_bad_record_mac = 1; | ||
462 | rr->length = 0; | ||
463 | #endif | ||
464 | } | ||
465 | i=s->method->ssl3_enc->mac(s,md,0); | ||
466 | if (i < 0 || mac == NULL || memcmp(md, mac, (size_t)mac_size) != 0) | ||
467 | { | ||
468 | decryption_failed_or_bad_record_mac = 1; | ||
469 | } | 467 | } |
468 | |||
469 | i=s->method->ssl3_enc->mac(s,md,0 /* not send */); | ||
470 | if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) | ||
471 | enc_err = -1; | ||
472 | if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) | ||
473 | enc_err = -1; | ||
470 | } | 474 | } |
471 | 475 | ||
472 | if (decryption_failed_or_bad_record_mac) | 476 | if (enc_err < 0) |
473 | { | 477 | { |
474 | /* A separate 'decryption_failed' alert was introduced with TLS 1.0, | 478 | /* A separate 'decryption_failed' alert was introduced with TLS 1.0, |
475 | * SSL 3.0 only has 'bad_record_mac'. But unless a decryption | 479 | * SSL 3.0 only has 'bad_record_mac'. But unless a decryption |
@@ -744,6 +748,7 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, | |||
744 | * bytes and record version number > TLS 1.0 | 748 | * bytes and record version number > TLS 1.0 |
745 | */ | 749 | */ |
746 | if (s->state == SSL3_ST_CW_CLNT_HELLO_B | 750 | if (s->state == SSL3_ST_CW_CLNT_HELLO_B |
751 | && !s->renegotiate | ||
747 | && TLS1_get_version(s) > TLS1_VERSION) | 752 | && TLS1_get_version(s) > TLS1_VERSION) |
748 | *(p++) = 0x1; | 753 | *(p++) = 0x1; |
749 | else | 754 | else |
@@ -1238,7 +1243,7 @@ start: | |||
1238 | goto f_err; | 1243 | goto f_err; |
1239 | } | 1244 | } |
1240 | #ifdef SSL_AD_MISSING_SRP_USERNAME | 1245 | #ifdef SSL_AD_MISSING_SRP_USERNAME |
1241 | if (alert_descr == SSL_AD_MISSING_SRP_USERNAME) | 1246 | else if (alert_descr == SSL_AD_MISSING_SRP_USERNAME) |
1242 | return(0); | 1247 | return(0); |
1243 | #endif | 1248 | #endif |
1244 | } | 1249 | } |
@@ -1454,8 +1459,14 @@ int ssl3_do_change_cipher_spec(SSL *s) | |||
1454 | slen=s->method->ssl3_enc->client_finished_label_len; | 1459 | slen=s->method->ssl3_enc->client_finished_label_len; |
1455 | } | 1460 | } |
1456 | 1461 | ||
1457 | s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, | 1462 | i = s->method->ssl3_enc->final_finish_mac(s, |
1458 | sender,slen,s->s3->tmp.peer_finish_md); | 1463 | sender,slen,s->s3->tmp.peer_finish_md); |
1464 | if (i == 0) | ||
1465 | { | ||
1466 | SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); | ||
1467 | return 0; | ||
1468 | } | ||
1469 | s->s3->tmp.peer_finish_md_len = i; | ||
1459 | 1470 | ||
1460 | return(1); | 1471 | return(1); |
1461 | } | 1472 | } |