From a937806043bda5775091844050e8c632a41922ac Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Tue, 5 Jul 2022 20:39:06 +0200
Subject: [PATCH] Fix a memory leak in tls13_generate_secret

This was found by my Reproducible Error Injection patch (#18356)

Due to the exact location of the injected memory
error the sha256 digest is missing, and this causes much later
the memory leak (and a failed assertion) in tls13_generate_secret.

But the reproduction is a bit challenging, as it requires AESNI
and RDRAND capability.

OPENSSL_ia32cap=0x4200000000000000 ERROR_INJECT=1657070330 ../util/shlib_wrap.sh ./client-test ./corpora/client/791afc153e17db072175eeef85385a38d7f6d194
    #0 0x7fceaffb7d4f in __sanitizer_print_stack_trace ../../../../src/libsanitizer/asan/asan_stack.cc:36
    #1 0x55fb9117f934 in my_malloc fuzz/test-corpus.c:114
    #2 0x7fceafa147f3 in OPENSSL_LH_insert crypto/lhash/lhash.c:109
    #3 0x7fceafa42639 in lh_OBJ_NAME_insert crypto/objects/obj_local.h:12
    #4 0x7fceafa42639 in OBJ_NAME_add crypto/objects/o_names.c:236
    #5 0x7fceaf9f7baa in EVP_add_digest crypto/evp/names.c:39
    #6 0x7fceaf9c6b97 in openssl_add_all_digests_int crypto/evp/c_alld.c:39
    #7 0x7fceafa0f8ec in ossl_init_add_all_digests crypto/init.c:275
    #8 0x7fceafa0f8ec in ossl_init_add_all_digests_ossl_ crypto/init.c:264
    #9 0x7fceaf69b4de in __pthread_once_slow /build/glibc-SzIz7B/glibc-2.31/nptl/pthread_once.c:116
    #10 0x7fceafafb27c in CRYPTO_THREAD_run_once crypto/threads_pthread.c:118
    #11 0x7fceafa1000e in OPENSSL_init_crypto crypto/init.c:677
    #12 0x7fceafa1000e in OPENSSL_init_crypto crypto/init.c:611
    #13 0x7fceafdad3e8 in OPENSSL_init_ssl ssl/ssl_init.c:190
    #14 0x55fb9117ee0f in FuzzerInitialize fuzz/client.c:46
    #15 0x55fb9117e939 in main fuzz/test-corpus.c:194
    #16 0x7fceaf4bc082 in __libc_start_main ../csu/libc-start.c:308
    #17 0x55fb9117ec7d in _start (.../openssl/fuzz/client-test+0x2c7d)

    #0 0x7fceaffb7d4f in __sanitizer_print_stack_trace ../../../../src/libsanitizer/asan/asan_stack.cc:36
    #1 0x55fb9117f934 in my_malloc fuzz/test-corpus.c:114
    #2 0x7fceafa147f3 in OPENSSL_LH_insert crypto/lhash/lhash.c:109
    #3 0x7fceafa42639 in lh_OBJ_NAME_insert crypto/objects/obj_local.h:12
    #4 0x7fceafa42639 in OBJ_NAME_add crypto/objects/o_names.c:236
    #5 0x7fceaf9f7baa in EVP_add_digest crypto/evp/names.c:39
    #6 0x7fceafdad328 in ossl_init_ssl_base ssl/ssl_init.c:87
    #7 0x7fceafdad328 in ossl_init_ssl_base_ossl_ ssl/ssl_init.c:24
    #8 0x7fceaf69b4de in __pthread_once_slow /build/glibc-SzIz7B/glibc-2.31/nptl/pthread_once.c:116
    #9 0x7fceafafb27c in CRYPTO_THREAD_run_once crypto/threads_pthread.c:118
    #10 0x7fceafdad412 in OPENSSL_init_ssl ssl/ssl_init.c:193
    #11 0x55fb9117ee0f in FuzzerInitialize fuzz/client.c:46
    #12 0x55fb9117e939 in main fuzz/test-corpus.c:194
    #13 0x7fceaf4bc082 in __libc_start_main ../csu/libc-start.c:308
    #14 0x55fb9117ec7d in _start (.../openssl/fuzz/client-test+0x2c7d)

=================================================================
==1320996==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 80 byte(s) in 1 object(s) allocated from:
    #0 0x7fceaffaa808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x7fceafa19425 in CRYPTO_zalloc crypto/mem.c:230
    #2 0x7fceafa03a85 in int_ctx_new crypto/evp/pmeth_lib.c:144
    #3 0x7fceafa03a85 in EVP_PKEY_CTX_new_id crypto/evp/pmeth_lib.c:250
    #4 0x7fceafe38de5 in tls13_generate_secret ssl/tls13_enc.c:174
    #5 0x7fceafd9537f in ssl_derive ssl/s3_lib.c:4833
    #6 0x7fceafdde91c in tls_parse_stoc_key_share ssl/statem/extensions_clnt.c:1902
    #7 0x7fceafdd4ac1 in tls_parse_all_extensions ssl/statem/extensions.c:752
    #8 0x7fceafdf8079 in tls_process_server_hello ssl/statem/statem_clnt.c:1698
    #9 0x7fceafe01f87 in ossl_statem_client_process_message ssl/statem/statem_clnt.c:1034
    #10 0x7fceafdeec0d in read_state_machine ssl/statem/statem.c:636
    #11 0x7fceafdeec0d in state_machine ssl/statem/statem.c:434
    #12 0x7fceafdb88d7 in SSL_do_handshake ssl/ssl_lib.c:3718
    #13 0x55fb9117f07c in FuzzerTestOneInput fuzz/client.c:98
    #14 0x55fb9117f463 in testfile fuzz/test-corpus.c:182
    #15 0x55fb9117eb92 in main fuzz/test-corpus.c:226
    #16 0x7fceaf4bc082 in __libc_start_main ../csu/libc-start.c:308

Indirect leak of 1080 byte(s) in 1 object(s) allocated from:
    #0 0x7fceaffaa808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x7fceafa19425 in CRYPTO_zalloc crypto/mem.c:230
    #2 0x7fceafa11555 in pkey_hkdf_init crypto/kdf/hkdf.c:51
    #3 0x7fceafa03b36 in int_ctx_new crypto/evp/pmeth_lib.c:160
    #4 0x7fceafa03b36 in EVP_PKEY_CTX_new_id crypto/evp/pmeth_lib.c:250
    #5 0x7fceafe38de5 in tls13_generate_secret ssl/tls13_enc.c:174
    #6 0x7fceafd9537f in ssl_derive ssl/s3_lib.c:4833
    #7 0x7fceafdde91c in tls_parse_stoc_key_share ssl/statem/extensions_clnt.c:1902
    #8 0x7fceafdd4ac1 in tls_parse_all_extensions ssl/statem/extensions.c:752
    #9 0x7fceafdf8079 in tls_process_server_hello ssl/statem/statem_clnt.c:1698
    #10 0x7fceafe01f87 in ossl_statem_client_process_message ssl/statem/statem_clnt.c:1034
    #11 0x7fceafdeec0d in read_state_machine ssl/statem/statem.c:636
    #12 0x7fceafdeec0d in state_machine ssl/statem/statem.c:434
    #13 0x7fceafdb88d7 in SSL_do_handshake ssl/ssl_lib.c:3718
    #14 0x55fb9117f07c in FuzzerTestOneInput fuzz/client.c:98
    #15 0x55fb9117f463 in testfile fuzz/test-corpus.c:182
    #16 0x55fb9117eb92 in main fuzz/test-corpus.c:226
    #17 0x7fceaf4bc082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: 1160 byte(s) leaked in 2 allocation(s).

Reviewed-by: Todd Short <todd.short@me.com>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18725)
---
 ssl/tls13_enc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index b8fb07f210..51ca1050a4 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -190,6 +190,7 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
     if (!ossl_assert(mdleni >= 0)) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
                  ERR_R_INTERNAL_ERROR);
+        EVP_PKEY_CTX_free(pctx);
         return 0;
     }
     mdlen = (size_t)mdleni;
-- 
2.17.1

