From b06746d3474ea0eda57419d3e99113443401e884 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 13 Sep 2023 09:25:25 +0900 Subject: [PATCH 01/13] [minicrypto] x25519 key derivation must fail when output is all-zero --- lib/cifra/x25519.c | 11 ++++++++++- t/picotls.c | 6 ++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/cifra/x25519.c b/lib/cifra/x25519.c index 58f464f8c..9e7d60153 100644 --- a/lib/cifra/x25519.c +++ b/lib/cifra/x25519.c @@ -45,6 +45,13 @@ static int x25519_derive_secret(ptls_iovec_t *secret, const uint8_t *clientpriv, return PTLS_ERROR_NO_MEMORY; cf_curve25519_mul(secret->base, clientpriv != NULL ? clientpriv : serverpriv, clientpriv != NULL ? serverpub : clientpub); + + static const uint8_t zeros[X25519_KEY_SIZE] = {}; + if (ptls_mem_equal(secret->base, zeros, sizeof(zeros))) { + free(secret->base); + return PTLS_ERROR_INCOMPATIBLE_KEY; + } + secret->len = X25519_KEY_SIZE; return 0; } @@ -111,8 +118,10 @@ static int x25519_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t Exit: ptls_clear_memory(priv, sizeof(priv)); - if (pub != NULL && ret != 0) + if (pub != NULL && ret != 0) { ptls_clear_memory(pub, X25519_KEY_SIZE); + free(pub); + } return ret; } diff --git a/t/picotls.c b/t/picotls.c index ecca51d3c..937f73cd6 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -2188,4 +2188,10 @@ void test_key_exchange(ptls_key_exchange_algorithm_t *client, ptls_key_exchange_ ret = ctx->on_exchange(&ctx, 1, NULL, ptls_iovec_init(NULL, 0)); ok(ret == 0); ok(ctx == NULL); + + /* test derivation failure. In case of X25519, the outcome is derived key becoming all-zero and rejected. In case of others, it + * is most likely that the provided key would be rejected. */ + static uint8_t zeros[32] = {}; + ret = server->exchange(server, &server_pubkey, &server_secret, ptls_iovec_init(zeros, sizeof(zeros))); + ok(ret != 0); } From 32b9845b369aeac6c9442bf18bbc7e871fd2f45d Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 13 Sep 2023 09:52:20 +0900 Subject: [PATCH 02/13] msvc compatibility --- lib/cifra/x25519.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cifra/x25519.c b/lib/cifra/x25519.c index 9e7d60153..3697d4ddf 100644 --- a/lib/cifra/x25519.c +++ b/lib/cifra/x25519.c @@ -46,7 +46,7 @@ static int x25519_derive_secret(ptls_iovec_t *secret, const uint8_t *clientpriv, cf_curve25519_mul(secret->base, clientpriv != NULL ? clientpriv : serverpriv, clientpriv != NULL ? serverpub : clientpub); - static const uint8_t zeros[X25519_KEY_SIZE] = {}; + static const uint8_t zeros[X25519_KEY_SIZE] = {0}; if (ptls_mem_equal(secret->base, zeros, sizeof(zeros))) { free(secret->base); return PTLS_ERROR_INCOMPATIBLE_KEY; From 871f5077bdac2679924892694e4ae89fe9433ae2 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 13 Sep 2023 10:08:12 +0900 Subject: [PATCH 03/13] here also --- t/picotls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/picotls.c b/t/picotls.c index 937f73cd6..9c970a263 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -2191,7 +2191,7 @@ void test_key_exchange(ptls_key_exchange_algorithm_t *client, ptls_key_exchange_ /* test derivation failure. In case of X25519, the outcome is derived key becoming all-zero and rejected. In case of others, it * is most likely that the provided key would be rejected. */ - static uint8_t zeros[32] = {}; + static uint8_t zeros[32] = {0}; ret = server->exchange(server, &server_pubkey, &server_secret, ptls_iovec_init(zeros, sizeof(zeros))); ok(ret != 0); } From b55b56a419787f4cabe5127307330fe623ffb6b4 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 14 Sep 2023 14:53:23 +0900 Subject: [PATCH 04/13] [boringssl] check x25519 bad key --- lib/openssl.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/openssl.c b/lib/openssl.c index b03533909..963d21237 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -526,18 +526,29 @@ static int evp_keyex_on_exchange(ptls_key_exchange_context_t **_ctx, int release #ifdef OPENSSL_IS_BORINGSSL if (ctx->super.algo->id == PTLS_GROUP_X25519) { - secret->len = peerkey.len; - if ((secret->base = malloc(secret->len)) == NULL) { + /* allocate memory to return secret */ + static const size_t SECRET_SIZE = 32; + if ((secret->base = malloc(SECRET_SIZE)) == NULL) { ret = PTLS_ERROR_NO_MEMORY; goto Exit; } + secret->len = SECRET_SIZE; + /* fetch raw key and derive the secret */ uint8_t sk_raw[32]; size_t sk_raw_len = sizeof(sk_raw); if (EVP_PKEY_get_raw_private_key(ctx->privkey, sk_raw, &sk_raw_len) != 1) { ret = PTLS_ERROR_LIBRARY; goto Exit; } + assert(sk_raw_len == sizeof(sk_raw)); X25519(secret->base, sk_raw, peerkey.base); + /* check bad key */ + static const uint8_t zeros[SECRET_SIZE] = {0}; + if (ptls_mem_equal(secret->base, zeros, SECRET_SIZE)) { + ret = PTLS_ERROR_INCOMPATIBLE_KEY; + goto Exit; + } + /* success */ ret = 0; goto Exit; } From b9104e7ee70e6f8db276dad76769407475a977b3 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 14 Sep 2023 14:54:16 +0900 Subject: [PATCH 05/13] clear secret --- lib/openssl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/openssl.c b/lib/openssl.c index 963d21237..2b88a8449 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -542,6 +542,7 @@ static int evp_keyex_on_exchange(ptls_key_exchange_context_t **_ctx, int release } assert(sk_raw_len == sizeof(sk_raw)); X25519(secret->base, sk_raw, peerkey.base); + ptls_clear_memory(sk_raw, sizeof(sk_raw)); /* check bad key */ static const uint8_t zeros[SECRET_SIZE] = {0}; if (ptls_mem_equal(secret->base, zeros, SECRET_SIZE)) { From 8fa15dc5a9beab038baeca2f09ad81e2db54c94e Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 14 Sep 2023 15:00:48 +0900 Subject: [PATCH 06/13] use macro to avoid compile errors --- lib/openssl.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/openssl.c b/lib/openssl.c index 2b88a8449..294fb6019 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -525,16 +525,16 @@ static int evp_keyex_on_exchange(ptls_key_exchange_context_t **_ctx, int release } #ifdef OPENSSL_IS_BORINGSSL +#define X25519_KEY_SIZE 32 if (ctx->super.algo->id == PTLS_GROUP_X25519) { /* allocate memory to return secret */ - static const size_t SECRET_SIZE = 32; - if ((secret->base = malloc(SECRET_SIZE)) == NULL) { + if ((secret->base = malloc(X25519_KEY_SIZE)) == NULL) { ret = PTLS_ERROR_NO_MEMORY; goto Exit; } - secret->len = SECRET_SIZE; + secret->len = X25519_KEY_SIZE; /* fetch raw key and derive the secret */ - uint8_t sk_raw[32]; + uint8_t sk_raw[X25519_KEY_SIZE]; size_t sk_raw_len = sizeof(sk_raw); if (EVP_PKEY_get_raw_private_key(ctx->privkey, sk_raw, &sk_raw_len) != 1) { ret = PTLS_ERROR_LIBRARY; @@ -544,8 +544,8 @@ static int evp_keyex_on_exchange(ptls_key_exchange_context_t **_ctx, int release X25519(secret->base, sk_raw, peerkey.base); ptls_clear_memory(sk_raw, sizeof(sk_raw)); /* check bad key */ - static const uint8_t zeros[SECRET_SIZE] = {0}; - if (ptls_mem_equal(secret->base, zeros, SECRET_SIZE)) { + static const uint8_t zeros[X25519_KEY_SIZE] = {0}; + if (ptls_mem_equal(secret->base, zeros, X25519_KEY_SIZE)) { ret = PTLS_ERROR_INCOMPATIBLE_KEY; goto Exit; } @@ -553,6 +553,7 @@ static int evp_keyex_on_exchange(ptls_key_exchange_context_t **_ctx, int release ret = 0; goto Exit; } +#undef X25519_KEY_SIZE #endif if ((evppeer = EVP_PKEY_new()) == NULL) { From d462d0c045bd3b4b50cb8a42861dfc3597c3d974 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 17 Oct 2023 13:53:52 +0900 Subject: [PATCH 07/13] [evp_keyex_init] keep refcount unchanged when the function fails --- lib/openssl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/openssl.c b/lib/openssl.c index 294fb6019..a6abafe51 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -608,6 +608,9 @@ static int evp_keyex_on_exchange(ptls_key_exchange_context_t **_ctx, int release return ret; } +/** + * Upon success, ownership of `pkey` is transferred to the object being created. Otherwise, the refcount remains unchanged. + */ static int evp_keyex_init(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **_ctx, EVP_PKEY *pkey) { struct st_evp_keyex_context_t *ctx = NULL; @@ -630,8 +633,10 @@ static int evp_keyex_init(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange *_ctx = &ctx->super; ret = 0; Exit: - if (ret != 0 && ctx != NULL) + if (ret != 0 && ctx != NULL) { + ctx->privkey = NULL; /* do not decrement refcount of pkey in case of error */ evp_keyex_free(ctx); + } return ret; } From 348e8a9c3479b47674a8fa8a987d9fccfca6a04a Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 20 Oct 2023 06:32:50 +0900 Subject: [PATCH 08/13] add the failing case --- t/picotls.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/t/picotls.c b/t/picotls.c index 9c970a263..36ac6049f 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -2026,6 +2026,13 @@ static void test_legacy_ch(void) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x32, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x13, 0x00, 0x09, 0x00, 0x15, 0x00, 0x12, 0x00, 0x03, 0x00, 0x08, 0x00, 0x14, 0x00, 0x11, 0x00, 0xff, 0x01, 0x00}; + static const uint8_t tls12_no_exts[] = { + 0x16, 0x03, 0x01, 0x00, 0x67, 0x01, 0x00, 0x00, 0x63, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xee, 0x8a, 0x29, 0xdd, 0xcf, 0x6d, 0x64, 0xfd, 0xd0, 0xcd, + 0xa0, 0x9b, 0xc1, 0x32, 0x46, 0xbf, 0x53, 0xda, 0x29, 0x23, 0x81, 0x5f, 0x54, 0x1f, 0xbd, 0xe0, 0x8e, 0x97, + 0x17, 0x5b, 0x03, 0x5d, 0x00, 0x1c, 0x00, 0xff, 0x00, 0x9c, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x0a, 0xc0, 0x09, + 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x9e, 0x00, 0x33, 0x00, 0x39, 0x00, 0x0a, 0x01, 0x00}; /* client hello generated by openssl 1.0.0s; s_client -bugs -no_ticket -cipher DES-CBC-SHA -connect */ static const uint8_t tls10_with_exts[] = {0x16, 0x03, 0x01, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x2b, 0x03, 0x01, 0x63, 0xfc, 0x5a, 0x16, 0xde, 0x7a, 0xfc, 0xc1, 0x0c, 0x54, 0x12, 0xa6, 0xd3, 0x8c, 0xcf, @@ -2087,6 +2094,12 @@ static void test_legacy_ch(void) free(legacy_params); legacy_params = NULL; + tls = ptls_new(ctx, 1); + len = sizeof(tls12_no_exts); + ret = ptls_handshake(tls, &sendbuf, tls12_no_exts, &len, NULL); + ptls_free(tls); + ok(ret == PTLS_ALERT_PROTOCOL_VERSION); + tls = ptls_new(ctx, 1); len = sizeof(tls10_with_exts); ret = ptls_handshake(tls, &sendbuf, tls10_with_exts, &len, NULL); From ba9bba4780b47423781a46e3cd34862a67760502 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 20 Oct 2023 06:34:20 +0900 Subject: [PATCH 09/13] extensions block is optional in TLS/1.2 also --- lib/picotls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index d03bf408a..34588cd16 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -3570,10 +3570,10 @@ static int decode_client_hello(ptls_context_t *ctx, struct st_ptls_client_hello_ src = end; }); - /* CH defined in TLS versions below 1.2 might not have extensions (or they might, see what OpenSSL 1.0.0 sends); so bail out - * after parsing the main variables. Zero is returned as it is a valid ClientHello. However `ptls_t::selected_version` remains - * zero indicating that no compatible version were found. */ - if (ch->legacy_version < 0x0303 && src == end) { + /* In TLS versions 1.2 and earlier CH might not have an extensions block (or they might, see what OpenSSL 1.0.0 sends); so bail + * out if that is the case after parsing the main variables. Zero is returned as it is a valid ClientHello. However + * `ptls_t::selected_version` remains zero indicating that no compatible version were found. */ + if (src == end) { ret = 0; goto Exit; } From 1a18e83417838860347315c21dbf8fce41b204c7 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 20 Oct 2023 06:39:25 +0900 Subject: [PATCH 10/13] even though we do not test what is recorded, clear it otherwise tests that follow fail --- t/picotls.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/t/picotls.c b/t/picotls.c index 36ac6049f..c1b6783b4 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -2099,6 +2099,8 @@ static void test_legacy_ch(void) ret = ptls_handshake(tls, &sendbuf, tls12_no_exts, &len, NULL); ptls_free(tls); ok(ret == PTLS_ALERT_PROTOCOL_VERSION); + free(legacy_params); + legacy_params = NULL; tls = ptls_new(ctx, 1); len = sizeof(tls10_with_exts); From 7c9c82bd6d41789fbaa3af2696fdcc0939e32096 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 30 Oct 2023 16:20:50 +0900 Subject: [PATCH 11/13] [fusion] unify detection scheme to the best one that we have (which we have had in h2o) --- CMakeLists.txt | 12 +++--------- cmake/fusion.cmake | 29 +++++++++++++++++++++++++++++ picotls.xcodeproj/project.pbxproj | 2 ++ 3 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 cmake/fusion.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 42692a520..4e96103f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,18 +10,12 @@ IF (CMAKE_VERSION VERSION_LESS 3.13.0) ENDIF () FIND_PACKAGE(PkgConfig REQUIRED) -INCLUDE(cmake/dtrace-utils.cmake) INCLUDE(cmake/boringssl-adjust.cmake) +INCLUDE(cmake/dtrace-utils.cmake) +INCLUDE(cmake/fusion.cmake) CHECK_DTRACE(${PROJECT_SOURCE_DIR}/picotls-probes.d) -IF ((CMAKE_SIZEOF_VOID_P EQUAL 8) AND - (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") OR - (CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") OR - (CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64")) - SET(WITH_FUSION_DEFAULT "ON") -ELSE () - SET(WITH_FUSION_DEFAULT "OFF") -ENDIF () +CHECK_FUSION_PREREQUISITES() OPTION(WITH_DTRACE "use USDT (userspace Dtrace probes)" ${HAVE_DTRACE}) OPTION(WITH_FUSION "build 'fusion' AES-GCM engine" ${WITH_FUSION_DEFAULT}) diff --git a/cmake/fusion.cmake b/cmake/fusion.cmake new file mode 100644 index 000000000..3c3c02ed6 --- /dev/null +++ b/cmake/fusion.cmake @@ -0,0 +1,29 @@ +INCLUDE(CheckCSourceCompiles) +INCLUDE(CMakePushCheckState) + +FUNCTION (CHECK_FUSION_PREREQUISITES) + MESSAGE(STATUS "Detecting fusion support") + + CMAKE_PUSH_CHECK_STATE() + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -mavx2 -maes -mpclmul -mvaes -mvpclmulqdq") + CHECK_C_SOURCE_COMPILES(" + #include + #include + int main(void) { + __m256i ord0, ord1, ord2, ord3 = _mm256_setzero_si256(); + ord0 = _mm256_aesenc_epi128(ord1, ord2); + ord3 = _mm256_aesenclast_epi128(ord0, ord1); + ord1 = _mm256_clmulepi64_epi128(ord3, ord2, 0x00); + return 0; + } + " CC_HAS_AESNI256) + CMAKE_POP_CHECK_STATE() + + IF (CC_HAS_AESNI256) + MESSAGE(STATUS "Can use fusion") + SET(WITH_FUSION_DEFAULT "ON" PARENT_SCOPE) + ELSE () + MESSAGE(STATUS "Cannot use fusion") + SET(WITH_FUSION_DEFAULT "OFF" PARENT_SCOPE) + ENDIF () +ENDFUNCTION () diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj index 6882e1977..d8a20e88b 100644 --- a/picotls.xcodeproj/project.pbxproj +++ b/picotls.xcodeproj/project.pbxproj @@ -205,6 +205,7 @@ 081F00CC291A358800534A86 /* asn1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = asn1.h; sourceTree = ""; }; 081F00CD291A358800534A86 /* pembase64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pembase64.h; sourceTree = ""; }; 081F00CE291A358800534A86 /* ptlsbcrypt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ptlsbcrypt.h; sourceTree = ""; }; + 0883D3272AEF8F2500B711CC /* fusion.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = fusion.cmake; sourceTree = ""; }; 08A835E12995E04100D872CE /* chacha20poly1305.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = chacha20poly1305.h; sourceTree = ""; }; 08A835EB2996971300D872CE /* boringssl-adjust.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "boringssl-adjust.cmake"; sourceTree = ""; }; 08B3298229419DFC009D6766 /* ech-live.t */ = {isa = PBXFileReference; lastKnownFileType = text; path = "ech-live.t"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.perl; }; @@ -527,6 +528,7 @@ children = ( 08A835EB2996971300D872CE /* boringssl-adjust.cmake */, E95EBCCA227EA0180022C32D /* dtrace-utils.cmake */, + 0883D3272AEF8F2500B711CC /* fusion.cmake */, ); path = cmake; sourceTree = ""; From 33e2fc1e1e31fb8525b968fbd78f54fa0f7263a7 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 30 Oct 2023 19:01:51 +0900 Subject: [PATCH 12/13] maybe `_mm_insert_epi64` is unavailable on i386? --- cmake/fusion.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/fusion.cmake b/cmake/fusion.cmake index 3c3c02ed6..2b7ef1c9c 100644 --- a/cmake/fusion.cmake +++ b/cmake/fusion.cmake @@ -14,6 +14,7 @@ FUNCTION (CHECK_FUSION_PREREQUISITES) ord0 = _mm256_aesenc_epi128(ord1, ord2); ord3 = _mm256_aesenclast_epi128(ord0, ord1); ord1 = _mm256_clmulepi64_epi128(ord3, ord2, 0x00); + _mm_insert_epi64(_mm_setr_epi32(0, 1, 2, 3), 0, 0); return 0; } " CC_HAS_AESNI256) From 9e323048b3f7884331f873e02c4b2286f790e9d8 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 7 Nov 2023 12:55:51 +0100 Subject: [PATCH 13/13] key_schedule_new might fail due to malloc failing --- lib/picotls.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index 34588cd16..b00b4292e 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -2373,7 +2373,10 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ /* initialize key schedule */ if (!is_second_flight) { - tls->key_schedule = key_schedule_new(tls->cipher_suite, tls->ctx->cipher_suites, tls->ech.aead != NULL); + if ((tls->key_schedule = key_schedule_new(tls->cipher_suite, tls->ctx->cipher_suites, tls->ech.aead != NULL)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; + } if ((ret = key_schedule_extract(tls->key_schedule, resumption_secret)) != 0) goto Exit; } @@ -4366,7 +4369,10 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl goto Exit; if (!is_second_flight) { tls->cipher_suite = cs; - tls->key_schedule = key_schedule_new(cs, NULL, 0); + if ((tls->key_schedule = key_schedule_new(cs, NULL, 0)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; + } } else { if (tls->cipher_suite != cs) { ret = PTLS_ALERT_HANDSHAKE_FAILURE;