From: Matt Caswell Date: Fri, 18 Nov 2022 11:39:33 +0000 (+0000) Subject: Add support for the msg_callback X-Git-Tag: openssl-3.2.0-alpha1~1389 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=1d57dbac190ac6082de7865ed9205cd1f41bfd97 Add support for the msg_callback Having support for the msg_callback will improve debug capabilities. For record headers we "manufacture" dummy ones so that as far as the callback is concerned we are doing "normal" TLS. Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/19748) --- diff --git a/ssl/quic/quic_tls.c b/ssl/quic/quic_tls.c index 4a2d5bb043..d7e3dd4acd 100644 --- a/ssl/quic/quic_tls.c +++ b/ssl/quic/quic_tls.c @@ -40,6 +40,10 @@ struct quic_tls_st { struct ossl_record_layer_st { QUIC_TLS *qtls; + + /* Protection level */ + int level; + /* Only used for retry flags */ BIO *dummybio; @@ -62,6 +66,10 @@ struct ossl_record_layer_st { /* Set if recbuf is populated with data */ unsigned int recread : 1; + + /* Callbacks */ + OSSL_FUNC_rlayer_msg_callback_fn *msg_callback; + void *cbarg; }; static int @@ -90,9 +98,25 @@ quic_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, } rl->qtls = (QUIC_TLS *)rlarg; + rl->level = level; rl->dummybio = transport; + rl->cbarg = cbarg; *retrl = rl; + if (fns != NULL) { + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + break; + case OSSL_FUNC_RLAYER_MSG_CALLBACK: + rl->msg_callback = OSSL_FUNC_rlayer_msg_callback(fns); + break; + default: + /* Just ignore anything we don't understand */ + break; + } + } + } + switch (level) { case OSSL_RECORD_PROTECTION_LEVEL_NONE: return 1; @@ -209,6 +233,36 @@ static int quic_write_records(OSSL_RECORD_LAYER *rl, BIO_clear_retry_flags(rl->dummybio); + if (rl->msg_callback != NULL) { + unsigned char dummyrec[SSL3_RT_HEADER_LENGTH]; + + /* + * For the purposes of the callback we "pretend" to be normal TLS, + * and manufacture a dummy record header + */ + dummyrec[0] = (rl->level == OSSL_RECORD_PROTECTION_LEVEL_NONE) + ? template->type + : SSL3_RT_APPLICATION_DATA; + dummyrec[1] = (unsigned char)((template->version >> 8) & 0xff); + dummyrec[2] = (unsigned char)(template->version & 0xff); + /* + * We assume that buflen is always <= UINT16_MAX. Since this is + * generated by libssl itself we actually expect it to never + * exceed SSL3_RT_MAX_PLAIN_LENGTH - so it should be a safe + * assumption + */ + dummyrec[3] = (unsigned char)((template->buflen >> 8) & 0xff); + dummyrec[4] = (unsigned char)(template->buflen & 0xff); + + rl->msg_callback(1, TLS1_3_VERSION, SSL3_RT_HEADER, dummyrec, + SSL3_RT_HEADER_LENGTH, rl->cbarg); + + if (rl->level != OSSL_RECORD_PROTECTION_LEVEL_NONE) { + rl->msg_callback(1, TLS1_3_VERSION, SSL3_RT_INNER_CONTENT_TYPE, + &template->type, 1, rl->cbarg); + } + } + switch (template->type) { case SSL3_RT_ALERT: if (template->buflen != 2) { @@ -315,6 +369,31 @@ static int quic_read_record(OSSL_RECORD_LAYER *rl, void **rechandle, rl->recread = 1; /* epoch/seq_num are not relevant for TLS */ + if (rl->msg_callback != NULL) { + unsigned char dummyrec[SSL3_RT_HEADER_LENGTH]; + + /* + * For the purposes of the callback we "pretend" to be normal TLS, + * and manufacture a dummy record header + */ + dummyrec[0] = (rl->level == OSSL_RECORD_PROTECTION_LEVEL_NONE) + ? SSL3_RT_HANDSHAKE + : SSL3_RT_APPLICATION_DATA; + dummyrec[1] = (unsigned char)((TLS1_2_VERSION >> 8) & 0xff); + dummyrec[2] = (unsigned char)(TLS1_2_VERSION & 0xff); + /* + * *datalen will always fit into 2 bytes because our original buffer + * size is less than that. + */ + dummyrec[3] = (unsigned char)((*datalen >> 8) & 0xff); + dummyrec[4] = (unsigned char)(*datalen & 0xff); + + rl->msg_callback(0, TLS1_3_VERSION, SSL3_RT_HEADER, dummyrec, + SSL3_RT_HEADER_LENGTH, rl->cbarg); + rl->msg_callback(0, TLS1_3_VERSION, SSL3_RT_INNER_CONTENT_TYPE, type, 1, + rl->cbarg); + } + return OSSL_RECORD_RETURN_SUCCESS; }