diff --git a/ssl/record/methods/ktls_meth.c b/ssl/record/methods/ktls_meth.c index dbf42b4d46..e794d3bfe7 100644 --- a/ssl/record/methods/ktls_meth.c +++ b/ssl/record/methods/ktls_meth.c @@ -15,6 +15,8 @@ #include "recmethod_local.h" #include "internal/ktls.h" +static struct record_functions_st ossl_ktls_funcs; + #if defined(__FreeBSD__) # include "crypto/cryptodev.h" @@ -389,19 +391,6 @@ static int ktls_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec) return 1; } -static struct record_functions_st ossl_ktls_funcs = { - ktls_set_crypto_state, - ktls_cipher, - NULL, - tls_default_set_protocol_version, - ktls_read_n, - tls_get_more_records, - ktls_validate_record_header, - ktls_post_process_record, - tls_get_max_records_default, - tls_write_records_default -}; - static int ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, int role, int direction, int level, uint16_t epoch, @@ -445,6 +434,67 @@ ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, return ret; } +static int ktls_allocate_write_buffers(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, size_t *prefix) +{ + if (!ossl_assert(numtempl == 1)) + return 0; + + /* + * We just use the end application buffer in the case of KTLS, so nothing + * to do. We pretend we set up one buffer. + */ + rl->numwpipes = 1; + + return 1; +} + +static int ktls_initialise_write_packets(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, + OSSL_RECORD_TEMPLATE *prefixtempl, + WPACKET *pkt, + SSL3_BUFFER *bufs, + size_t *wpinited) +{ + SSL3_BUFFER *wb; + + /* + * We just use the application buffer directly, and don't use any WPACKET + * structures + */ + wb = &bufs[0]; + wb->type = templates[0].type; + + /* + * ktls doesn't modify the buffer, but to avoid a warning we need + * to discard the const qualifier. + * This doesn't leak memory because the buffers have been + * released when switching to ktls. + */ + SSL3_BUFFER_set_buf(wb, (unsigned char *)templates[0].buf); + SSL3_BUFFER_set_offset(wb, 0); + SSL3_BUFFER_set_app_buffer(wb, 1); + + return 1; +} + +static struct record_functions_st ossl_ktls_funcs = { + ktls_set_crypto_state, + ktls_cipher, + NULL, + tls_default_set_protocol_version, + ktls_read_n, + tls_get_more_records, + ktls_validate_record_header, + ktls_post_process_record, + tls_get_max_records_default, + tls_write_records_default, + ktls_allocate_write_buffers, + ktls_initialise_write_packets +}; + const OSSL_RECORD_METHOD ossl_ktls_record_method = { ktls_new_record_layer, tls_free, diff --git a/ssl/record/methods/recmethod_local.h b/ssl/record/methods/recmethod_local.h index eda50050e2..4bb040d345 100644 --- a/ssl/record/methods/recmethod_local.h +++ b/ssl/record/methods/recmethod_local.h @@ -74,6 +74,27 @@ struct record_functions_st /* Return 1 for success or 0 for error */ int (*write_records)(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates, size_t numtempl); + + /* Allocate the rl->wbuf buffers. Return 1 for success or 0 for error */ + int (*allocate_write_buffers)(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, size_t *prefix); + + /* + * Initialise the packets in the |pkt| array using the buffers in |rl->wbuf|. + * Some protocol versions may use the space in |prefixtempl| to add + * an artificial template in front of the |templates| array and hence may + * initialise 1 more WPACKET than there are templates. |*wpinited| + * returns the number of WPACKETs in |pkt| that were successfully + * initialised. This must be 0 on entry and will be filled in even on error. + */ + int (*initialise_write_packets)(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, + OSSL_RECORD_TEMPLATE *prefixtempl, + WPACKET *pkt, + SSL3_BUFFER *bufs, + size_t *wpinited); }; struct ossl_record_layer_st @@ -343,6 +364,26 @@ int tls_write_records_multiblock(OSSL_RECORD_LAYER *rl, size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, int type, size_t len, size_t maxfrag, size_t *preffrag); +int tls_allocate_write_buffers_default(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, size_t *prefix); +int tls_initialise_write_packets_default(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, + OSSL_RECORD_TEMPLATE *prefixtempl, + WPACKET *pkt, + SSL3_BUFFER *bufs, + size_t *wpinited); +int tls1_allocate_write_buffers(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, size_t *prefix); +int tls1_initialise_write_packets(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, + OSSL_RECORD_TEMPLATE *prefixtempl, + WPACKET *pkt, + SSL3_BUFFER *bufs, + size_t *wpinited); size_t tls_get_max_records_multiblock(OSSL_RECORD_LAYER *rl, int type, size_t len, size_t maxfrag, size_t *preffrag); diff --git a/ssl/record/methods/ssl3_meth.c b/ssl/record/methods/ssl3_meth.c index e48ca5bc70..23a27ee889 100644 --- a/ssl/record/methods/ssl3_meth.c +++ b/ssl/record/methods/ssl3_meth.c @@ -310,5 +310,8 @@ struct record_functions_st ssl_3_0_funcs = { tls_default_validate_record_header, tls_default_post_process_record, tls_get_max_records_default, - tls_write_records_default + tls_write_records_default, + /* These 2 functions are defined in tls1_meth.c */ + tls1_allocate_write_buffers, + tls1_initialise_write_packets }; diff --git a/ssl/record/methods/tls13_meth.c b/ssl/record/methods/tls13_meth.c index aa01d2f758..e720347bc5 100644 --- a/ssl/record/methods/tls13_meth.c +++ b/ssl/record/methods/tls13_meth.c @@ -249,5 +249,7 @@ struct record_functions_st tls_1_3_funcs = { tls13_validate_record_header, tls13_post_process_record, tls_get_max_records_default, - tls_write_records_default + tls_write_records_default, + tls_allocate_write_buffers_default, + tls_initialise_write_packets_default }; diff --git a/ssl/record/methods/tls1_meth.c b/ssl/record/methods/tls1_meth.c index a2612e8986..6887d756af 100644 --- a/ssl/record/methods/tls1_meth.c +++ b/ssl/record/methods/tls1_meth.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "../../ssl_local.h" #include "../record_local.h" #include "recmethod_local.h" @@ -542,6 +543,104 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, return ret; } +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 +# ifndef OPENSSL_NO_COMP +# define MAX_PREFIX_LEN ((SSL3_ALIGN_PAYLOAD - 1) \ + + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + + SSL3_RT_HEADER_LENGTH \ + + SSL3_RT_MAX_COMPRESSED_OVERHEAD) +# else +# define MAX_PREFIX_LEN ((SSL3_ALIGN_PAYLOAD - 1) \ + + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + + SSL3_RT_HEADER_LENGTH) +# endif /* OPENSSL_NO_COMP */ +#else +# ifndef OPENSSL_NO_COMP +# define MAX_PREFIX_LEN (SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + + SSL3_RT_HEADER_LENGTH \ + + SSL3_RT_MAX_COMPRESSED_OVERHEAD) +# else +# define MAX_PREFIX_LEN (SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + + SSL3_RT_HEADER_LENGTH) +# endif /* OPENSSL_NO_COMP */ +#endif + +/* This function is also used by the SSLv3 implementation */ +int tls1_allocate_write_buffers(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, size_t *prefix) +{ + /* Do we need to add an empty record prefix? */ + *prefix = rl->need_empty_fragments + && templates[0].type == SSL3_RT_APPLICATION_DATA; + + /* + * In the prefix case we can allocate a much smaller buffer. Otherwise we + * just allocate the default buffer size + */ + if (!tls_setup_write_buffer(rl, numtempl + *prefix, + *prefix ? MAX_PREFIX_LEN : 0, 0)) { + /* RLAYERfatal() already called */ + return 0; + } + + return 1; +} + +/* This function is also used by the SSLv3 implementation */ +int tls1_initialise_write_packets(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, + OSSL_RECORD_TEMPLATE *prefixtempl, + WPACKET *pkt, + SSL3_BUFFER *bufs, + size_t *wpinited) +{ + size_t align = 0; + SSL3_BUFFER *wb; + size_t prefix; + + /* Do we need to add an empty record prefix? */ + prefix = rl->need_empty_fragments + && templates[0].type == SSL3_RT_APPLICATION_DATA; + + if (prefix) { + /* + * countermeasure against known-IV weakness in CBC ciphersuites (see + * http://www.openssl.org/~bodo/tls-cbc.txt) + */ + prefixtempl->buf = NULL; + prefixtempl->version = templates[0].version; + prefixtempl->buflen = 0; + prefixtempl->type = SSL3_RT_APPLICATION_DATA; + + wb = &bufs[0]; + +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 + align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 + - ((align - 1) % SSL3_ALIGN_PAYLOAD); +#endif + SSL3_BUFFER_set_offset(wb, align); + + if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb), + SSL3_BUFFER_get_len(wb), 0)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + *wpinited = 1; + if (!WPACKET_allocate_bytes(&pkt[0], align, NULL)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return tls_initialise_write_packets_default(rl, templates, numtempl, + NULL, + pkt + prefix, bufs + prefix, + wpinited); +} + /* TLSv1.0, TLSv1.1 and TLSv1.2 all use the same funcs */ struct record_functions_st tls_1_funcs = { tls1_set_crypto_state, @@ -553,7 +652,9 @@ struct record_functions_st tls_1_funcs = { tls_default_validate_record_header, tls_default_post_process_record, tls_get_max_records_multiblock, - tls_write_records_multiblock /* Defined in tls_multib.c */ + tls_write_records_multiblock, /* Defined in tls_multib.c */ + tls1_allocate_write_buffers, + tls1_initialise_write_packets }; struct record_functions_st dtls_1_funcs = { @@ -566,5 +667,7 @@ struct record_functions_st dtls_1_funcs = { NULL, NULL, NULL, + NULL, + NULL, NULL }; diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c index 50132d7771..4a1a8d13b2 100644 --- a/ssl/record/methods/tls_common.c +++ b/ssl/record/methods/tls_common.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "internal/e_os.h" #include "internal/packet.h" #include "../../ssl_local.h" @@ -115,28 +116,6 @@ static void tls_release_write_buffer_int(OSSL_RECORD_LAYER *rl, size_t start) } } -#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 -# ifndef OPENSSL_NO_COMP -# define MAX_PREFIX_LEN ((SSL3_ALIGN_PAYLOAD - 1) \ - + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ - + SSL3_RT_HEADER_LENGTH \ - + SSL3_RT_MAX_COMPRESSED_OVERHEAD) -# else -# define MAX_PREFIX_LEN ((SSL3_ALIGN_PAYLOAD - 1) \ - + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ - + SSL3_RT_HEADER_LENGTH) -# endif /* OPENSSL_NO_COMP */ -#else -# ifndef OPENSSL_NO_COMP -# define MAX_PREFIX_LEN (SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ - + SSL3_RT_HEADER_LENGTH \ - + SSL3_RT_MAX_COMPRESSED_OVERHEAD) -# else -# define MAX_PREFIX_LEN (SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ - + SSL3_RT_HEADER_LENGTH) -# endif /* OPENSSL_NO_COMP */ -#endif - int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes, size_t firstlen, size_t nextlen) { @@ -1479,7 +1458,7 @@ size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, int type, size_t len, * it, then return the preferred number of pipelines. */ if (rl->max_pipelines > 0 - && rl->enc_ctx!= NULL + && rl->enc_ctx != NULL && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(rl->enc_ctx)) & EVP_CIPH_FLAG_PIPELINE) != 0 && RLAYER_USE_EXPLICIT_IV(rl)) { @@ -1501,6 +1480,59 @@ size_t tls_get_max_records(OSSL_RECORD_LAYER *rl, int type, size_t len, return rl->funcs->get_max_records(rl, type, len, maxfrag, preffrag); } +int tls_allocate_write_buffers_default(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, + size_t *prefix) +{ + if (!tls_setup_write_buffer(rl, numtempl, 0, 0)) { + /* RLAYERfatal() already called */ + return 0; + } + + return 1; +} + +int tls_initialise_write_packets_default(OSSL_RECORD_LAYER *rl, + OSSL_RECORD_TEMPLATE *templates, + size_t numtempl, + OSSL_RECORD_TEMPLATE *prefixtempl, + WPACKET *pkt, + SSL3_BUFFER *bufs, + size_t *wpinited) +{ + WPACKET *thispkt; + size_t j, align; + SSL3_BUFFER *wb; + + for (j = 0; j < numtempl; j++) { + thispkt = &pkt[j]; + wb = &bufs[j]; + + wb->type = templates[j].type; + +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 + align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 + - ((align - 1) % SSL3_ALIGN_PAYLOAD); +#endif + SSL3_BUFFER_set_offset(wb, align); + + if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb), + SSL3_BUFFER_get_len(wb), 0)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + (*wpinited)++; + if (!WPACKET_allocate_bytes(thispkt, align, NULL)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} + int tls_write_records_default(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates, size_t numtempl) @@ -1511,15 +1543,12 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl, SSL3_RECORD *thiswr; unsigned char *recordstart; int mac_size = 0, ret = 0; - size_t align = 0; - SSL3_BUFFER *wb; size_t len, wpinited = 0; size_t j, prefix = 0; int using_ktls; OSSL_RECORD_TEMPLATE prefixtempl; OSSL_RECORD_TEMPLATE *thistempl; - if (rl->md_ctx != NULL && EVP_MD_CTX_get0_md(rl->md_ctx) != NULL) { mac_size = EVP_MD_CTX_get_size(rl->md_ctx); if (mac_size < 0) { @@ -1528,16 +1557,14 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl, } } - /* Do we need to add an empty record prefix? */ - prefix = rl->need_empty_fragments - && templates[0].type == SSL3_RT_APPLICATION_DATA; + if (!rl->funcs->allocate_write_buffers(rl, templates, numtempl, &prefix)) { + /* RLAYERfatal() already called */ + goto err; + } - /* - * In the prefix case we can allocate a much smaller buffer. Otherwise we - * just allocate the default buffer size - */ - if (!tls_setup_write_buffer(rl, numtempl + prefix, - prefix ? MAX_PREFIX_LEN : 0, 0)) { + if (!rl->funcs->initialise_write_packets(rl, templates, numtempl, + &prefixtempl, pkt, rl->wbuf, + &wpinited)) { /* RLAYERfatal() already called */ goto err; } @@ -1548,65 +1575,6 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl, goto err; } - if (prefix) { - /* - * countermeasure against known-IV weakness in CBC ciphersuites (see - * http://www.openssl.org/~bodo/tls-cbc.txt) - */ - prefixtempl.buf = NULL; - prefixtempl.version = templates[0].version; - prefixtempl.buflen = 0; - prefixtempl.type = SSL3_RT_APPLICATION_DATA; - wpinited = 1; - - wb = &rl->wbuf[0]; -#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 - align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH; - align = SSL3_ALIGN_PAYLOAD - 1 - - ((align - 1) % SSL3_ALIGN_PAYLOAD); -#endif - SSL3_BUFFER_set_offset(wb, align); - if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb), - SSL3_BUFFER_get_len(wb), 0) - || !WPACKET_allocate_bytes(&pkt[0], align, NULL)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; - } - wpinited = 1; - } - for (j = 0; j < numtempl; j++) { - thispkt = &pkt[prefix + j]; - - wb = &rl->wbuf[prefix + j]; - wb->type = templates[j].type; - - if (using_ktls) { - /* - * ktls doesn't modify the buffer, but to avoid a warning we need - * to discard the const qualifier. - * This doesn't leak memory because the buffers have been - * released when switching to ktls. - */ - SSL3_BUFFER_set_buf(wb, (unsigned char *)templates[j].buf); - SSL3_BUFFER_set_offset(wb, 0); - SSL3_BUFFER_set_app_buffer(wb, 1); - } else { -#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 - align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH; - align = SSL3_ALIGN_PAYLOAD - 1 - - ((align - 1) % SSL3_ALIGN_PAYLOAD); -#endif - SSL3_BUFFER_set_offset(wb, align); - if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb), - SSL3_BUFFER_get_len(wb), 0) - || !WPACKET_allocate_bytes(thispkt, align, NULL)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - goto err; - } - wpinited++; - } - } - /* Clear our SSL3_RECORD structures */ memset(wr, 0, sizeof(wr)); for (j = 0; j < numtempl + prefix; j++) { @@ -1616,8 +1584,7 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl, thispkt = &pkt[j]; thiswr = &wr[j]; - thistempl = (j == 0 && prefix == 1) ? &prefixtempl : - &templates[j - prefix]; + thistempl = (j < prefix) ? &prefixtempl : &templates[j - prefix]; /* * In TLSv1.3, once encrypting, we always use application data for the @@ -1796,13 +1763,12 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl, } } - for (j = 0; j < prefix + numtempl; j++) { + for (j = 0; j < numtempl + prefix; j++) { size_t origlen; thispkt = &pkt[j]; thiswr = &wr[j]; - thistempl = (prefix == 1 && j == 0) ? &prefixtempl - : &templates[j - prefix]; + thistempl = (j < prefix) ? &prefixtempl : &templates[j - prefix]; if (using_ktls) goto mac_done; diff --git a/ssl/record/methods/tlsany_meth.c b/ssl/record/methods/tlsany_meth.c index 141354b435..499a70cb3a 100644 --- a/ssl/record/methods/tlsany_meth.c +++ b/ssl/record/methods/tlsany_meth.c @@ -144,7 +144,9 @@ struct record_functions_st tls_any_funcs = { tls_validate_record_header, tls_default_post_process_record, tls_get_max_records_default, - tls_write_records_default + tls_write_records_default, + tls_allocate_write_buffers_default, + tls_initialise_write_packets_default }; static int dtls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers) @@ -166,5 +168,7 @@ struct record_functions_st dtls_any_funcs = { NULL, NULL, NULL, + NULL, + NULL, NULL };