From 1853d20a008a85d327f4faa9e07be40a85549f8e Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 12 May 2022 17:21:25 +0100 Subject: [PATCH] Remove unneccesary KTLS code from non-KTLS specific files This also moves other protocol specific code to the protocol specific files. Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/18132) --- ssl/record/methods/ktls_meth.c | 133 ++++++- ssl/record/methods/recmethod_local.h | 86 ++++- ssl/record/methods/ssl3_meth.c | 6 +- ssl/record/methods/tls13_meth.c | 65 +++- ssl/record/methods/tls1_meth.c | 6 +- ssl/record/methods/tls_common.c | 551 ++++++++++----------------- ssl/record/methods/tlsany_meth.c | 107 +++++- ssl/record/rec_layer_s3.c | 2 + ssl/record/recordmethod.h | 16 + ssl/statem/statem.h | 8 - ssl/statem/statem_lib.c | 27 +- ssl/statem/statem_srvr.c | 9 +- 12 files changed, 639 insertions(+), 377 deletions(-) diff --git a/ssl/record/methods/ktls_meth.c b/ssl/record/methods/ktls_meth.c index b6c8aeeb5710a..3a9c836077c40 100644 --- a/ssl/record/methods/ktls_meth.c +++ b/ssl/record/methods/ktls_meth.c @@ -408,6 +408,35 @@ static int ktls_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, return OSSL_RECORD_RETURN_SUCCESS; } +static int ktls_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend, + int clearold, size_t *readbytes) +{ + int ret; + + ret = tls_default_read_n(rl, n, max, extend, clearold, readbytes); + + if (ret < OSSL_RECORD_RETURN_RETRY) { + switch (errno) { + case EBADMSG: + RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC, + SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + break; + case EMSGSIZE: + RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, + SSL_R_PACKET_LENGTH_TOO_LONG); + break; + case EINVAL: + RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, + SSL_R_WRONG_VERSION_NUMBER); + break; + default: + break; + } + } + + return ret; +} + static int ktls_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs, int sending, SSL_MAC_BUF *mac, size_t macsize, /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) @@ -415,8 +444,108 @@ static int ktls_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs return 1; } -struct record_functions_st ossl_ktls_funcs = { +static int ktls_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec) +{ + if (rec->rec_version != TLS1_2_VERSION) { + RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_WRONG_VERSION_NUMBER); + return 0; + } + + return 1; +} + +static int ktls_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, + SSL_CONNECTION *s) +{ + if (rl->version == TLS1_3_VERSION) + return tls13_common_post_process_record(rl, rec, s); + + return 1; +} + +static struct record_functions_st ossl_ktls_funcs = { ktls_set_crypto_state, + ktls_read_n, ktls_cipher, - NULL + NULL, + tls_default_set_protocol_version, + ktls_validate_record_header, + ktls_post_process_record +}; + +static int +ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, + int role, int direction, int level, unsigned char *key, + size_t keylen, unsigned char *iv, size_t ivlen, + unsigned char *mackey, size_t mackeylen, + const EVP_CIPHER *ciph, size_t taglen, + /* TODO(RECLAYER): This probably should not be an int */ + int mactype, + const EVP_MD *md, const SSL_COMP *comp, BIO *transport, + BIO_ADDR *local, BIO_ADDR *peer, + const OSSL_PARAM *settings, const OSSL_PARAM *options, + OSSL_RECORD_LAYER **retrl, + /* TODO(RECLAYER): Remove me */ + SSL_CONNECTION *s) +{ + int ret; + + ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level, + key, keylen, iv, ivlen, mackey, mackeylen, + ciph, taglen, mactype, md, comp, transport, + local, peer, settings, options, retrl, s); + + if (ret != OSSL_RECORD_RETURN_SUCCESS) + return ret; + + (*retrl)->funcs = &ossl_ktls_funcs; + + ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv, + ivlen, mackey, mackeylen, ciph, + taglen, mactype, md, comp, s); + + if (ret != OSSL_RECORD_RETURN_SUCCESS) { + OPENSSL_free(*retrl); + *retrl = NULL; + } else { + /* + * With KTLS we always try and read as much as possible and fill the + * buffer + */ + (*retrl)->read_ahead = 1; + } + return ret; +} + +const OSSL_RECORD_METHOD ossl_ktls_record_method = { + ktls_new_record_layer, + tls_free, + tls_reset, + tls_unprocessed_read_pending, + tls_processed_read_pending, + tls_app_data_pending, + tls_write_pending, + tls_get_max_record_len, + tls_get_max_records, + tls_write_records, + tls_retry_write_records, + tls_read_record, + tls_release_record, + tls_get_alert_code, + tls_set1_bio, + tls_set_protocol_version, + tls_set_plain_alerts, + tls_set_first_handshake, + + /* + * TODO(RECLAYER): Remove these. These function pointers are temporary hacks + * during the record layer refactoring. They need to be removed before the + * refactor is complete. + */ + tls_default_read_n, + tls_get0_rbuf, + tls_get0_packet, + tls_set0_packet, + tls_get_packet_length, + tls_reset_packet_length }; diff --git a/ssl/record/methods/recmethod_local.h b/ssl/record/methods/recmethod_local.h index 2e21a25b87272..ef124c8237c36 100644 --- a/ssl/record/methods/recmethod_local.h +++ b/ssl/record/methods/recmethod_local.h @@ -33,6 +33,9 @@ struct record_functions_st const SSL_COMP *comp, /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s); + + int (*read_n)(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend, + int clearold, size_t *readbytes); /* * Returns: * 0: if the record is publicly invalid, or an internal error, or AEAD @@ -45,6 +48,16 @@ struct record_functions_st /* Returns 1 for success or 0 for error */ int (*mac)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, int sending, /* TODO(RECLAYER): Remove me */SSL_CONNECTION *ssl); + + /* Return 1 for success or 0 for error */ + int (*set_protocol_version)(OSSL_RECORD_LAYER *rl, int version); + + /* Return 1 for success or 0 for error */ + int (*validate_record_header)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec); + + /* Return 1 for success or 0 for error */ + int (*post_process_record)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, + /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s); }; struct ossl_record_layer_st @@ -78,9 +91,6 @@ struct ossl_record_layer_st /* The number of records that have been released via tls_release_record */ size_t num_released; - /* Set to true if this is the first record in a connection */ - unsigned int is_first_record; - /* where we are when reading */ int rstate; @@ -102,18 +112,28 @@ struct ossl_record_layer_st /* cryptographic state */ EVP_CIPHER_CTX *enc_read_ctx; - /* TLSv1.3 static read IV */ - unsigned char read_iv[EVP_MAX_IV_LENGTH]; + /* used for mac generation */ EVP_MD_CTX *read_hash; /* uncompress */ COMP_CTX *expand; + /* Set to 1 if this is the first handshake. 0 otherwise */ + int is_first_handshake; + /* Only used by SSLv3 */ unsigned char mac_secret[EVP_MAX_MD_SIZE]; - /* TLSv1.3 static IV */ + /* TLSv1.3 fields */ + /* static IV */ unsigned char iv[EVP_MAX_IV_LENGTH]; + /* static read IV */ + unsigned char read_iv[EVP_MAX_IV_LENGTH]; + int allow_plain_alerts; + + /* TLS "any" fields */ + /* Set to true if this is the first record in a connection */ + unsigned int is_first_record; size_t taglen; @@ -125,7 +145,6 @@ struct ossl_record_layer_st extern struct record_functions_st ssl_3_0_funcs; extern struct record_functions_st tls_1_funcs; extern struct record_functions_st tls_1_3_funcs; -extern struct record_functions_st ossl_ktls_funcs; extern struct record_functions_st tls_any_funcs; void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason, @@ -153,3 +172,56 @@ __owur int ssl3_cbc_digest_record(const EVP_MD *md, size_t data_plus_mac_plus_padding_size, const unsigned char *mac_secret, size_t mac_secret_length, char is_sslv3); + +int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend, + int clearold, size_t *readbytes); + +int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version); +int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *re); +int tls_default_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, SSL_CONNECTION *s); +int tls13_common_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, + SSL_CONNECTION *s); + +int +tls_int_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, + int role, int direction, int level, unsigned char *key, + size_t keylen, unsigned char *iv, size_t ivlen, + unsigned char *mackey, size_t mackeylen, + const EVP_CIPHER *ciph, size_t taglen, + /* TODO(RECLAYER): This probably should not be an int */ + int mactype, + const EVP_MD *md, const SSL_COMP *comp, BIO *transport, + BIO_ADDR *local, BIO_ADDR *peer, + const OSSL_PARAM *settings, const OSSL_PARAM *options, + OSSL_RECORD_LAYER **retrl, + /* TODO(RECLAYER): Remove me */ + SSL_CONNECTION *s); +void tls_free(OSSL_RECORD_LAYER *rl); +int tls_reset(OSSL_RECORD_LAYER *rl); +int tls_unprocessed_read_pending(OSSL_RECORD_LAYER *rl); +int tls_processed_read_pending(OSSL_RECORD_LAYER *rl); +size_t tls_app_data_pending(OSSL_RECORD_LAYER *rl); +int tls_write_pending(OSSL_RECORD_LAYER *rl); +size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl); +size_t tls_get_max_records(OSSL_RECORD_LAYER *rl); +int tls_write_records(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE **templates, + size_t numtempl, size_t allowance, size_t *sent); +int tls_retry_write_records(OSSL_RECORD_LAYER *rl, size_t allowance, + size_t *sent); +int tls_get_alert_code(OSSL_RECORD_LAYER *rl); +int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio); +int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle, int *rversion, + int *type, unsigned char **data, size_t *datalen, + uint16_t *epoch, unsigned char *seq_num, + /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s); +int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle); +int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version); +int tls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version); +void tls_set_plain_alerts(OSSL_RECORD_LAYER *rl, int allow); +void tls_set_first_handshake(OSSL_RECORD_LAYER *rl, int first); +SSL3_BUFFER *tls_get0_rbuf(OSSL_RECORD_LAYER *rl); +unsigned char *tls_get0_packet(OSSL_RECORD_LAYER *rl); +void tls_set0_packet(OSSL_RECORD_LAYER *rl, unsigned char *packet, + size_t packetlen); +size_t tls_get_packet_length(OSSL_RECORD_LAYER *rl); +void tls_reset_packet_length(OSSL_RECORD_LAYER *rl); diff --git a/ssl/record/methods/ssl3_meth.c b/ssl/record/methods/ssl3_meth.c index 15f5d02c4174a..fa0e1c28a8393 100644 --- a/ssl/record/methods/ssl3_meth.c +++ b/ssl/record/methods/ssl3_meth.c @@ -315,6 +315,10 @@ static int ssl3_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, struct record_functions_st ssl_3_0_funcs = { ssl3_set_crypto_state, + tls_default_read_n, ssl3_cipher, - ssl3_mac + ssl3_mac, + tls_default_set_protocol_version, + tls_default_validate_record_header, + tls_default_post_process_record }; diff --git a/ssl/record/methods/tls13_meth.c b/ssl/record/methods/tls13_meth.c index bc8d5f0a03b87..3ea0f5fec34ce 100644 --- a/ssl/record/methods/tls13_meth.c +++ b/ssl/record/methods/tls13_meth.c @@ -191,8 +191,71 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs, return 1; } +static int tls13_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec) +{ + if (rec->type != SSL3_RT_APPLICATION_DATA + && (rec->type != SSL3_RT_CHANGE_CIPHER_SPEC + || !rl->is_first_handshake) + && (rec->type != SSL3_RT_ALERT || !rl->allow_plain_alerts)) { + RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE); + return 0; + } + + if (rec->rec_version != TLS1_2_VERSION) { + RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_WRONG_VERSION_NUMBER); + return 0; + } + + if (rec->length > SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH) { + RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, + SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + return 0; + } + return 1; +} + +static int tls13_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, + SSL_CONNECTION *s) +{ + /* Skip this if we've received a plaintext alert */ + if (rec->type != SSL3_RT_ALERT) { + size_t end; + + if (rec->length == 0 + || rec->type != SSL3_RT_APPLICATION_DATA) { + RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, + SSL_R_BAD_RECORD_TYPE); + return 0; + } + + /* Strip trailing padding */ + for (end = rec->length - 1; end > 0 && rec->data[end] == 0; + end--) + continue; + + rec->length = end; + rec->type = rec->data[end]; + } + + if (rec->length > SSL3_RT_MAX_PLAIN_LENGTH) { + RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + + if (!tls13_common_post_process_record(rl, rec, s)) { + /* RLAYERfatal already called */ + return 0; + } + + return 1; +} + struct record_functions_st tls_1_3_funcs = { tls13_set_crypto_state, + tls_default_read_n, tls13_cipher, - NULL + NULL, + tls_default_set_protocol_version, + tls13_validate_record_header, + tls13_post_process_record }; diff --git a/ssl/record/methods/tls1_meth.c b/ssl/record/methods/tls1_meth.c index 5c0a8f2cc3dca..2e60778b72ee1 100644 --- a/ssl/record/methods/tls1_meth.c +++ b/ssl/record/methods/tls1_meth.c @@ -591,6 +591,10 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, /* TLSv1.0, TLSv1.1 and TLSv1.2 all use the same funcs */ struct record_functions_st tls_1_funcs = { tls1_set_crypto_state, + tls_default_read_n, tls1_cipher, - tls1_mac + tls1_mac, + tls_default_set_protocol_version, + tls_default_validate_record_header, + tls_default_post_process_record }; diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c index 6189ab3a96cf7..fa6551dffb538 100644 --- a/ssl/record/methods/tls_common.c +++ b/ssl/record/methods/tls_common.c @@ -89,8 +89,6 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) } } -static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio); - static int rlayer_allow_compression(OSSL_RECORD_LAYER *rl) { if (rl->options & SSL_OP_NO_COMPRESSION) @@ -157,7 +155,7 @@ static int rlayer_release_read_buffer(OSSL_RECORD_LAYER *rl) return 1; } -static void tls_reset_packet_length(OSSL_RECORD_LAYER *rl) +void tls_reset_packet_length(OSSL_RECORD_LAYER *rl) { rl->packet_length = 0; } @@ -165,8 +163,8 @@ static void tls_reset_packet_length(OSSL_RECORD_LAYER *rl) /* * Return values are as per SSL_read() */ -static int tls_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend, - int clearold, size_t *readbytes) +int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend, + int clearold, size_t *readbytes) { /* * If extend == 0, obtain new n-byte packet; if extend == 1, increase @@ -272,12 +270,8 @@ static int tls_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend, return OSSL_RECORD_RETURN_FATAL; } - /* - * Ktls always reads full records. - * Also, we always act like read_ahead is set for DTLS. - */ - if (!BIO_get_ktls_recv(rl->bio) && !rl->read_ahead - && !rl->isdtls) { + /* We always act like read_ahead is set for DTLS */ + if (!rl->read_ahead && !rl->isdtls) { /* ignore max parameter */ max = n; } else { @@ -419,7 +413,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, int imac_size; size_t num_recs = 0, max_recs, j; PACKET pkt, sslv2pkt; - int using_ktls; SSL_MAC_BUF *macbufs = NULL; int ret = OSSL_RECORD_RETURN_FATAL; SSL *ssl = SSL_CONNECTION_GET_SSL(s); @@ -438,12 +431,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, max_recs = 1; sess = s->session; - /* - * KTLS reads full records. If there is any data left, - * then it is from before enabling ktls. - */ - using_ktls = BIO_get_ktls_recv(rl->bio) && SSL3_BUFFER_get_left(rbuf) == 0; - do { thisrr = &rr[num_recs]; @@ -453,33 +440,13 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, size_t sslv2len; unsigned int type; - rret = tls_read_n(rl, SSL3_RT_HEADER_LENGTH, - SSL3_BUFFER_get_len(rbuf), 0, - num_recs == 0 ? 1 : 0, &n); - - if (rret < OSSL_RECORD_RETURN_SUCCESS) { -#ifndef OPENSSL_NO_KTLS - if (!BIO_get_ktls_recv(rl->bio) || rret == 0) - return rret; /* error or non-blocking */ - switch (errno) { - case EBADMSG: - RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC, - SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); - break; - case EMSGSIZE: - RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, - SSL_R_PACKET_LENGTH_TOO_LONG); - break; - case EINVAL: - RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, - SSL_R_WRONG_VERSION_NUMBER); - break; - default: - break; - } -#endif - return rret; - } + rret = rl->funcs->read_n(rl, SSL3_RT_HEADER_LENGTH, + SSL3_BUFFER_get_len(rbuf), 0, + num_recs == 0 ? 1 : 0, &n); + + if (rret < OSSL_RECORD_RETURN_SUCCESS) + return rret; /* error or non-blocking */ + rl->rstate = SSL_ST_READ_BODY; p = rl->packet; @@ -520,11 +487,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, SSL_R_PACKET_LENGTH_TOO_LONG); return OSSL_RECORD_RETURN_FATAL; } - - if (thisrr->length < MIN_SSL2_RECORD_LEN) { - RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT); - return OSSL_RECORD_RETURN_FATAL; - } } else { /* SSLv3+ style record */ @@ -545,89 +507,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, s->msg_callback(0, version, SSL3_RT_HEADER, p, 5, ssl, s->msg_callback_arg); - /* - * Lets check version. In TLSv1.3 we only check this field - * when encryption is occurring (see later check). For the - * ServerHello after an HRR we haven't actually selected TLSv1.3 - * yet, but we still treat it as TLSv1.3, so we must check for - * that explicitly - */ - if (!s->first_packet && !SSL_CONNECTION_IS_TLS13(s) - && s->hello_retry_request != SSL_HRR_PENDING - && version != (unsigned int)s->version) { - if ((s->version & 0xFF00) == (version & 0xFF00) - && !s->enc_write_ctx && !s->write_hash) { - if (thisrr->type == SSL3_RT_ALERT) { - /* - * The record is using an incorrect version number, - * but what we've got appears to be an alert. We - * haven't read the body yet to check whether its a - * fatal or not - but chances are it is. We probably - * shouldn't send a fatal alert back. We'll just - * end. - */ - RLAYERfatal(rl, SSL_AD_NO_ALERT, - SSL_R_WRONG_VERSION_NUMBER); - return OSSL_RECORD_RETURN_FATAL; - } - /* - * Send back error using their minor version number :-) - */ - s->version = (unsigned short)version; - } - RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, - SSL_R_WRONG_VERSION_NUMBER); - return OSSL_RECORD_RETURN_FATAL; - } - - if ((version >> 8) != SSL3_VERSION_MAJOR) { - if (rl->is_first_record) { - /* Go back to start of packet, look at the five bytes - * that we have. */ - p = rl->packet; - if (HAS_PREFIX((char *)p, "GET ") || - HAS_PREFIX((char *)p, "POST ") || - HAS_PREFIX((char *)p, "HEAD ") || - HAS_PREFIX((char *)p, "PUT ")) { - RLAYERfatal(rl, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST); - return OSSL_RECORD_RETURN_FATAL; - } else if (HAS_PREFIX((char *)p, "CONNE")) { - RLAYERfatal(rl, SSL_AD_NO_ALERT, - SSL_R_HTTPS_PROXY_REQUEST); - return OSSL_RECORD_RETURN_FATAL; - } - - /* Doesn't look like TLS - don't send an alert */ - RLAYERfatal(rl, SSL_AD_NO_ALERT, - SSL_R_WRONG_VERSION_NUMBER); - return OSSL_RECORD_RETURN_FATAL; - } else { - RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, - SSL_R_WRONG_VERSION_NUMBER); - return OSSL_RECORD_RETURN_FATAL; - } - } - - if (SSL_CONNECTION_IS_TLS13(s) - && rl->enc_read_ctx != NULL - && !using_ktls) { - if (thisrr->type != SSL3_RT_APPLICATION_DATA - && (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC - || !SSL_IS_FIRST_HANDSHAKE(s)) - && (thisrr->type != SSL3_RT_ALERT - || s->statem.enc_read_state - != ENC_READ_STATE_ALLOW_PLAIN_ALERTS)) { - RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, - SSL_R_BAD_RECORD_TYPE); - return OSSL_RECORD_RETURN_FATAL; - } - if (thisrr->rec_version != TLS1_2_VERSION) { - RLAYERfatal(rl, SSL_AD_DECODE_ERROR, - SSL_R_WRONG_VERSION_NUMBER); - return OSSL_RECORD_RETURN_FATAL; - } - } - if (thisrr->length > SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) { RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, @@ -636,42 +515,12 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, } } - /* now rl->rstate == SSL_ST_READ_BODY */ - } - - if (SSL_CONNECTION_IS_TLS13(s)) { - size_t len = SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH; - - /* KTLS strips the inner record type. */ - if (using_ktls) - len = SSL3_RT_MAX_ENCRYPTED_LENGTH; - - if (thisrr->length > len) { - RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, - SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + if (!rl->funcs->validate_record_header(rl, thisrr)) { + /* RLAYERfatal already called */ return OSSL_RECORD_RETURN_FATAL; } - } else { - size_t len = SSL3_RT_MAX_ENCRYPTED_LENGTH; -#ifndef OPENSSL_NO_COMP - /* - * If OPENSSL_NO_COMP is defined then SSL3_RT_MAX_ENCRYPTED_LENGTH - * does not include the compression overhead anyway. - */ - if (s->expand == NULL) - len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD; -#endif - - /* KTLS may use all of the buffer */ - if (using_ktls) - len = SSL3_BUFFER_get_left(rbuf); - - if (thisrr->length > len) { - RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, - SSL_R_ENCRYPTED_LENGTH_TOO_LONG); - return OSSL_RECORD_RETURN_FATAL; - } + /* now rl->rstate == SSL_ST_READ_BODY */ } /* @@ -688,7 +537,7 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, if (more > 0) { /* now rl->packet_length == SSL3_RT_HEADER_LENGTH */ - rret = tls_read_n(rl, more, more, 1, 0, &n); + rret = rl->funcs->read_n(rl, more, more, 1, 0, &n); if (rret < OSSL_RECORD_RETURN_SUCCESS) return rret; /* error or non-blocking io */ } @@ -742,7 +591,7 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, if (num_recs == 1 && thisrr->type == SSL3_RT_CHANGE_CIPHER_SPEC && (SSL_CONNECTION_IS_TLS13(s) || s->hello_retry_request != SSL_HRR_NONE) - && SSL_IS_FIRST_HANDSHAKE(s)) { + && rl->is_first_handshake) { /* * CCS messages must be exactly 1 byte long, containing the value 0x01 */ @@ -769,9 +618,6 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, return OSSL_RECORD_RETURN_SUCCESS; } - if (using_ktls) - goto skip_decryption; - if (rl->read_hash != NULL) { const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(rl->read_hash); @@ -908,85 +754,11 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, goto end; } - skip_decryption: - for (j = 0; j < num_recs; j++) { thisrr = &rr[j]; - /* thisrr->length is now just compressed */ - if (s->expand != NULL) { - if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) { - RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, - SSL_R_COMPRESSED_LENGTH_TOO_LONG); - goto end; - } - if (!ssl3_do_uncompress(s, thisrr)) { - RLAYERfatal(rl, SSL_AD_DECOMPRESSION_FAILURE, - SSL_R_BAD_DECOMPRESSION); - goto end; - } - } - - if (SSL_CONNECTION_IS_TLS13(s) - && rl->enc_read_ctx != NULL - && thisrr->type != SSL3_RT_ALERT) { - /* - * The following logic are irrelevant in KTLS: the kernel provides - * unprotected record and thus record type represent the actual - * content type, and padding is already removed and thisrr->type and - * thisrr->length should have the correct values. - */ - if (!using_ktls) { - size_t end; - - if (thisrr->length == 0 - || thisrr->type != SSL3_RT_APPLICATION_DATA) { - RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, - SSL_R_BAD_RECORD_TYPE); - goto end; - } - - /* Strip trailing padding */ - for (end = thisrr->length - 1; end > 0 && thisrr->data[end] == 0; - end--) - continue; - - thisrr->length = end; - thisrr->type = thisrr->data[end]; - } - if (thisrr->type != SSL3_RT_APPLICATION_DATA - && thisrr->type != SSL3_RT_ALERT - && thisrr->type != SSL3_RT_HANDSHAKE) { - RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE); - goto end; - } - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_INNER_CONTENT_TYPE, - &thisrr->type, 1, ssl, s->msg_callback_arg); - } - - /* - * TLSv1.3 alert and handshake records are required to be non-zero in - * length. - */ - if (SSL_CONNECTION_IS_TLS13(s) - && (thisrr->type == SSL3_RT_HANDSHAKE - || thisrr->type == SSL3_RT_ALERT) - && thisrr->length == 0) { - RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_LENGTH); - goto end; - } - - /* - * Usually thisrr->length is the length of a single record, but when - * KTLS handles the decryption, thisrr->length may be larger than - * SSL3_RT_MAX_PLAIN_LENGTH because the kernel may have coalesced - * multiple records. - * Therefore we have to rely on KTLS to check the plaintext length - * limit in the kernel. - */ - if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH && !using_ktls) { - RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG); + if (!rl->funcs->post_process_record(rl, thisrr, s)) { + /* RLAYERfatal already called */ goto end; } @@ -1045,11 +817,118 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl, return ret; } -static int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle, - int *rversion, int *type, unsigned char **data, - size_t *datalen, uint16_t *epoch, - unsigned char *seq_num, - /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) +/* Shared by ssl3_meth and tls1_meth */ +int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec) +{ + size_t len = SSL3_RT_MAX_ENCRYPTED_LENGTH; + + if (rec->rec_version != rl->version) { + RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, SSL_R_WRONG_VERSION_NUMBER); + return 0; + } + +#ifndef OPENSSL_NO_COMP + /* + * If OPENSSL_NO_COMP is defined then SSL3_RT_MAX_ENCRYPTED_LENGTH + * does not include the compression overhead anyway. + */ + if (rl->expand == NULL) + len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD; +#endif + + if (rec->length > len) { + RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, + SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + return 0; + } + + return 1; +} + +static int tls_do_uncompress(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec) +{ +#ifndef OPENSSL_NO_COMP + int i; + + if (rec->comp == NULL) { + rec->comp = (unsigned char *) + OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); + } + if (rec->comp == NULL) + return 0; + + i = COMP_expand_block(rl->expand, rec->comp, + SSL3_RT_MAX_PLAIN_LENGTH, rec->data, (int)rec->length); + if (i < 0) + return 0; + else + rec->length = i; + rec->data = rec->comp; + return 1; +#else + return 0; +#endif +} + +/* Shared by tlsany_meth, ssl3_meth and tls1_meth */ +int tls_default_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, SSL_CONNECTION *s) +{ + if (rl->expand != NULL) { + if (rec->length > SSL3_RT_MAX_COMPRESSED_LENGTH) { + RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, + SSL_R_COMPRESSED_LENGTH_TOO_LONG); + return 0; + } + if (!tls_do_uncompress(rl, rec)) { + RLAYERfatal(rl, SSL_AD_DECOMPRESSION_FAILURE, + SSL_R_BAD_DECOMPRESSION); + return 0; + } + } + + if (rec->length > SSL3_RT_MAX_PLAIN_LENGTH) { + RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + + return 1; +} + +/* Shared by tls13_meth and ktls_meth */ +int tls13_common_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, + SSL_CONNECTION *s) +{ + SSL *ssl = SSL_CONNECTION_GET_SSL(s); + + if (rec->type != SSL3_RT_APPLICATION_DATA + && rec->type != SSL3_RT_ALERT + && rec->type != SSL3_RT_HANDSHAKE) { + RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE); + return 0; + } + + if (s->msg_callback) + s->msg_callback(0, rl->version, SSL3_RT_INNER_CONTENT_TYPE, + &rec->type, 1, ssl, s->msg_callback_arg); + + /* + * TLSv1.3 alert and handshake records are required to be non-zero in + * length. + */ + if ((rec->type == SSL3_RT_HANDSHAKE + || rec->type == SSL3_RT_ALERT) + && rec->length == 0) { + RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_LENGTH); + return 0; + } + + return 1; +} + +int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle, int *rversion, + int *type, unsigned char **data, size_t *datalen, + uint16_t *epoch, unsigned char *seq_num, + /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) { SSL3_RECORD *rec; @@ -1088,7 +967,7 @@ static int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle, return OSSL_RECORD_RETURN_SUCCESS; } -static int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle) +int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle) { if (!ossl_assert(rl->num_released < rl->curr_rec) || !ossl_assert(rechandle == &rl->rrec[rl->num_released])) { @@ -1102,7 +981,7 @@ static int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle) return OSSL_RECORD_RETURN_SUCCESS; } -static int +int tls_int_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, int role, int direction, int level, unsigned char *key, size_t keylen, unsigned char *iv, size_t ivlen, @@ -1173,7 +1052,7 @@ tls_int_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, rl->role = role; rl->direction = direction; - if (level == 0) + if (level == OSSL_RECORD_PROTECTION_LEVEL_NONE) rl->is_first_record = 1; if (!tls_set1_bio(rl, transport)) @@ -1245,39 +1124,23 @@ tls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, return ret; } -static int -dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, - int role, int direction, int level, unsigned char *key, - size_t keylen, unsigned char *iv, size_t ivlen, - unsigned char *mackey, size_t mackeylen, - const EVP_CIPHER *ciph, size_t taglen, - /* TODO(RECLAYER): This probably should not be an int */ - int mactype, - const EVP_MD *md, const SSL_COMP *comp, BIO *transport, - BIO_ADDR *local, BIO_ADDR *peer, - const OSSL_PARAM *settings, const OSSL_PARAM *options, - OSSL_RECORD_LAYER **retrl, - /* TODO(RECLAYER): Remove me */ - SSL_CONNECTION *s) +/* TODO(RECLAYER): Temporary funcs */ +static int dtls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version) { - int ret; - - ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level, - key, keylen, iv, ivlen, mackey, mackeylen, - ciph, taglen, mactype, md, comp, transport, - local, peer, settings, options, retrl, s); - - if (ret != OSSL_RECORD_RETURN_SUCCESS) - return ret; - - (*retrl)->isdtls = 1; - - return OSSL_RECORD_RETURN_SUCCESS; + rl->version = version; + return 1; } +static struct record_functions_st dtls_funcs = { + NULL, + NULL, + NULL, + NULL, + dtls_set_protocol_version, + NULL +}; -#ifndef OPENSSL_NO_KTLS static int -ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, +dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, int role, int direction, int level, unsigned char *key, size_t keylen, unsigned char *iv, size_t ivlen, unsigned char *mackey, size_t mackeylen, @@ -1293,6 +1156,7 @@ ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, { int ret; + ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level, key, keylen, iv, ivlen, mackey, mackeylen, ciph, taglen, mactype, md, comp, transport, @@ -1301,83 +1165,74 @@ ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, if (ret != OSSL_RECORD_RETURN_SUCCESS) return ret; - (*retrl)->funcs = &ossl_ktls_funcs; - - ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv, - ivlen, mackey, mackeylen, ciph, - taglen, mactype, md, comp, s); + (*retrl)->isdtls = 1; + (*retrl)->funcs = &dtls_funcs; - if (ret != OSSL_RECORD_RETURN_SUCCESS) { - OPENSSL_free(*retrl); - *retrl = NULL; - } - return ret; + return OSSL_RECORD_RETURN_SUCCESS; } -#endif -static void tls_free(OSSL_RECORD_LAYER *rl) +void tls_free(OSSL_RECORD_LAYER *rl) { /* TODO(RECLAYER): Cleanse sensitive fields */ BIO_free(rl->bio); OPENSSL_free(rl); } -static int tls_reset(OSSL_RECORD_LAYER *rl) +int tls_reset(OSSL_RECORD_LAYER *rl) { memset(rl, 0, sizeof(*rl)); return 1; } -static int tls_unprocessed_read_pending(OSSL_RECORD_LAYER *rl) +int tls_unprocessed_read_pending(OSSL_RECORD_LAYER *rl) { return SSL3_BUFFER_get_left(&rl->rbuf) != 0;; } -static int tls_processed_read_pending(OSSL_RECORD_LAYER *rl) +int tls_processed_read_pending(OSSL_RECORD_LAYER *rl) { return rl->curr_rec < rl->num_recs; } -static size_t tls_app_data_pending(OSSL_RECORD_LAYER *rl) +size_t tls_app_data_pending(OSSL_RECORD_LAYER *rl) { return 0; } -static int tls_write_pending(OSSL_RECORD_LAYER *rl) +int tls_write_pending(OSSL_RECORD_LAYER *rl) { return 0; } -static size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl) +size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl) { return 0; } -static size_t tls_get_max_records(OSSL_RECORD_LAYER *rl) +size_t tls_get_max_records(OSSL_RECORD_LAYER *rl) { return 0; } -static int tls_write_records(OSSL_RECORD_LAYER *rl, - OSSL_RECORD_TEMPLATE **templates, size_t numtempl, - size_t allowance, size_t *sent) +int tls_write_records(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE **templates, + size_t numtempl, size_t allowance, size_t *sent) { return 0; } -static int tls_retry_write_records(OSSL_RECORD_LAYER *rl, size_t allowance, - size_t *sent) +int tls_retry_write_records(OSSL_RECORD_LAYER *rl, size_t allowance, + size_t *sent) { return 0; } -static int tls_get_alert_code(OSSL_RECORD_LAYER *rl) +int tls_get_alert_code(OSSL_RECORD_LAYER *rl) { return rl->alert; } -static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio) +int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio) { if (bio != NULL && !BIO_up_ref(bio)) return 0; @@ -1387,24 +1242,48 @@ static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio) return 1; } -static SSL3_BUFFER *tls_get0_rbuf(OSSL_RECORD_LAYER *rl) +/* Shared by most methods except tlsany_meth */ +int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version) +{ + if (rl->version != version) + return 0; + + return 1; +} + +int tls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version) +{ + return rl->funcs->set_protocol_version(rl, version); +} + +void tls_set_plain_alerts(OSSL_RECORD_LAYER *rl, int allow) +{ + rl->allow_plain_alerts = allow; +} + +void tls_set_first_handshake(OSSL_RECORD_LAYER *rl, int first) +{ + rl->is_first_handshake = first; +} + +SSL3_BUFFER *tls_get0_rbuf(OSSL_RECORD_LAYER *rl) { return &rl->rbuf; } -static unsigned char *tls_get0_packet(OSSL_RECORD_LAYER *rl) +unsigned char *tls_get0_packet(OSSL_RECORD_LAYER *rl) { return rl->packet; } -static void tls_set0_packet(OSSL_RECORD_LAYER *rl, unsigned char *packet, - size_t packetlen) +void tls_set0_packet(OSSL_RECORD_LAYER *rl, unsigned char *packet, + size_t packetlen) { rl->packet = packet; rl->packet_length = packetlen; } -static size_t tls_get_packet_length(OSSL_RECORD_LAYER *rl) +size_t tls_get_packet_length(OSSL_RECORD_LAYER *rl) { return rl->packet_length; } @@ -1425,51 +1304,22 @@ const OSSL_RECORD_METHOD ossl_tls_record_method = { tls_release_record, tls_get_alert_code, tls_set1_bio, + tls_set_protocol_version, + tls_set_plain_alerts, + tls_set_first_handshake, /* * TODO(RECLAYER): Remove these. These function pointers are temporary hacks * during the record layer refactoring. They need to be removed before the * refactor is complete. */ - tls_read_n, - tls_get0_rbuf, - tls_get0_packet, - tls_set0_packet, - tls_get_packet_length, - tls_reset_packet_length -}; - -#ifndef OPENSSL_NO_KTLS -const OSSL_RECORD_METHOD ossl_ktls_record_method = { - ktls_new_record_layer, - tls_free, - tls_reset, - tls_unprocessed_read_pending, - tls_processed_read_pending, - tls_app_data_pending, - tls_write_pending, - tls_get_max_record_len, - tls_get_max_records, - tls_write_records, - tls_retry_write_records, - tls_read_record, - tls_release_record, - tls_get_alert_code, - tls_set1_bio, - - /* - * TODO(RECLAYER): Remove these. These function pointers are temporary hacks - * during the record layer refactoring. They need to be removed before the - * refactor is complete. - */ - tls_read_n, + tls_default_read_n, tls_get0_rbuf, tls_get0_packet, tls_set0_packet, tls_get_packet_length, tls_reset_packet_length }; -#endif const OSSL_RECORD_METHOD ossl_dtls_record_method = { dtls_new_record_layer, @@ -1487,13 +1337,16 @@ const OSSL_RECORD_METHOD ossl_dtls_record_method = { tls_release_record, tls_get_alert_code, tls_set1_bio, + tls_set_protocol_version, + NULL, + tls_set_first_handshake, /* * TODO(RECLAYER): Remove these. These function pointers are temporary hacks * during the record layer refactoring. They need to be removed before the * refactor is complete. */ - tls_read_n, + tls_default_read_n, tls_get0_rbuf, tls_get0_packet, tls_set0_packet, diff --git a/ssl/record/methods/tlsany_meth.c b/ssl/record/methods/tlsany_meth.c index cde57a41cc05d..12443261ea1ef 100644 --- a/ssl/record/methods/tlsany_meth.c +++ b/ssl/record/methods/tlsany_meth.c @@ -43,8 +43,113 @@ static int tls_any_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, return 1; } +static int tls_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec) +{ + if (rec->rec_version == SSL2_VERSION) { + /* SSLv2 format ClientHello */ + if (!ossl_assert(rl->version == TLS_ANY_VERSION)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + if (rec->length < MIN_SSL2_RECORD_LEN) { + RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT); + return 0; + } + } else { + if (rl->version == TLS_ANY_VERSION) { + if ((rec->rec_version >> 8) != SSL3_VERSION_MAJOR) { + if (rl->is_first_record) { + unsigned char *p; + + /* + * Go back to start of packet, look at the five bytes that + * we have. + */ + p = rl->packet; + if (HAS_PREFIX((char *)p, "GET ") || + HAS_PREFIX((char *)p, "POST ") || + HAS_PREFIX((char *)p, "HEAD ") || + HAS_PREFIX((char *)p, "PUT ")) { + RLAYERfatal(rl, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST); + return 0; + } else if (HAS_PREFIX((char *)p, "CONNE")) { + RLAYERfatal(rl, SSL_AD_NO_ALERT, + SSL_R_HTTPS_PROXY_REQUEST); + return 0; + } + + /* Doesn't look like TLS - don't send an alert */ + RLAYERfatal(rl, SSL_AD_NO_ALERT, + SSL_R_WRONG_VERSION_NUMBER); + return 0; + } else { + RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, + SSL_R_WRONG_VERSION_NUMBER); + return 0; + } + } + } else if (rl->version == TLS1_3_VERSION) { + /* + * In this case we know we are going to negotiate TLSv1.3, but we've + * had an HRR, so we haven't actually done so yet. Nonetheless we + * still expect the record version to be TLSv1.2 as per a normal + * TLSv1.3 record + */ + if (rec->rec_version != TLS1_2_VERSION) { + RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, + SSL_R_WRONG_VERSION_NUMBER); + return 0; + } + } else if (rec->rec_version != rl->version) { + if ((rl->version & 0xFF00) == (rec->rec_version & 0xFF00)) { + if (rec->type == SSL3_RT_ALERT) { + /* + * The record is using an incorrect version number, + * but what we've got appears to be an alert. We + * haven't read the body yet to check whether its a + * fatal or not - but chances are it is. We probably + * shouldn't send a fatal alert back. We'll just + * end. + */ + RLAYERfatal(rl, SSL_AD_NO_ALERT, + SSL_R_WRONG_VERSION_NUMBER); + return 0; + } + /* Send back error using their minor version number */ + rl->version = (unsigned short)rec->rec_version; + } + RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION, + SSL_R_WRONG_VERSION_NUMBER); + return 0; + } + } + if (rec->length > SSL3_RT_MAX_PLAIN_LENGTH) { + /* + * We use SSL_R_DATA_LENGTH_TOO_LONG instead of + * SSL_R_ENCRYPTED_LENGTH_TOO_LONG here because we are the "any" method + * and we know that we are dealing with plaintext data + */ + RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + return 1; +} + +static int tls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers) +{ + if (rl->version != TLS_ANY_VERSION && rl->version != vers) + return 0; + rl->version = vers; + + return 1; +} + struct record_functions_st tls_any_funcs = { tls_any_set_crypto_state, + tls_default_read_n, tls_any_cipher, - NULL + NULL, + tls_any_set_protocol_version, + tls_validate_record_header, + tls_default_post_process_record }; diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index deb108cfc77d9..c5f4591391005 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -1783,6 +1783,8 @@ static int ssl_post_record_layer_select(SSL_CONNECTION *s) SSL_set_options(ssl, SSL_OP_NO_RENEGOTIATION); } #endif + if (SSL_IS_FIRST_HANDSHAKE(s) && s->rrlmethod->set_first_handshake != NULL) + s->rrlmethod->set_first_handshake(s->rrl, 1); return 1; } diff --git a/ssl/record/recordmethod.h b/ssl/record/recordmethod.h index 43562e36b4def..8f025cc7859d3 100644 --- a/ssl/record/recordmethod.h +++ b/ssl/record/recordmethod.h @@ -284,6 +284,22 @@ struct ossl_record_method_st { */ int (*set1_bio)(OSSL_RECORD_LAYER *rl, BIO *bio); + /* Called when protocol negotiation selects a protocol version to use */ + int (*set_protocol_version)(OSSL_RECORD_LAYER *rl, int version); + + /* + * Whether we are allowed to receive unencrypted alerts, even if we might + * otherwise expect encrypted records. Ignored by protocol versions where + * this isn't relevant + */ + void (*set_plain_alerts)(OSSL_RECORD_LAYER *rl, int allow); + + /* + * Called immediately after creation of the recory layer if we are in a + * first handshake. Also called at the end of the first handshake + */ + void (*set_first_handshake)(OSSL_RECORD_LAYER *rl, int first); + /* * TODO(RECLAYER): Remove these. These function pointers are temporary hacks * during the record layer refactoring. They need to be removed before the diff --git a/ssl/statem/statem.h b/ssl/statem/statem.h index b904ee50c80e6..7dbe71ed7d48a 100644 --- a/ssl/statem/statem.h +++ b/ssl/statem/statem.h @@ -80,13 +80,6 @@ typedef enum { ENC_WRITE_STATE_WRITE_PLAIN_ALERTS } ENC_WRITE_STATES; -typedef enum { - /* The enc_read_ctx can be used normally */ - ENC_READ_STATE_VALID, - /* We may receive encrypted or plaintext alerts */ - ENC_READ_STATE_ALLOW_PLAIN_ALERTS -} ENC_READ_STATES; - /***************************************************************************** * * * This structure should be considered "opaque" to anything outside of the * @@ -117,7 +110,6 @@ struct ossl_statem_st { unsigned int no_cert_verify; int use_timer; ENC_WRITE_STATES enc_write_state; - ENC_READ_STATES enc_read_state; }; typedef struct ossl_statem_st OSSL_STATEM; diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 70d194ff815f0..d1614a56d886c 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -794,16 +794,18 @@ MSG_PROCESS_RETURN tls_process_finished(SSL_CONNECTION *s, PACKET *pkt) { size_t md_len; SSL *ssl = SSL_CONNECTION_GET_SSL(s); + int was_first = SSL_IS_FIRST_HANDSHAKE(s); /* This is a real handshake so make sure we clean it up at the end */ if (s->server) { /* * To get this far we must have read encrypted data from the client. We - * no longer tolerate unencrypted alerts. This value is ignored if less - * than TLSv1.3 + * no longer tolerate unencrypted alerts. This is ignored if less than + * TLSv1.3 */ - s->statem.enc_read_state = ENC_READ_STATE_VALID; + if (s->rrlmethod->set_plain_alerts != NULL) + s->rrlmethod->set_plain_alerts(s->rrl, 0); if (s->post_handshake_auth != SSL_PHA_REQUESTED) s->statem.cleanuphand = 1; if (SSL_CONNECTION_IS_TLS13(s) @@ -893,6 +895,11 @@ MSG_PROCESS_RETURN tls_process_finished(SSL_CONNECTION *s, PACKET *pkt) } } + if (was_first + && !SSL_IS_FIRST_HANDSHAKE(s) + && s->rrlmethod->set_first_handshake != NULL) + s->rrlmethod->set_first_handshake(s->rrl, 0); + return MSG_PROCESS_FINISHED_READING; } @@ -1873,6 +1880,9 @@ int ssl_choose_server_version(SSL_CONNECTION *s, CLIENTHELLO_MSG *hello, check_for_downgrade(s, best_vers, dgrd); s->version = best_vers; ssl->method = best_method; + if (!s->rrlmethod->set_protocol_version(s->rrl, best_vers)) + return ERR_R_INTERNAL_ERROR; + return 0; } return SSL_R_UNSUPPORTED_PROTOCOL; @@ -1900,6 +1910,9 @@ int ssl_choose_server_version(SSL_CONNECTION *s, CLIENTHELLO_MSG *hello, check_for_downgrade(s, vent->version, dgrd); s->version = vent->version; ssl->method = method; + if (!s->rrlmethod->set_protocol_version(s->rrl, s->version)) + return ERR_R_INTERNAL_ERROR; + return 0; } disabled = 1; @@ -1959,6 +1972,10 @@ int ssl_choose_client_version(SSL_CONNECTION *s, int version, * versions they don't want. If not, then easy to fix, just return * ssl_method_error(s, s->method) */ + if (!s->rrlmethod->set_protocol_version(s->rrl, s->version)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } return 1; case TLS_ANY_VERSION: table = tls_version_table; @@ -2019,6 +2036,10 @@ int ssl_choose_client_version(SSL_CONNECTION *s, int version, continue; ssl->method = vent->cmeth(); + if (!s->rrlmethod->set_protocol_version(s->rrl, s->version)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } return 1; } diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index db6d40682c036..2ed19231abdc1 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -914,7 +914,8 @@ WORK_STATE ossl_statem_server_post_work(SSL_CONNECTION *s, WORK_STATE wst) * is an unencrypted alert, an encrypted alert, or an encrypted * handshake message. We temporarily tolerate unencrypted alerts. */ - s->statem.enc_read_state = ENC_READ_STATE_ALLOW_PLAIN_ALERTS; + if (s->rrlmethod->set_plain_alerts != NULL) + s->rrlmethod->set_plain_alerts(s->rrl, 1); break; } @@ -3455,10 +3456,10 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL_CONNECTION *s, /* * To get this far we must have read encrypted data from the client. We no - * longer tolerate unencrypted alerts. This value is ignored if less than - * TLSv1.3 + * longer tolerate unencrypted alerts. This is ignored if less than TLSv1.3 */ - s->statem.enc_read_state = ENC_READ_STATE_VALID; + if (s->rrlmethod->set_plain_alerts != NULL) + s->rrlmethod->set_plain_alerts(s->rrl, 0); if ((sk = sk_X509_new_null()) == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);