diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libssl/d1_pkt.c | 134 | ||||
-rw-r--r-- | lib/libssl/s3_cbc.c | 30 | ||||
-rw-r--r-- | lib/libssl/ssl_locl.h | 14 | ||||
-rw-r--r-- | lib/libssl/ssl_pkt.c | 166 | ||||
-rw-r--r-- | lib/libssl/t1_enc.c | 339 | ||||
-rw-r--r-- | lib/libssl/tls12_record_layer.c | 348 |
6 files changed, 426 insertions, 605 deletions
diff --git a/lib/libssl/d1_pkt.c b/lib/libssl/d1_pkt.c index 859043a3cec..30ce78414d3 100644 --- a/lib/libssl/d1_pkt.c +++ b/lib/libssl/d1_pkt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_pkt.c,v 1.84 2020/10/03 17:11:28 jsing Exp $ */ +/* $OpenBSD: d1_pkt.c,v 1.85 2020/10/03 17:35:16 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -310,130 +310,40 @@ dtls1_process_buffered_records(SSL *s) static int dtls1_process_record(SSL *s) { - int i, al; - int enc_err; - SSL_SESSION *sess; - SSL3_RECORD_INTERNAL *rr; - unsigned int mac_size, orig_len; - unsigned char md[EVP_MAX_MD_SIZE]; - - rr = &(S3I(s)->rrec); - sess = s->session; - - /* At this point, s->internal->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, - * and we have that many bytes in s->internal->packet - */ - rr->input = &(s->internal->packet[DTLS1_RT_HEADER_LENGTH]); - - /* ok, we can now read from 's->internal->packet' data into 'rr' - * rr->input points at rr->length bytes, which - * need to be copied into rr->data by either - * the decryption or by the decompression - * When the data is 'copied' into the rr->data buffer, - * rr->input will be pointed at the new buffer */ - - /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] - * rr->length bytes of encrypted compressed stuff. */ - - /* check is not needed I believe */ - if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerror(s, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); - goto f_err; - } - - /* decrypt in place in 'rr->input' */ - rr->data = rr->input; - - /* enc_err is: - * 0: (in non-constant time) if the record is publically invalid. - * 1: if the padding is valid - * -1: if the padding is invalid */ - if ((enc_err = tls1_enc(s, 0)) == 0) { - /* For DTLS we simply ignore bad packets. */ - rr->length = 0; - s->internal->packet_length = 0; - goto err; - } + SSL3_RECORD_INTERNAL *rr = &(S3I(s)->rrec); + uint8_t alert_desc; + uint8_t *out; + size_t out_len; - /* r->length is now the compressed data plus mac */ - if ((sess != NULL) && (s->enc_read_ctx != NULL) && - (EVP_MD_CTX_md(s->read_hash) != NULL)) { - /* s->read_hash != NULL => mac_size != -1 */ - unsigned char *mac = NULL; - unsigned char mac_tmp[EVP_MAX_MD_SIZE]; - mac_size = EVP_MD_CTX_size(s->read_hash); - OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); - - orig_len = rr->length + rr->padding_length; - - /* orig_len is the length of the record before any padding was - * removed. This is public information, as is the MAC in use, - * therefore we can safely process the record in a different - * amount of time if it's too short to possibly contain a MAC. - */ - if (orig_len < mac_size || - /* CBC records must have a padding length byte too. */ - (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && - orig_len < mac_size + 1)) { - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } + tls12_record_layer_set_version(s->internal->rl, s->version); + tls12_record_layer_set_read_epoch(s->internal->rl, rr->epoch); - if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { - /* We update the length so that the TLS header bytes - * can be constructed correctly but we need to extract - * the MAC in constant time from within the record, - * without leaking the contents of the padding bytes. - * */ - mac = mac_tmp; - ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); - rr->length -= mac_size; - } else { - /* In this case there's no padding, so |orig_len| - * equals |rec->length| and we checked that there's - * enough bytes for |mac_size| above. */ - rr->length -= mac_size; - mac = &rr->data[rr->length]; - } + if (!tls12_record_layer_open_record(s->internal->rl, s->internal->packet, + s->internal->packet_length, &out, &out_len)) { + tls12_record_layer_alert(s->internal->rl, &alert_desc); - i = tls1_mac(s, md, 0 /* not send */); - if (i < 0 || mac == NULL || timingsafe_memcmp(md, mac, (size_t)mac_size) != 0) - enc_err = -1; - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size) - enc_err = -1; - } + if (alert_desc == 0) + goto err; - if (enc_err < 0) { - /* decryption failed, silently discard message */ - rr->length = 0; - s->internal->packet_length = 0; - goto err; - } + if (alert_desc == SSL_AD_RECORD_OVERFLOW) + SSLerror(s, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + else if (alert_desc == SSL_AD_BAD_RECORD_MAC) + SSLerror(s, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); - if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerror(s, SSL_R_DATA_LENGTH_TOO_LONG); goto f_err; } + rr->data = out; + rr->length = out_len; rr->off = 0; - /* So at this point the following is true - * ssl->s3->internal->rrec.type is the type of record - * ssl->s3->internal->rrec.length == number of bytes in record - * ssl->s3->internal->rrec.off == offset to first valid byte - * ssl->s3->internal->rrec.data == where to take bytes from, increment - * after use :-). - */ - /* we have pulled in a full packet so zero things */ s->internal->packet_length = 0; + return (1); -f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); -err: + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, alert_desc); + err: return (0); } diff --git a/lib/libssl/s3_cbc.c b/lib/libssl/s3_cbc.c index 74e0562c2db..4f84c9485bd 100644 --- a/lib/libssl/s3_cbc.c +++ b/lib/libssl/s3_cbc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_cbc.c,v 1.22 2020/06/19 21:26:40 tb Exp $ */ +/* $OpenBSD: s3_cbc.c,v 1.23 2020/10/03 17:35:16 jsing Exp $ */ /* ==================================================================== * Copyright (c) 2012 The OpenSSL Project. All rights reserved. * @@ -101,7 +101,7 @@ constant_time_eq_8(unsigned int a, unsigned int b) return DUPLICATE_MSB_TO_ALL_8(c); } -/* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC +/* ssl3_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC * record in |rec| in constant time and returns 1 if the padding is valid and * -1 otherwise. It also removes any explicit IV from the start of the record * without leaking any timing about whether there was enough space after the @@ -113,26 +113,24 @@ constant_time_eq_8(unsigned int a, unsigned int b) * 1: if the padding was valid * -1: otherwise. */ int -tls1_cbc_remove_padding(const SSL* s, SSL3_RECORD_INTERNAL *rec, - unsigned int block_size, unsigned int mac_size) +ssl3_cbc_remove_padding(SSL3_RECORD_INTERNAL *rec, unsigned int eiv_len, + unsigned int mac_size) { unsigned int padding_length, good, to_check, i; const unsigned int overhead = 1 /* padding length byte */ + mac_size; - /* Check if version requires explicit IV */ - if (SSL_USE_EXPLICIT_IV(s)) { - /* These lengths are all public so we can test them in - * non-constant time. - */ - if (overhead + block_size > rec->length) - return 0; - /* We can now safely skip explicit IV */ - rec->data += block_size; - rec->input += block_size; - rec->length -= block_size; - } else if (overhead > rec->length) + /* + * These lengths are all public so we can test them in + * non-constant time. + */ + if (overhead + eiv_len > rec->length) return 0; + /* We can now safely skip explicit IV, if any. */ + rec->data += eiv_len; + rec->input += eiv_len; + rec->length -= eiv_len; + padding_length = rec->data[rec->length - 1]; good = constant_time_ge(rec->length, overhead + padding_length); diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index 9a9ef592826..0dda3ecd019 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.295 2020/09/24 18:12:00 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.296 2020/10/03 17:35:16 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -477,6 +477,8 @@ struct tls12_record_layer; struct tls12_record_layer *tls12_record_layer_new(void); void tls12_record_layer_free(struct tls12_record_layer *rl); +void tls12_record_layer_alert(struct tls12_record_layer *rl, + uint8_t *alert_desc); void tls12_record_layer_set_version(struct tls12_record_layer *rl, uint16_t version); void tls12_record_layer_set_read_epoch(struct tls12_record_layer *rl, @@ -497,6 +499,10 @@ int tls12_record_layer_set_read_cipher_hash(struct tls12_record_layer *rl, EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, int stream_mac); int tls12_record_layer_set_write_cipher_hash(struct tls12_record_layer *rl, EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, int stream_mac); +int tls12_record_layer_set_read_mac_key(struct tls12_record_layer *rl, + const uint8_t *mac_key, size_t mac_key_len); +int tls12_record_layer_open_record(struct tls12_record_layer *rl, + uint8_t *buf, size_t buf_len, uint8_t **out, size_t *out_len); int tls12_record_layer_seal_record(struct tls12_record_layer *rl, uint8_t content_type, const uint8_t *content, size_t content_len, CBB *out); @@ -1361,9 +1367,7 @@ int tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len); void tls1_cleanup_key_block(SSL *s); int tls1_change_cipher_state(SSL *s, int which); int tls1_setup_key_block(SSL *s); -int tls1_enc(SSL *s, int snd); int tls1_final_finish_mac(SSL *s, const char *str, int slen, unsigned char *p); -int tls1_mac(SSL *ssl, unsigned char *md, int snd); int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, int len); int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen, @@ -1411,8 +1415,8 @@ int tls1_check_ec_server_key(SSL *s); /* s3_cbc.c */ void ssl3_cbc_copy_mac(unsigned char *out, const SSL3_RECORD_INTERNAL *rec, unsigned int md_size, unsigned int orig_len); -int tls1_cbc_remove_padding(const SSL *s, SSL3_RECORD_INTERNAL *rec, - unsigned int block_size, unsigned int mac_size); +int ssl3_cbc_remove_padding(SSL3_RECORD_INTERNAL *rec, unsigned int eiv_len, + unsigned int mac_size); char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, unsigned char *md_out, size_t *md_out_size, const unsigned char header[13], diff --git a/lib/libssl/ssl_pkt.c b/lib/libssl/ssl_pkt.c index c9c86471d3c..02a476ea82b 100644 --- a/lib/libssl/ssl_pkt.c +++ b/lib/libssl/ssl_pkt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_pkt.c,v 1.31 2020/08/30 15:40:20 jsing Exp $ */ +/* $OpenBSD: ssl_pkt.c,v 1.32 2020/10/03 17:35:16 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -149,15 +149,14 @@ ssl_force_want_read(SSL *s) static int ssl3_read_n(SSL *s, int n, int max, int extend) { + SSL3_BUFFER_INTERNAL *rb = &(S3I(s)->rbuf); int i, len, left; size_t align; unsigned char *pkt; - SSL3_BUFFER_INTERNAL *rb; if (n <= 0) return n; - rb = &(S3I(s)->rbuf); if (rb->buf == NULL) if (!ssl3_setup_read_buffer(s)) return -1; @@ -327,15 +326,13 @@ ssl3_packet_extend(SSL *s, int plen) static int ssl3_get_record(SSL *s) { - int al; - int enc_err, n, i, ret = -1; - SSL3_RECORD_INTERNAL *rr; - SSL_SESSION *sess; - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int mac_size, orig_len; - - rr = &(S3I(s)->rrec); - sess = s->session; + SSL3_BUFFER_INTERNAL *rb = &(S3I(s)->rbuf); + SSL3_RECORD_INTERNAL *rr = &(S3I(s)->rrec); + uint8_t alert_desc; + uint8_t *out; + size_t out_len; + int al, n; + int ret = -1; again: /* check if we have the header */ @@ -387,17 +384,13 @@ ssl3_get_record(SSL *s) goto err; } - if (rr->length > S3I(s)->rbuf.len - SSL3_RT_HEADER_LENGTH) { + if (rr->length > rb->len - SSL3_RT_HEADER_LENGTH) { al = SSL_AD_RECORD_OVERFLOW; SSLerror(s, SSL_R_PACKET_LENGTH_TOO_LONG); goto f_err; } - - /* now s->internal->rstate == SSL_ST_READ_BODY */ } - /* s->internal->rstate == SSL_ST_READ_BODY, get and decode the data */ - n = ssl3_packet_extend(s, SSL3_RT_HEADER_LENGTH + rr->length); if (n <= 0) return (n); @@ -406,133 +399,40 @@ ssl3_get_record(SSL *s) s->internal->rstate = SSL_ST_READ_HEADER; /* set state for later operations */ - /* At this point, s->internal->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, - * and we have that many bytes in s->internal->packet + /* + * A full record has now been read from the wire, which now needs + * to be processed. */ - rr->input = &(s->internal->packet[SSL3_RT_HEADER_LENGTH]); - - /* ok, we can now read from 's->internal->packet' data into 'rr' - * rr->input points at rr->length bytes, which - * need to be copied into rr->data by either - * the decryption or by the decompression - * When the data is 'copied' into the rr->data buffer, - * rr->input will be pointed at the new buffer */ - - /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] - * rr->length bytes of encrypted compressed stuff. */ - - /* check is not needed I believe */ - if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerror(s, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); - goto f_err; - } - - /* decrypt in place in 'rr->input' */ - rr->data = rr->input; + tls12_record_layer_set_version(s->internal->rl, s->version); - /* enc_err is: - * 0: (in non-constant time) if the record is publically invalid. - * 1: if the padding is valid - * -1: if the padding is invalid */ - if ((enc_err = tls1_enc(s, 0)) == 0) { - al = SSL_AD_BAD_RECORD_MAC; - SSLerror(s, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); - goto f_err; - } - - /* r->length is now the compressed data plus mac */ - if ((sess != NULL) && (s->enc_read_ctx != NULL) && - (EVP_MD_CTX_md(s->read_hash) != NULL)) { - /* s->read_hash != NULL => mac_size != -1 */ - unsigned char *mac = NULL; - unsigned char mac_tmp[EVP_MAX_MD_SIZE]; - - mac_size = EVP_MD_CTX_size(s->read_hash); - OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); - - orig_len = rr->length + rr->padding_length; + if (!tls12_record_layer_open_record(s->internal->rl, s->internal->packet, + s->internal->packet_length, &out, &out_len)) { + tls12_record_layer_alert(s->internal->rl, &alert_desc); - /* orig_len is the length of the record before any padding was - * removed. This is public information, as is the MAC in use, - * therefore we can safely process the record in a different - * amount of time if it's too short to possibly contain a MAC. - */ - if (orig_len < mac_size || - /* CBC records must have a padding length byte too. */ - (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && - orig_len < mac_size + 1)) { - al = SSL_AD_DECODE_ERROR; - SSLerror(s, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - - if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { - /* We update the length so that the TLS header bytes - * can be constructed correctly but we need to extract - * the MAC in constant time from within the record, - * without leaking the contents of the padding bytes. - * */ - mac = mac_tmp; - ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); - rr->length -= mac_size; - } else { - /* In this case there's no padding, so |orig_len| - * equals |rec->length| and we checked that there's - * enough bytes for |mac_size| above. */ - rr->length -= mac_size; - mac = &rr->data[rr->length]; - } + if (alert_desc == 0) + goto err; - i = tls1_mac(s,md,0 /* not send */); - if (i < 0 || mac == NULL || - timingsafe_memcmp(md, mac, (size_t)mac_size) != 0) - enc_err = -1; - if (rr->length > - SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size) - enc_err = -1; - } + if (alert_desc == SSL_AD_RECORD_OVERFLOW) + SSLerror(s, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + else if (alert_desc == SSL_AD_BAD_RECORD_MAC) + SSLerror(s, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); - if (enc_err < 0) { - /* - * A separate 'decryption_failed' alert was introduced with - * TLS 1.0, SSL 3.0 only has 'bad_record_mac'. But unless a - * decryption failure is directly visible from the ciphertext - * anyway, we should not reveal which kind of error - * occurred -- this might become visible to an attacker - * (e.g. via a logfile) - */ - al = SSL_AD_BAD_RECORD_MAC; - SSLerror(s, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); - goto f_err; - } - - if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerror(s, SSL_R_DATA_LENGTH_TOO_LONG); + al = alert_desc; goto f_err; } + rr->data = out; + rr->length = out_len; rr->off = 0; - /* - * So at this point the following is true - * - * ssl->s3->internal->rrec.type is the type of record - * ssl->s3->internal->rrec.length == number of bytes in record - * ssl->s3->internal->rrec.off == offset to first valid byte - * ssl->s3->internal->rrec.data == where to take bytes from, increment - * after use :-). - */ /* we have pulled in a full packet so zero things */ s->internal->packet_length = 0; if (rr->length == 0) { /* - * CBC countermeasures for known IV weaknesses - * can legitimately insert a single empty record, - * so we allow ourselves to read once past a single - * empty record without forcing want_read. + * CBC countermeasures for known IV weaknesses can legitimately + * insert a single empty record, so we allow ourselves to read + * once past a single empty record without forcing want_read. */ if (s->internal->empty_record_count++ > SSL_MAX_EMPTY_RECORDS) { SSLerror(s, SSL_R_PEER_BEHAVING_BADLY); @@ -543,15 +443,15 @@ ssl3_get_record(SSL *s) return -1; } goto again; - } else { - s->internal->empty_record_count = 0; } + s->internal->empty_record_count = 0; + return (1); -f_err: + f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); -err: + err: return (ret); } diff --git a/lib/libssl/t1_enc.c b/lib/libssl/t1_enc.c index a66c82bdca6..7a71a084349 100644 --- a/lib/libssl/t1_enc.c +++ b/lib/libssl/t1_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_enc.c,v 1.123 2020/08/30 15:40:20 jsing Exp $ */ +/* $OpenBSD: t1_enc.c,v 1.124 2020/10/03 17:35:16 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -440,6 +440,10 @@ tls1_change_cipher_state_cipher(SSL *s, char is_read, if (!tls12_record_layer_set_read_cipher_hash(s->internal->rl, cipher_ctx, mac_ctx, stream_mac)) goto err; + + if (!tls12_record_layer_set_read_mac_key(s->internal->rl, + S3I(s)->read_mac_secret, mac_secret_size)) + goto err; } else { if (stream_mac) s->internal->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; @@ -672,260 +676,6 @@ tls1_setup_key_block(SSL *s) return (ret); } -/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. - * - * Returns: - * 0: (in non-constant time) if the record is publically invalid (i.e. too - * short etc). - * 1: if the record's padding is valid / the encryption was successful. - * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, - * an internal error occured. - */ -int -tls1_enc(SSL *s, int send) -{ - const SSL_AEAD_CTX *aead; - const EVP_CIPHER *enc; - EVP_CIPHER_CTX *ds; - SSL3_RECORD_INTERNAL *rec; - unsigned char *seq; - unsigned long l; - int bs, i, j, k, ret, mac_size = 0; - - if (send) { - /* No longer supported. */ - return -1; - } else { - aead = s->internal->aead_read_ctx; - rec = &S3I(s)->rrec; - seq = S3I(s)->read_sequence; - } - - if (aead) { - unsigned char ad[13], *in, *out, nonce[16]; - size_t out_len, pad_len = 0; - unsigned int nonce_used; - - if (SSL_IS_DTLS(s)) { - dtls1_build_sequence_number(ad, seq, - send ? D1I(s)->w_epoch : D1I(s)->r_epoch); - } else { - memcpy(ad, seq, SSL3_SEQUENCE_SIZE); - tls1_record_sequence_increment(seq); - } - - ad[8] = rec->type; - ad[9] = (unsigned char)(s->version >> 8); - ad[10] = (unsigned char)(s->version); - - if (aead->variable_nonce_len > 8 || - aead->variable_nonce_len > sizeof(nonce)) - return -1; - - if (aead->xor_fixed_nonce) { - if (aead->fixed_nonce_len > sizeof(nonce) || - aead->variable_nonce_len > aead->fixed_nonce_len) - return -1; /* Should never happen. */ - pad_len = aead->fixed_nonce_len - aead->variable_nonce_len; - } else { - if (aead->fixed_nonce_len + - aead->variable_nonce_len > sizeof(nonce)) - return -1; /* Should never happen. */ - } - - if (send) { - size_t len = rec->length; - size_t eivlen = 0; - in = rec->input; - out = rec->data; - - if (aead->xor_fixed_nonce) { - /* - * The sequence number is left zero - * padded, then xored with the fixed - * nonce. - */ - memset(nonce, 0, pad_len); - memcpy(nonce + pad_len, ad, - aead->variable_nonce_len); - for (i = 0; i < aead->fixed_nonce_len; i++) - nonce[i] ^= aead->fixed_nonce[i]; - nonce_used = aead->fixed_nonce_len; - } else { - /* - * When sending we use the sequence number as - * the variable part of the nonce. - */ - memcpy(nonce, aead->fixed_nonce, - aead->fixed_nonce_len); - nonce_used = aead->fixed_nonce_len; - memcpy(nonce + nonce_used, ad, - aead->variable_nonce_len); - nonce_used += aead->variable_nonce_len; - } - - /* - * In do_ssl3_write, rec->input is moved forward by - * variable_nonce_len in order to leave space for the - * variable nonce. Thus we can copy the sequence number - * bytes into place without overwriting any of the - * plaintext. - */ - if (aead->variable_nonce_in_record) { - memcpy(out, ad, aead->variable_nonce_len); - len -= aead->variable_nonce_len; - eivlen = aead->variable_nonce_len; - } - - ad[11] = len >> 8; - ad[12] = len & 0xff; - - if (!EVP_AEAD_CTX_seal(&aead->ctx, - out + eivlen, &out_len, len + aead->tag_len, nonce, - nonce_used, in + eivlen, len, ad, sizeof(ad))) - return -1; - if (aead->variable_nonce_in_record) - out_len += aead->variable_nonce_len; - } else { - /* receive */ - size_t len = rec->length; - - if (rec->data != rec->input) - return -1; /* internal error - should never happen. */ - out = in = rec->input; - - if (len < aead->variable_nonce_len) - return 0; - - if (aead->xor_fixed_nonce) { - /* - * The sequence number is left zero - * padded, then xored with the fixed - * nonce. - */ - memset(nonce, 0, pad_len); - memcpy(nonce + pad_len, ad, - aead->variable_nonce_len); - for (i = 0; i < aead->fixed_nonce_len; i++) - nonce[i] ^= aead->fixed_nonce[i]; - nonce_used = aead->fixed_nonce_len; - } else { - memcpy(nonce, aead->fixed_nonce, - aead->fixed_nonce_len); - nonce_used = aead->fixed_nonce_len; - - memcpy(nonce + nonce_used, - aead->variable_nonce_in_record ? in : ad, - aead->variable_nonce_len); - nonce_used += aead->variable_nonce_len; - } - - if (aead->variable_nonce_in_record) { - in += aead->variable_nonce_len; - len -= aead->variable_nonce_len; - out += aead->variable_nonce_len; - } - - if (len < aead->tag_len) - return 0; - len -= aead->tag_len; - - ad[11] = len >> 8; - ad[12] = len & 0xff; - - if (!EVP_AEAD_CTX_open(&aead->ctx, out, &out_len, len, - nonce, nonce_used, in, len + aead->tag_len, ad, - sizeof(ad))) - return -1; - - rec->data = rec->input = out; - } - - rec->length = out_len; - - return 1; - } - - if (send) { - if (EVP_MD_CTX_md(s->internal->write_hash)) { - int n = EVP_MD_CTX_size(s->internal->write_hash); - OPENSSL_assert(n >= 0); - } - ds = s->internal->enc_write_ctx; - if (s->internal->enc_write_ctx == NULL) - enc = NULL; - else { - int ivlen = 0; - enc = EVP_CIPHER_CTX_cipher(s->internal->enc_write_ctx); - if (SSL_USE_EXPLICIT_IV(s) && - EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) - ivlen = EVP_CIPHER_iv_length(enc); - if (ivlen > 1) { - if (rec->data != rec->input) { -#ifdef DEBUG - /* we can't write into the input stream: - * Can this ever happen?? (steve) - */ - fprintf(stderr, - "%s:%d: rec->data != rec->input\n", - __FILE__, __LINE__); -#endif - } else - arc4random_buf(rec->input, ivlen); - } - } - } else { - if (EVP_MD_CTX_md(s->read_hash)) { - int n = EVP_MD_CTX_size(s->read_hash); - OPENSSL_assert(n >= 0); - } - ds = s->enc_read_ctx; - if (s->enc_read_ctx == NULL) - enc = NULL; - else - enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx); - } - - if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { - memmove(rec->data, rec->input, rec->length); - rec->input = rec->data; - ret = 1; - } else { - l = rec->length; - bs = EVP_CIPHER_block_size(ds->cipher); - - if (bs != 1 && send) { - i = bs - ((int)l % bs); - - /* Add weird padding of upto 256 bytes */ - - /* we need to add 'i' padding bytes of value j */ - j = i - 1; - for (k = (int)l; k < (int)(l + i); k++) - rec->input[k] = j; - l += i; - rec->length += i; - } - - if (!send) { - if (l == 0 || l % bs != 0) - return 0; - } - - i = EVP_Cipher(ds, rec->data, rec->input, l); - if ((EVP_CIPHER_flags(ds->cipher) & - EVP_CIPH_FLAG_CUSTOM_CIPHER) ? (i < 0) : (i == 0)) - return -1; /* AEAD can fail to verify MAC */ - - ret = 1; - if (EVP_MD_CTX_md(s->read_hash) != NULL) - mac_size = EVP_MD_CTX_size(s->read_hash); - if ((bs != 1) && !send) - ret = tls1_cbc_remove_padding(s, rec, bs, mac_size); - } - return ret; -} - int tls1_final_finish_mac(SSL *s, const char *str, int str_len, unsigned char *out) { @@ -947,85 +697,6 @@ tls1_final_finish_mac(SSL *s, const char *str, int str_len, unsigned char *out) } int -tls1_mac(SSL *ssl, unsigned char *md, int send) -{ - SSL3_RECORD_INTERNAL *rec; - unsigned char *seq; - EVP_MD_CTX *hash; - size_t md_size, orig_len; - EVP_MD_CTX hmac, *mac_ctx; - unsigned char header[13]; - int stream_mac = (send ? - (ssl->internal->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM) : - (ssl->internal->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM)); - int t; - - if (send) { - /* No longer supported. */ - return -1; - } else { - rec = &(ssl->s3->internal->rrec); - seq = &(ssl->s3->internal->read_sequence[0]); - hash = ssl->read_hash; - } - - t = EVP_MD_CTX_size(hash); - OPENSSL_assert(t >= 0); - md_size = t; - - /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ - if (stream_mac) { - mac_ctx = hash; - } else { - if (!EVP_MD_CTX_copy(&hmac, hash)) - return -1; - mac_ctx = &hmac; - } - - if (SSL_IS_DTLS(ssl)) - dtls1_build_sequence_number(header, seq, - send ? D1I(ssl)->w_epoch : D1I(ssl)->r_epoch); - else - memcpy(header, seq, SSL3_SEQUENCE_SIZE); - - orig_len = rec->length + md_size + rec->padding_length; - - header[8] = rec->type; - header[9] = (unsigned char)(ssl->version >> 8); - header[10] = (unsigned char)(ssl->version); - header[11] = (rec->length) >> 8; - header[12] = (rec->length) & 0xff; - - if (!send && - EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && - ssl3_cbc_record_digest_supported(mac_ctx)) { - /* This is a CBC-encrypted record. We must avoid leaking any - * timing-side channel information about how many blocks of - * data we are hashing because that gives an attacker a - * timing-oracle. */ - if (!ssl3_cbc_digest_record(mac_ctx, - md, &md_size, header, rec->input, - rec->length + md_size, orig_len, - ssl->s3->internal->read_mac_secret, - ssl->s3->internal->read_mac_secret_size)) - return -1; - } else { - EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)); - EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length); - t = EVP_DigestSignFinal(mac_ctx, md, &md_size); - OPENSSL_assert(t > 0); - } - - if (!stream_mac) - EVP_MD_CTX_cleanup(&hmac); - - if (!SSL_IS_DTLS(ssl)) - tls1_record_sequence_increment(seq); - - return (md_size); -} - -int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, int len) { diff --git a/lib/libssl/tls12_record_layer.c b/lib/libssl/tls12_record_layer.c index 10d0f1194b4..56ff94d95c9 100644 --- a/lib/libssl/tls12_record_layer.c +++ b/lib/libssl/tls12_record_layer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls12_record_layer.c,v 1.4 2020/09/16 17:15:01 jsing Exp $ */ +/* $OpenBSD: tls12_record_layer.c,v 1.5 2020/10/03 17:35:17 jsing Exp $ */ /* * Copyright (c) 2020 Joel Sing <jsing@openbsd.org> * @@ -25,6 +25,8 @@ struct tls12_record_layer { uint16_t version; int dtls; + uint8_t alert_desc; + uint16_t read_epoch; uint16_t write_epoch; @@ -43,6 +45,9 @@ struct tls12_record_layer { EVP_CIPHER_CTX *write_cipher_ctx; EVP_MD_CTX *write_hash_ctx; + const uint8_t *read_mac_key; + size_t read_mac_key_len; + uint8_t *read_seq_num; uint8_t *write_seq_num; }; @@ -65,6 +70,12 @@ tls12_record_layer_free(struct tls12_record_layer *rl) } void +tls12_record_layer_alert(struct tls12_record_layer *rl, uint8_t *alert_desc) +{ + *alert_desc = rl->alert_desc; +} + +void tls12_record_layer_set_version(struct tls12_record_layer *rl, uint16_t version) { rl->version = version; @@ -111,6 +122,7 @@ void tls12_record_layer_clear_read_state(struct tls12_record_layer *rl) { tls12_record_layer_set_read_state(rl, NULL, NULL, NULL, 0); + tls12_record_layer_set_read_mac_key(rl, NULL, 0); rl->read_seq_num = NULL; } @@ -173,6 +185,16 @@ tls12_record_layer_set_write_cipher_hash(struct tls12_record_layer *rl, return 1; } +int +tls12_record_layer_set_read_mac_key(struct tls12_record_layer *rl, + const uint8_t *mac_key, size_t mac_key_len) +{ + rl->read_mac_key = mac_key; + rl->read_mac_key_len = mac_key_len; + + return 1; +} + static int tls12_record_layer_build_seq_num(struct tls12_record_layer *rl, CBB *cbb, uint16_t epoch, uint8_t *seq_num, size_t seq_num_len) @@ -234,7 +256,7 @@ tls12_record_layer_mac(struct tls12_record_layer *rl, CBB *cbb, { EVP_MD_CTX *mac_ctx = NULL; uint8_t *header = NULL; - size_t header_len; + size_t header_len = 0; size_t mac_len; uint8_t *mac; int ret = 0; @@ -258,6 +280,8 @@ tls12_record_layer_mac(struct tls12_record_layer *rl, CBB *cbb, goto err; if (EVP_DigestSignFinal(mac_ctx, mac, &mac_len) <= 0) goto err; + if (mac_len == 0) + goto err; if (stream_mac) { if (!EVP_MD_CTX_copy(hash_ctx, mac_ctx)) @@ -269,12 +293,67 @@ tls12_record_layer_mac(struct tls12_record_layer *rl, CBB *cbb, err: EVP_MD_CTX_free(mac_ctx); - free(header); + freezero(header, header_len); return ret; } static int +tls12_record_layer_read_mac_cbc(struct tls12_record_layer *rl, CBB *cbb, + uint8_t content_type, const uint8_t *content, size_t content_len, + size_t mac_len, size_t padding_len) +{ + uint8_t *header = NULL; + size_t header_len = 0; + uint8_t *mac = NULL; + size_t out_mac_len = 0; + int ret = 0; + + /* + * Must be constant time to avoid leaking details about CBC padding. + */ + + if (!ssl3_cbc_record_digest_supported(rl->read_hash_ctx)) + goto err; + + if (!tls12_record_layer_pseudo_header(rl, content_type, content_len, + rl->read_epoch, rl->read_seq_num, SSL3_SEQUENCE_SIZE, + &header, &header_len)) + goto err; + + if (!CBB_add_space(cbb, &mac, mac_len)) + goto err; + if (!ssl3_cbc_digest_record(rl->read_hash_ctx, mac, &out_mac_len, header, + content, content_len + mac_len, content_len + mac_len + padding_len, + rl->read_mac_key, rl->read_mac_key_len)) + goto err; + if (mac_len != out_mac_len) + goto err; + + ret = 1; + + err: + freezero(header, header_len); + + return ret; +} + +static int +tls12_record_layer_read_mac(struct tls12_record_layer *rl, CBB *cbb, + uint8_t content_type, const uint8_t *content, size_t content_len) +{ + EVP_CIPHER_CTX *enc = rl->read_cipher_ctx; + size_t out_len; + + if (EVP_CIPHER_CTX_mode(enc) == EVP_CIPH_CBC_MODE) + return 0; + + return tls12_record_layer_mac(rl, cbb, rl->read_hash_ctx, + rl->read_stream_mac, rl->read_epoch, rl->read_seq_num, + SSL3_SEQUENCE_SIZE, content_type, content, content_len, &out_len); +} + +static int tls12_record_layer_write_mac(struct tls12_record_layer *rl, CBB *cbb, uint8_t content_type, const uint8_t *content, size_t content_len, size_t *out_len) @@ -286,7 +365,8 @@ tls12_record_layer_write_mac(struct tls12_record_layer *rl, CBB *cbb, static int tls12_record_layer_aead_concat_nonce(struct tls12_record_layer *rl, - const SSL_AEAD_CTX *aead, uint8_t *seq_num, uint8_t **out, size_t *out_len) + const SSL_AEAD_CTX *aead, const uint8_t *seq_num, + uint8_t **out, size_t *out_len) { CBB cbb; @@ -314,7 +394,8 @@ tls12_record_layer_aead_concat_nonce(struct tls12_record_layer *rl, static int tls12_record_layer_aead_xored_nonce(struct tls12_record_layer *rl, - const SSL_AEAD_CTX *aead, uint8_t *seq_num, uint8_t **out, size_t *out_len) + const SSL_AEAD_CTX *aead, const uint8_t *seq_num, + uint8_t **out, size_t *out_len) { uint8_t *nonce = NULL; size_t nonce_len = 0; @@ -357,6 +438,263 @@ tls12_record_layer_aead_xored_nonce(struct tls12_record_layer *rl, } static int +tls12_record_layer_open_record_plaintext(struct tls12_record_layer *rl, + uint8_t content_type, CBS *fragment, uint8_t **out, size_t *out_len) +{ + if (rl->read_aead_ctx != NULL || rl->read_cipher_ctx != NULL) + return 0; + + /* XXX - decrypt/process in place for now. */ + *out = (uint8_t *)CBS_data(fragment); + *out_len = CBS_len(fragment); + + return 1; +} + +static int +tls12_record_layer_open_record_protected_aead(struct tls12_record_layer *rl, + uint8_t content_type, CBS *fragment, uint8_t **out, size_t *out_len) +{ + const SSL_AEAD_CTX *aead = rl->read_aead_ctx; + uint8_t *header = NULL, *nonce = NULL; + size_t header_len = 0, nonce_len = 0; + uint8_t *plain; + size_t plain_len; + uint16_t epoch = 0; + CBS var_nonce; + int ret = 0; + + /* XXX - move to nonce allocated in record layer, matching TLSv1.3 */ + if (aead->xor_fixed_nonce) { + if (!tls12_record_layer_aead_xored_nonce(rl, aead, + rl->read_seq_num, &nonce, &nonce_len)) + goto err; + } else if (aead->variable_nonce_in_record) { + if (!CBS_get_bytes(fragment, &var_nonce, + aead->variable_nonce_len)) + goto err; + if (!tls12_record_layer_aead_concat_nonce(rl, aead, + CBS_data(&var_nonce), &nonce, &nonce_len)) + goto err; + } else { + if (!tls12_record_layer_aead_concat_nonce(rl, aead, + rl->read_seq_num, &nonce, &nonce_len)) + goto err; + } + + /* XXX EVP_AEAD_max_tag_len vs EVP_AEAD_CTX_tag_len. */ + if (CBS_len(fragment) < aead->tag_len) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + if (CBS_len(fragment) > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + rl->alert_desc = SSL_AD_RECORD_OVERFLOW; + goto err; + } + + /* XXX - decrypt/process in place for now. */ + plain = (uint8_t *)CBS_data(fragment); + plain_len = CBS_len(fragment) - aead->tag_len; + + if (!tls12_record_layer_pseudo_header(rl, content_type, plain_len, + epoch, rl->read_seq_num, SSL3_SEQUENCE_SIZE, &header, &header_len)) + goto err; + + if (!EVP_AEAD_CTX_open(&aead->ctx, plain, out_len, plain_len, + nonce, nonce_len, CBS_data(fragment), CBS_len(fragment), + header, header_len)) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + + if (*out_len > SSL3_RT_MAX_PLAIN_LENGTH) { + rl->alert_desc = SSL_AD_RECORD_OVERFLOW; + goto err; + } + + if (*out_len != plain_len) + goto err; + + *out = plain; + + ret = 1; + + err: + freezero(header, header_len); + freezero(nonce, nonce_len); + + return ret; +} + +static int +tls12_record_layer_open_record_protected_cipher(struct tls12_record_layer *rl, + uint8_t content_type, CBS *fragment, uint8_t **out, size_t *out_len) +{ + EVP_CIPHER_CTX *enc = rl->read_cipher_ctx; + SSL3_RECORD_INTERNAL rrec; + int block_size, eiv_len; + uint8_t *mac = NULL; + int mac_len = 0; + uint8_t *out_mac = NULL; + size_t out_mac_len = 0; + uint8_t *plain; + size_t plain_len; + size_t min_len; + CBB cbb_mac; + int ret = 0; + + memset(&cbb_mac, 0, sizeof(cbb_mac)); + + block_size = EVP_CIPHER_CTX_block_size(enc); + if (block_size < 0 || block_size > EVP_MAX_BLOCK_LENGTH) + goto err; + + /* Determine explicit IV length. */ + eiv_len = 0; + if (rl->version != TLS1_VERSION && + EVP_CIPHER_CTX_mode(enc) == EVP_CIPH_CBC_MODE) + eiv_len = EVP_CIPHER_CTX_iv_length(enc); + if (eiv_len < 0 || eiv_len > EVP_MAX_IV_LENGTH) + goto err; + + mac_len = 0; + if (rl->read_hash_ctx != NULL) { + mac_len = EVP_MD_CTX_size(rl->read_hash_ctx); + if (mac_len <= 0 || mac_len > EVP_MAX_MD_SIZE) + goto err; + } + + /* CBC has at least one padding byte. */ + min_len = eiv_len + mac_len; + if (EVP_CIPHER_CTX_mode(enc) == EVP_CIPH_CBC_MODE) + min_len += 1; + + if (CBS_len(fragment) < min_len) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + if (CBS_len(fragment) > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + rl->alert_desc = SSL_AD_RECORD_OVERFLOW; + goto err; + } + if (CBS_len(fragment) % block_size != 0) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + + /* XXX - decrypt/process in place for now. */ + plain = (uint8_t *)CBS_data(fragment); + plain_len = CBS_len(fragment); + + if (!EVP_Cipher(enc, plain, CBS_data(fragment), plain_len)) + goto err; + + rrec.data = plain; + rrec.input = plain; + rrec.length = plain_len; + + /* + * We now have to remove padding, extract MAC, calculate MAC + * and compare MAC in constant time. + */ + if (block_size > 1) + ssl3_cbc_remove_padding(&rrec, eiv_len, mac_len); + + if ((mac = calloc(1, mac_len)) == NULL) + goto err; + + if (!CBB_init(&cbb_mac, EVP_MAX_MD_SIZE)) + goto err; + if (EVP_CIPHER_CTX_mode(enc) == EVP_CIPH_CBC_MODE) { + ssl3_cbc_copy_mac(mac, &rrec, mac_len, rrec.length + + rrec.padding_length); + rrec.length -= mac_len; + if (!tls12_record_layer_read_mac_cbc(rl, &cbb_mac, content_type, + rrec.input, rrec.length, mac_len, rrec.padding_length)) + goto err; + } else { + rrec.length -= mac_len; + memcpy(mac, rrec.data + rrec.length, mac_len); + if (!tls12_record_layer_read_mac(rl, &cbb_mac, content_type, + rrec.input, rrec.length)) + goto err; + } + if (!CBB_finish(&cbb_mac, &out_mac, &out_mac_len)) + goto err; + if (mac_len != out_mac_len) + goto err; + + if (timingsafe_memcmp(mac, out_mac, mac_len) != 0) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + + if (rrec.length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_len) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + if (rrec.length > SSL3_RT_MAX_PLAIN_LENGTH) { + rl->alert_desc = SSL_AD_RECORD_OVERFLOW; + goto err; + } + + *out = rrec.data; + *out_len = rrec.length; + + ret = 1; + + err: + CBB_cleanup(&cbb_mac); + freezero(mac, mac_len); + freezero(out_mac, out_mac_len); + + return ret; +} + +int +tls12_record_layer_open_record(struct tls12_record_layer *rl, uint8_t *buf, + size_t buf_len, uint8_t **out, size_t *out_len) +{ + CBS cbs, fragment, seq_no; + uint16_t epoch, version; + uint8_t content_type; + + CBS_init(&cbs, buf, buf_len); + + if (!CBS_get_u8(&cbs, &content_type)) + return 0; + if (!CBS_get_u16(&cbs, &version)) + return 0; + if (rl->dtls) { + if (!CBS_get_u16(&cbs, &epoch)) + return 0; + if (!CBS_get_bytes(&cbs, &seq_no, 6)) + return 0; + } + if (!CBS_get_u16_length_prefixed(&cbs, &fragment)) + return 0; + + if (rl->read_aead_ctx != NULL) { + if (!tls12_record_layer_open_record_protected_aead(rl, + content_type, &fragment, out, out_len)) + return 0; + } else if (rl->read_cipher_ctx != NULL) { + if (!tls12_record_layer_open_record_protected_cipher(rl, + content_type, &fragment, out, out_len)) + return 0; + } else { + if (!tls12_record_layer_open_record_plaintext(rl, + content_type, &fragment, out, out_len)) + return 0; + } + + if (!rl->dtls) + tls1_record_sequence_increment(rl->read_seq_num); + + return 1; +} + +static int tls12_record_layer_seal_record_plaintext(struct tls12_record_layer *rl, uint8_t content_type, const uint8_t *content, size_t content_len, CBB *out) { |