From 3664bc6189db57bc99de31cb6f30b639e73c1e5e Mon Sep 17 00:00:00 2001 From: Roberto Guimaraes Date: Thu, 4 May 2023 19:44:46 -0600 Subject: [PATCH 001/151] add a new boolean flag to determine if chacha20 should be reprioritized to the top of the server cipher list in case it happens to appear at the top of the client cipher list --- include/picotls.h | 5 +++++ lib/picotls.c | 18 ++++++++++++++++-- t/picotls.c | 43 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index 0cadb178e..0ad6f872c 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -869,6 +869,11 @@ struct st_ptls_context_t { * boolean indicating if the cipher-suite should be chosen based on server's preference */ unsigned server_cipher_preference : 1; + /** + * boolean indicating if ChaCha20-Poly1305 should be reprioritized to the top of the server cipher list if a ChaCha20-Poly1305 + * cipher is at the top of the client cipher list + */ + unsigned server_cipher_chacha_priority : 1; /** * */ diff --git a/lib/picotls.c b/lib/picotls.c index a17228913..d07fa79e5 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -1979,16 +1979,27 @@ static int decode_signature_algorithms(struct st_ptls_signature_algorithms_t *sa } static int select_cipher(ptls_cipher_suite_t **selected, ptls_cipher_suite_t **candidates, const uint8_t *src, - const uint8_t *const end, int server_preference) + const uint8_t *const end, int server_preference, int server_chacha_priority) { size_t found_index = SIZE_MAX; int ret; + int is_first_cipher = 1; while (src != end) { uint16_t id; if ((ret = ptls_decode16(&id, &src, end)) != 0) goto Exit; + if (is_first_cipher && server_chacha_priority) { + if (id != PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256) + server_chacha_priority = 0; + is_first_cipher = 0; + } for (size_t i = 0; candidates[i] != NULL; ++i) { + if (server_chacha_priority && candidates[i]->id == PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256) { + /* return the pointer matching chacha20 cipher found in the server list */ + *selected = candidates[i]; + goto Exit; + } if (candidates[i]->id == id) { if (server_preference) { /* preserve smallest matching index, and proceed to the next input */ @@ -2003,6 +2014,9 @@ static int select_cipher(ptls_cipher_suite_t **selected, ptls_cipher_suite_t **c } } } + /* first position of the server list matched (server_preference) */ + if (found_index == 0) + break; } if (found_index != SIZE_MAX) { *selected = candidates[found_index]; @@ -4353,7 +4367,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl { /* select (or check) cipher-suite, create key_schedule */ ptls_cipher_suite_t *cs; if ((ret = select_cipher(&cs, tls->ctx->cipher_suites, ch->cipher_suites.base, - ch->cipher_suites.base + ch->cipher_suites.len, tls->ctx->server_cipher_preference)) != 0) + ch->cipher_suites.base + ch->cipher_suites.len, tls->ctx->server_cipher_preference, tls->ctx->server_cipher_chacha_priority)) != 0) goto Exit; if (!is_second_flight) { tls->cipher_suite = cs; diff --git a/t/picotls.c b/t/picotls.c index b81f83560..467ea2095 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -60,30 +60,59 @@ static void test_select_cipher(void) { #define C(x) ((x) >> 8) & 0xff, (x)&0xff - ptls_cipher_suite_t *selected, - *candidates[] = {&ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL}; + ptls_cipher_suite_t *selected; { + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL}; static const uint8_t input; /* `input[0]` is preferable, but prohibited by MSVC */ - ok(select_cipher(&selected, candidates, &input, &input, 0) == PTLS_ALERT_HANDSHAKE_FAILURE); + ok(select_cipher(&selected, candidates, &input, &input, 0, 0) == PTLS_ALERT_HANDSHAKE_FAILURE); } { + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL}; static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256)}; - ok(select_cipher(&selected, candidates, input, input + sizeof(input), 0) == 0); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 0, 0) == 0); ok(selected == &ptls_minicrypto_aes128gcmsha256); - ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1) == 0); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0); ok(selected == &ptls_minicrypto_chacha20poly1305sha256); } { + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL}; static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256)}; - ok(select_cipher(&selected, candidates, input, input + sizeof(input), 0) == 0); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 0, 0) == 0); ok(selected == &ptls_minicrypto_aes128gcmsha256); - ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1) == 0); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0); ok(selected == &ptls_minicrypto_aes128gcmsha256); } + { + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, NULL}; + static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256)}; + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0); + ok(selected == &ptls_minicrypto_aes128gcmsha256); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); + ok(selected == &ptls_minicrypto_chacha20poly1305sha256); + } + + { + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL}; + static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0); + ok(selected == &ptls_minicrypto_aes256gcmsha384); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); + ok(selected == &ptls_minicrypto_chacha20poly1305sha256); + } + + { + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL}; + static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); + ok(selected == &ptls_minicrypto_aes256gcmsha384); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); + ok(selected == &ptls_minicrypto_aes256gcmsha384); + } + #undef C } From 9918937d1ad3f21246ae258be7281448ca7170b8 Mon Sep 17 00:00:00 2001 From: Roberto Guimaraes Date: Mon, 8 May 2023 11:47:50 -0600 Subject: [PATCH 002/151] add a test where the client offers chacha, but chacha is not avail in the server list: server preference should be honered if set --- t/picotls.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/t/picotls.c b/t/picotls.c index 467ea2095..6116de02b 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -102,6 +102,8 @@ static void test_select_cipher(void) ok(selected == &ptls_minicrypto_aes256gcmsha384); ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); ok(selected == &ptls_minicrypto_chacha20poly1305sha256); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 0, 1) == 0); + ok(selected == &ptls_minicrypto_chacha20poly1305sha256); } { @@ -113,6 +115,19 @@ static void test_select_cipher(void) ok(selected == &ptls_minicrypto_aes256gcmsha384); } + { + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_aes128gcmsha256, NULL}; + static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0); + ok(selected == &ptls_minicrypto_aes256gcmsha384); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); + ok(selected == &ptls_minicrypto_aes256gcmsha384); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 0, 0) == 0); + ok(selected == &ptls_minicrypto_aes128gcmsha256); + ok(select_cipher(&selected, candidates, input, input + sizeof(input), 0, 1) == 0); + ok(selected == &ptls_minicrypto_aes128gcmsha256); + } + #undef C } From f4c3536b561e3c8f727680eca210058f68495054 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sun, 7 May 2023 09:06:04 +0900 Subject: [PATCH 003/151] `server_prefer_chacha` indicates a condition to disable server-precedence --- lib/picotls.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index d07fa79e5..14ea227da 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -1983,25 +1983,14 @@ static int select_cipher(ptls_cipher_suite_t **selected, ptls_cipher_suite_t **c { size_t found_index = SIZE_MAX; int ret; - int is_first_cipher = 1; while (src != end) { uint16_t id; if ((ret = ptls_decode16(&id, &src, end)) != 0) goto Exit; - if (is_first_cipher && server_chacha_priority) { - if (id != PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256) - server_chacha_priority = 0; - is_first_cipher = 0; - } for (size_t i = 0; candidates[i] != NULL; ++i) { - if (server_chacha_priority && candidates[i]->id == PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256) { - /* return the pointer matching chacha20 cipher found in the server list */ - *selected = candidates[i]; - goto Exit; - } if (candidates[i]->id == id) { - if (server_preference) { + if (server_preference && !(server_chacha_priority && id == PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256)) { /* preserve smallest matching index, and proceed to the next input */ if (i < found_index) { found_index = i; @@ -2017,6 +2006,8 @@ static int select_cipher(ptls_cipher_suite_t **selected, ptls_cipher_suite_t **c /* first position of the server list matched (server_preference) */ if (found_index == 0) break; + /* server preference is overridden only if the first entry of client-provided list is chachapoly */ + server_chacha_priority = 0; } if (found_index != SIZE_MAX) { *selected = candidates[found_index]; From 1f79b442e09f1a576de0d2ebac16ed19b0ac2063 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 2 Aug 2023 11:52:26 +0200 Subject: [PATCH 004/151] cmake: "FATAL ERROR" -> FATAL_ERROR --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ad42d82b..6faf288c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,7 +196,7 @@ ENDIF () IF (BUILD_FUZZER) IF (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - MESSAGE(FATAL ERROR "The fuzzer needs clang as a compiler") + MESSAGE(FATAL_ERROR "The fuzzer needs clang as a compiler") ENDIF() ADD_EXECUTABLE(fuzz-asn1 fuzz/fuzz-asn1.c) From d7cc3f2dd1b352af4423e6e91c858f80e2537abc Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 2 Aug 2023 11:49:07 +0200 Subject: [PATCH 005/151] Add ptls_export() prototype to picotls.h --- include/picotls.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/picotls.h b/include/picotls.h index 0ad6f872c..2d829cc89 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -1417,6 +1417,10 @@ static ptls_t *ptls_new(ptls_context_t *ctx, int is_server); int ptls_build_tls12_export_params(ptls_context_t *ctx, ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher, const void *master_secret, const void *hello_randoms, uint64_t next_send_record_iv, const char *server_name, ptls_iovec_t negotiated_protocol); +/** + * store the parameters of a post-handshake TLS connection so that it can be reconstructed later + */ +int ptls_export(ptls_t *tls, ptls_buffer_t *output); /** * create a post-handshake TLS connection object using given parameters */ From 6609fc5de315c0102f136652e5cff69a6b5255b7 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 1 Aug 2023 19:43:17 +0200 Subject: [PATCH 006/151] Add optional support for the AEGIS cipher suites This adds the following TLS 1.3 suites: - `TLS_AEGIS_256_SHA384 (0x13, 0x07)` - `TLS_AEGIS_128L_SHA256 (0x13, 0x06)` Requires `libaegis`. --- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 39 +++++- README.md | 5 +- include/picotls.h | 18 ++- include/picotls/minicrypto.h | 8 ++ lib/cifra.c | 15 ++- lib/cifra/libaegis.c | 62 +++++++++ lib/libaegis.h | 252 +++++++++++++++++++++++++++++++++++ lib/openssl.c | 61 ++++++++- lib/picotls.c | 4 + t/openssl.c | 6 +- t/picotls.c | 32 +++++ t/ptlsbench.c | 4 + 13 files changed, 492 insertions(+), 16 deletions(-) create mode 100644 lib/cifra/libaegis.c create mode 100644 lib/libaegis.h diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02cd62674..80b5401a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: - name: "Linux / OpenSSL 1.1.0" command: make -f misc/docker-ci.mk CMAKE_ARGS='-DOPENSSL_ROOT_DIR=-DOPENSSL_ROOT_DIR=/opt/openssl-1.1.0 -DWITH_FUSION=OFF' CONTAINER_NAME='h2oserver/h2o-ci:ubuntu1604' - name: "Linux / OpenSSL 1.1.1" - command: make -f misc/docker-ci.mk + command: make -f misc/docker-ci.mk CMAKE_ARGS='-DWITH_AEGIS=1 -DAEGIS_INCLUDE_DIR=/usr/local/include' - name: "Linux / OpenSSL 3.0" command: make -f misc/docker-ci.mk CONTAINER_NAME=h2oserver/h2o-ci:ubuntu2204 - name: "Linux / OpenSSL 1.1.1 + ASan & UBSan" diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ad42d82b..42692a520 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ ENDIF () IF (WITH_FUSION) MESSAGE(STATUS "Enabling 'fusion' AES-GCM engine") ENDIF () +OPTION(WITH_AEGIS "enable AEGIS (requires libaegis)" ${WITH_AEGIS}) SET(CMAKE_C_FLAGS "-std=c99 -Wall -O2 -g ${CC_WARNING_FLAGS} ${CMAKE_C_FLAGS}") INCLUDE_DIRECTORIES( @@ -88,8 +89,13 @@ ADD_LIBRARY(picotls-core ${CORE_FILES}) TARGET_LINK_LIBRARIES(picotls-core ${CORE_EXTRA_LIBS}) TARGET_LINK_DIRECTORIES(picotls-core PUBLIC ${CORE_EXTRA_LIBS_DIRS}) +IF (WITH_AEGIS) + SET(MINICRYPTO_AEGIS_FILES lib/cifra/libaegis.c) +ENDIF () + ADD_LIBRARY(picotls-minicrypto ${MINICRYPTO_LIBRARY_FILES} + ${MINICRYPTO_AEGIS_FILES} lib/cifra.c lib/cifra/x25519.c lib/cifra/chacha20.c @@ -103,6 +109,7 @@ ADD_LIBRARY(picotls-minicrypto TARGET_LINK_LIBRARIES(picotls-minicrypto picotls-core) ADD_EXECUTABLE(test-minicrypto.t ${MINICRYPTO_LIBRARY_FILES} + ${MINICRYPTO_AEGIS_FILES} deps/picotest/picotest.c ${CORE_TEST_FILES} t/minicrypto.c @@ -120,6 +127,23 @@ SET(TEST_EXES test-minicrypto.t) SET(PTLSBENCH_LIBS picotls-minicrypto picotls-core) +IF (WITH_AEGIS) + FIND_PACKAGE(aegis) + IF (aegis_FOUND) + INCLUDE_DIRECTORIES(${AEGIS_INCLUDE_DIR}) + IF (EXISTS "${AEGIS_INCLUDE_DIR}/aegis.h") + MESSAGE(STATUS "Enabling AEGIS support (library found in ${aegis_DIR})") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPTLS_HAVE_AEGIS=1") + SET(AEGIS_LIBRARIES ${aegis_LIBRARIES}) + TARGET_LINK_LIBRARIES(test-minicrypto.t ${AEGIS_LIBRARIES}) + ELSE() + MESSAGE(FATAL_ERROR "libaegis found, but aegis.h not found - Define AEGIS_INCLUDE_DIR accordingly") + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR "libaegis not found") + ENDIF() +ENDIF() + FIND_PACKAGE(OpenSSL) BORINGSSL_ADJUST() @@ -127,12 +151,13 @@ IF (OPENSSL_FOUND AND NOT (OPENSSL_VERSION VERSION_LESS "1.0.1")) MESSAGE(STATUS " Enabling OpenSSL support") INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) ADD_LIBRARY(picotls-openssl lib/openssl.c) - TARGET_LINK_LIBRARIES(picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} picotls-core ${CMAKE_DL_LIBS}) + TARGET_LINK_LIBRARIES(picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${AEGIS_LIBRARIES} picotls-core ${CMAKE_DL_LIBS}) ADD_EXECUTABLE(cli t/cli.c lib/pembase64.c) TARGET_LINK_LIBRARIES(cli picotls-openssl picotls-core) ADD_EXECUTABLE(test-openssl.t ${MINICRYPTO_LIBRARY_FILES} + ${MINICRYPTO_AEGIS_FILES} lib/cifra.c lib/cifra/x25519.c lib/cifra/chacha20.c @@ -147,9 +172,9 @@ IF (OPENSSL_FOUND AND NOT (OPENSSL_VERSION VERSION_LESS "1.0.1")) ${CORE_TEST_FILES} t/openssl.c) SET_TARGET_PROPERTIES(test-openssl.t PROPERTIES COMPILE_FLAGS "-DPTLS_MEMORY_DEBUG=1") - TARGET_LINK_LIBRARIES(test-openssl.t ${OPENSSL_CRYPTO_LIBRARIES} ${CMAKE_DL_LIBS}) + TARGET_LINK_LIBRARIES(test-openssl.t ${OPENSSL_CRYPTO_LIBRARIES} ${AEGIS_LIBRARIES} ${CMAKE_DL_LIBS}) - LIST(APPEND PTLSBENCH_LIBS picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${CMAKE_DL_LIBS}) + LIST(APPEND PTLSBENCH_LIBS picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${AEGIS_LIBRARIES} ${CMAKE_DL_LIBS}) SET(TEST_EXES ${TEST_EXES} test-openssl.t) ELSE () @@ -196,7 +221,7 @@ ENDIF () IF (BUILD_FUZZER) IF (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - MESSAGE(FATAL ERROR "The fuzzer needs clang as a compiler") + MESSAGE(FATAL_ERROR "The fuzzer needs clang as a compiler") ENDIF() ADD_EXECUTABLE(fuzz-asn1 fuzz/fuzz-asn1.c) @@ -225,8 +250,8 @@ IF (BUILD_FUZZER) LINK_FLAGS "-fsanitize=fuzzer") ENDIF (OSS_FUZZ) - TARGET_LINK_LIBRARIES(fuzz-asn1 picotls-minicrypto picotls-core picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${LIB_FUZZER}) - TARGET_LINK_LIBRARIES(fuzz-server-hello picotls-core picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${LIB_FUZZER}) - TARGET_LINK_LIBRARIES(fuzz-client-hello picotls-core picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${LIB_FUZZER}) + TARGET_LINK_LIBRARIES(fuzz-asn1 picotls-minicrypto picotls-core picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${AEGIS_LIBRARIES} ${LIB_FUZZER}) + TARGET_LINK_LIBRARIES(fuzz-server-hello picotls-core picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${AEGIS_LIBRARIES} ${LIB_FUZZER}) + TARGET_LINK_LIBRARIES(fuzz-client-hello picotls-core picotls-openssl ${OPENSSL_CRYPTO_LIBRARIES} ${AEGIS_LIBRARIES} ${LIB_FUZZER}) ENDIF() diff --git a/README.md b/README.md index 5bb0e3a64..3f4570e9b 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Picotls is a [TLS 1.3 (RFC 8446)](https://tools.ietf.org/html/rfc8446) protocol * "OpenSSL" backend using libcrypto for crypto and X.509 operations * "minicrypto" backend using [cifra](https://github.com/ctz/cifra) for most crypto and [micro-ecc](https://github.com/kmackay/micro-ecc) for secp256r1 * ["fusion" AES-GCM engine, optimized for QUIC and other protocols that use short AEAD blocks](https://github.com/h2o/picotls/pull/310) + * [libaegis](https://github.com/jedisct1/libaegis) for the AEGIS AEADs * support for PSK, PSK-DHE resumption using 0-RTT * API for dealing directly with TLS handshake messages (essential for QUIC) * supported extensions: @@ -23,8 +24,8 @@ License and the cryptographic algorithms supported by the crypto bindings are as | Binding | License | Key Exchange | Certificate | AEAD cipher | |:-----:|:-----:|:-----:|:-----:|:-----:| -| minicrypto | [CC0](https://github.com/ctz/cifra/) / [2-clause BSD](https://github.com/kmackay/micro-ecc) | secp256r1, x25519 | ECDSA (secp256r1)1 | AES-128-GCM, chacha20-poly1305 | -| OpenSSL | OpenSSL | secp256r1, secp384r1, secp521r1, x25519 | RSA, ECDSA (secp256r1, secp384r1, secp521r1), ed25519 | AES-128-GCM, AES-256-GCM, chacha20-poly1305 | +| minicrypto | [CC0](https://github.com/ctz/cifra/) / [2-clause BSD](https://github.com/kmackay/micro-ecc) | secp256r1, x25519 | ECDSA (secp256r1)1 | AES-128-GCM, chacha20-poly1305, AEGIS-128L (using libaegis), AEGIS-256 (using libaegis) | +| OpenSSL | OpenSSL | secp256r1, secp384r1, secp521r1, x25519 | RSA, ECDSA (secp256r1, secp384r1, secp521r1), ed25519 | AES-128-GCM, AES-256-GCM, chacha20-poly1305, AEGIS-128L (using libaegis), AEGIS-256 (using libaegis) | Note 1: Minicrypto binding is capable of signing a handshake using the certificate's key, but cannot verify a signature sent by the peer. diff --git a/include/picotls.h b/include/picotls.h index 0ad6f872c..00621bd80 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -91,6 +91,18 @@ extern "C" { #define PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT UINT64_MAX /* at least 2^64 */ #define PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT UINT64_C(0x1000000000) /* 2^36 */ +#define PTLS_AEGIS128L_KEY_SIZE 16 +#define PTLS_AEGIS128L_IV_SIZE 16 +#define PTLS_AEGIS128L_TAG_SIZE 16 +#define PTLS_AEGIS128L_CONFIDENTIALITY_LIMIT UINT64_MAX /* at least 2^64 */ +#define PTLS_AEGIS128L_INTEGRITY_LIMIT UINT64_C(0x1000000000000) /* 2^48 */ + +#define PTLS_AEGIS256_KEY_SIZE 32 +#define PTLS_AEGIS256_IV_SIZE 32 +#define PTLS_AEGIS256_TAG_SIZE 16 +#define PTLS_AEGIS256_CONFIDENTIALITY_LIMIT UINT64_MAX /* at least 2^64 */ +#define PTLS_AEGIS256_INTEGRITY_LIMIT UINT64_C(0x1000000000000) /* 2^48 */ + #define PTLS_BLOWFISH_KEY_SIZE 16 #define PTLS_BLOWFISH_BLOCK_SIZE 8 @@ -104,7 +116,7 @@ extern "C" { #define PTLS_SHA512_DIGEST_SIZE 64 #define PTLS_MAX_SECRET_SIZE 32 -#define PTLS_MAX_IV_SIZE 16 +#define PTLS_MAX_IV_SIZE 32 #define PTLS_MAX_DIGEST_SIZE 64 /* versions */ @@ -118,6 +130,10 @@ extern "C" { #define PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" #define PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256 0x1303 #define PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" +#define PTLS_CIPHER_SUITE_AEGIS256_SHA384 0x1306 +#define PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384 "TLS_AEGIS_256_SHA384" +#define PTLS_CIPHER_SUITE_AEGIS128L_SHA256 0x1307 +#define PTLS_CIPHER_SUITE_NAME_AEGIS128L_SHA256 "TLS_AEGIS_128L_SHA256" /* TLS/1.2 cipher-suites that we support (for compatibility, OpenSSL names are used) */ #define PTLS_CIPHER_SUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xc02b diff --git a/include/picotls/minicrypto.h b/include/picotls/minicrypto.h index af0c71466..21f5c1c6f 100644 --- a/include/picotls/minicrypto.h +++ b/include/picotls/minicrypto.h @@ -47,8 +47,16 @@ extern ptls_key_exchange_algorithm_t *ptls_minicrypto_key_exchanges[]; extern ptls_cipher_algorithm_t ptls_minicrypto_aes128ecb, ptls_minicrypto_aes256ecb, ptls_minicrypto_aes128ctr, ptls_minicrypto_aes256ctr, ptls_minicrypto_chacha20; extern ptls_aead_algorithm_t ptls_minicrypto_aes128gcm, ptls_minicrypto_aes256gcm, ptls_minicrypto_chacha20poly1305; +#ifdef PTLS_HAVE_AEGIS +extern ptls_aead_algorithm_t ptls_minicrypto_aegis128l; +extern ptls_aead_algorithm_t ptls_minicrypto_aegis256; +#endif extern ptls_hash_algorithm_t ptls_minicrypto_sha256, ptls_minicrypto_sha384; extern ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256, ptls_minicrypto_aes256gcmsha384, ptls_minicrypto_chacha20poly1305sha256; +#ifdef PTLS_HAVE_AEGIS +extern ptls_cipher_suite_t ptls_minicrypto_aegis128lsha256; +extern ptls_cipher_suite_t ptls_minicrypto_aegis256sha384; +#endif extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[]; typedef struct st_ptls_asn1_pkcs8_private_key_t { diff --git a/lib/cifra.c b/lib/cifra.c index b41d3bc0d..507014ef2 100644 --- a/lib/cifra.c +++ b/lib/cifra.c @@ -23,5 +23,16 @@ #include "picotls.h" #include "picotls/minicrypto.h" -ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_aes128gcmsha256, - &ptls_minicrypto_chacha20poly1305sha256, NULL}; +ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha384 (must be first) +#ifdef PTLS_HAVE_AEGIS + &ptls_minicrypto_aegis256sha384, +#endif + &ptls_minicrypto_aes256gcmsha384, + + // ciphers used with sha256 +#ifdef PTLS_HAVE_AEGIS + &ptls_minicrypto_aegis128lsha256, +#endif + &ptls_minicrypto_aes128gcmsha256, + &ptls_minicrypto_chacha20poly1305sha256, + NULL}; diff --git a/lib/cifra/libaegis.c b/lib/cifra/libaegis.c new file mode 100644 index 000000000..0b4af9349 --- /dev/null +++ b/lib/cifra/libaegis.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Frank Denis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "../libaegis.h" + +extern ptls_hash_algorithm_t ptls_minicrypto_sha256; +extern ptls_hash_algorithm_t ptls_minicrypto_sha384; + +ptls_aead_algorithm_t ptls_minicrypto_aegis128l = {"AEGIS-128L", + PTLS_AEGIS128L_CONFIDENTIALITY_LIMIT, + PTLS_AEGIS128L_INTEGRITY_LIMIT, + NULL, + NULL, + PTLS_AEGIS128L_KEY_SIZE, + PTLS_AEGIS128L_IV_SIZE, + PTLS_AEGIS128L_TAG_SIZE, + { 0, 0 }, + 0, + 0, + sizeof(struct aegis128l_context_t), + aegis128l_setup_crypto}; +ptls_cipher_suite_t ptls_minicrypto_aegis128lsha256 = {.id = PTLS_CIPHER_SUITE_AEGIS128L_SHA256, + .name = PTLS_CIPHER_SUITE_NAME_AEGIS128L_SHA256, + .aead = &ptls_minicrypto_aegis128l, + .hash = &ptls_minicrypto_sha256}; + +ptls_aead_algorithm_t ptls_minicrypto_aegis256 = {"AEGIS-256", + PTLS_AEGIS256_CONFIDENTIALITY_LIMIT, + PTLS_AEGIS256_INTEGRITY_LIMIT, + NULL, + NULL, + PTLS_AEGIS256_KEY_SIZE, + PTLS_AEGIS256_IV_SIZE, + PTLS_AEGIS256_TAG_SIZE, + { 0, 0 }, + 0, + 0, + sizeof(struct aegis256_context_t), + aegis256_setup_crypto}; +ptls_cipher_suite_t ptls_minicrypto_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384, + .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384, + .aead = &ptls_minicrypto_aegis256, + .hash = &ptls_minicrypto_sha384}; diff --git a/lib/libaegis.h b/lib/libaegis.h new file mode 100644 index 000000000..ec78a4bb1 --- /dev/null +++ b/lib/libaegis.h @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2023 Frank Denis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include + +#include "picotls.h" + +// AEGIS-128L + +struct aegis128l_context_t { + ptls_aead_context_t super; + aegis128l_state st; + uint8_t key[PTLS_AEGIS128L_KEY_SIZE]; + uint8_t static_iv[PTLS_AEGIS128L_IV_SIZE]; +}; + +static void aegis128l_get_iv(ptls_aead_context_t *_ctx, void *iv) +{ + struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; + + memcpy(iv, ctx->static_iv, sizeof(ctx->static_iv)); +} + +static void aegis128l_set_iv(ptls_aead_context_t *_ctx, const void *iv) +{ + struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; + + memcpy(ctx->static_iv, iv, sizeof(ctx->static_iv)); +} + +static void aegis128l_init(ptls_aead_context_t *_ctx, uint64_t seq, const void *aad, size_t aadlen) +{ + struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; + uint8_t iv[PTLS_AEGIS128L_IV_SIZE]; + + ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); + + aegis128l_state_init(&ctx->st, (const uint8_t *)aad, aadlen, iv, ctx->key); + + return; +} + +static size_t aegis128l_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen) +{ + struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; + size_t written; + + aegis128l_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis128l_TAILBYTES_MAX, &written, (const uint8_t *)input, inlen); + + return written; +} + +static size_t aegis128l_encrypt_final(ptls_aead_context_t *_ctx, void *output) +{ + struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; + size_t written; + + aegis128l_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis128l_TAILBYTES_MAX + PTLS_AEGIS128L_TAG_SIZE, &written, PTLS_AEGIS128L_TAG_SIZE); + + return written; +} + +static size_t aegis128l_decrypt_oneshot(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq, + const void *aad, size_t aadlen) +{ + struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; + uint8_t iv[PTLS_AEGIS128L_IV_SIZE] = {0}; + + if (inlen < PTLS_AEGIS128L_TAG_SIZE) { + return SIZE_MAX; + } + + ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); + + if (aegis128l_decrypt((uint8_t *)output, (const uint8_t *)input, inlen, PTLS_AEGIS128L_TAG_SIZE, (const uint8_t *)aad, aadlen, + iv, ctx->key) != 0) { + return SIZE_MAX; + } + + return inlen - PTLS_AEGIS128L_TAG_SIZE; +} + +static void aegis128l_dispose_crypto(ptls_aead_context_t *_ctx) +{ + struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; + + ptls_clear_memory(ctx->key, sizeof(ctx->key)); + + return; +} + +static int aegis128l_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv) +{ + struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; + + ctx->super.dispose_crypto = aegis128l_dispose_crypto; + ctx->super.do_get_iv = aegis128l_get_iv; + ctx->super.do_set_iv = aegis128l_set_iv; + + if (is_enc) { + ctx->super.do_encrypt_init = aegis128l_init; + ctx->super.do_encrypt_update = aegis128l_encrypt_update; + ctx->super.do_encrypt_final = aegis128l_encrypt_final; + ctx->super.do_encrypt = ptls_aead__do_encrypt; + ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v; + ctx->super.do_decrypt = NULL; + } else { + ctx->super.do_encrypt_init = NULL; + ctx->super.do_encrypt_update = NULL; + ctx->super.do_encrypt_final = NULL; + ctx->super.do_encrypt = NULL; + ctx->super.do_encrypt_v = NULL; + ctx->super.do_decrypt = aegis128l_decrypt_oneshot; + } + + memcpy(ctx->key, key, sizeof(ctx->key)); + memcpy(ctx->static_iv, iv, sizeof(ctx->static_iv)); + + return 0; +} + +// AEGIS-256 + +struct aegis256_context_t { + ptls_aead_context_t super; + aegis256_state st; + uint8_t key[PTLS_AEGIS256_KEY_SIZE]; + uint8_t static_iv[PTLS_AEGIS256_IV_SIZE]; +}; + +static void aegis256_get_iv(ptls_aead_context_t *_ctx, void *iv) +{ + struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; + + memcpy(iv, ctx->static_iv, sizeof(ctx->static_iv)); +} + +static void aegis256_set_iv(ptls_aead_context_t *_ctx, const void *iv) +{ + struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; + + memcpy(ctx->static_iv, iv, sizeof(ctx->static_iv)); +} + +static void aegis256_init(ptls_aead_context_t *_ctx, uint64_t seq, const void *aad, size_t aadlen) +{ + struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; + uint8_t iv[PTLS_AEGIS256_IV_SIZE] = {0}; + + ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); + + aegis256_state_init(&ctx->st, (const uint8_t *)aad, aadlen, iv, ctx->key); + + return; +} + +static size_t aegis256_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen) +{ + struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; + size_t written; + + aegis256_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis256_TAILBYTES_MAX, &written, (const uint8_t *)input, inlen); + + return written; +} + +static size_t aegis256_encrypt_final(ptls_aead_context_t *_ctx, void *output) +{ + struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; + size_t written; + + aegis256_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis256_TAILBYTES_MAX + PTLS_AEGIS256_TAG_SIZE, &written, PTLS_AEGIS256_TAG_SIZE); + + return written; +} + +static size_t aegis256_decrypt_oneshot(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq, + const void *aad, size_t aadlen) +{ + struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; + uint8_t iv[PTLS_AEGIS256_IV_SIZE]; + + if (inlen < PTLS_AEGIS256_TAG_SIZE) { + return SIZE_MAX; + } + + ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); + + if (aegis256_decrypt((uint8_t *)output, (const uint8_t *)input, inlen, PTLS_AEGIS256_TAG_SIZE, (const uint8_t *)aad, aadlen, iv, + ctx->key) != 0) { + return SIZE_MAX; + } + + return inlen - PTLS_AEGIS256_TAG_SIZE; +} + +static void aegis256_dispose_crypto(ptls_aead_context_t *_ctx) +{ + struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; + + ptls_clear_memory(ctx->key, sizeof(ctx->key)); + + return; +} + +static int aegis256_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv) +{ + struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; + + ctx->super.dispose_crypto = aegis256_dispose_crypto; + ctx->super.do_get_iv = aegis256_get_iv; + ctx->super.do_set_iv = aegis256_set_iv; + + if (is_enc) { + ctx->super.do_encrypt_init = aegis256_init; + ctx->super.do_encrypt_update = aegis256_encrypt_update; + ctx->super.do_encrypt_final = aegis256_encrypt_final; + ctx->super.do_encrypt = ptls_aead__do_encrypt; + ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v; + ctx->super.do_decrypt = NULL; + } else { + ctx->super.do_encrypt_init = NULL; + ctx->super.do_encrypt_update = NULL; + ctx->super.do_encrypt_final = NULL; + ctx->super.do_encrypt = NULL; + ctx->super.do_encrypt_v = NULL; + ctx->super.do_decrypt = aegis256_decrypt_oneshot; + } + + memcpy(ctx->key, key, sizeof(ctx->key)); + memcpy(ctx->static_iv, iv, sizeof(ctx->static_iv)); + + return 0; +} diff --git a/lib/openssl.c b/lib/openssl.c index 0cd39767f..daf1dbaaf 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -52,6 +52,9 @@ #ifdef OPENSSL_IS_BORINGSSL #include "./chacha20poly1305.h" #endif +#ifdef PTLS_HAVE_AEGIS +#include "./libaegis.h" +#endif #ifdef _WINDOWS #ifndef _CRT_SECURE_NO_WARNINGS @@ -2161,7 +2164,63 @@ ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_ecdsa_chacha20poly1305sha256 = { .aead = &ptls_openssl_chacha20poly1305, .hash = &ptls_openssl_sha256}; #endif -ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = {&ptls_openssl_aes256gcmsha384, &ptls_openssl_aes128gcmsha256, + + +#if PTLS_HAVE_AEGIS +ptls_aead_algorithm_t ptls_libaegis_aegis128l = { + .name = "AEGIS-128L", + .confidentiality_limit = PTLS_AEGIS128L_CONFIDENTIALITY_LIMIT, + .integrity_limit = PTLS_AEGIS128L_INTEGRITY_LIMIT, + .ctr_cipher = NULL, + .ecb_cipher = NULL, + .key_size = PTLS_AEGIS128L_KEY_SIZE, + .iv_size = PTLS_AEGIS128L_IV_SIZE, + .tag_size = PTLS_AEGIS128L_TAG_SIZE, + .tls12 = { .fixed_iv_size = 0, .record_iv_size = 0 }, + .non_temporal = 0, + .align_bits = 0, + .context_size = sizeof(struct aegis128l_context_t), + .setup_crypto = aegis128l_setup_crypto, +}; +ptls_cipher_suite_t ptls_openssl_aegis128lsha256 = {.id = PTLS_CIPHER_SUITE_AEGIS128L_SHA256, + .name = PTLS_CIPHER_SUITE_NAME_AEGIS128L_SHA256, + .aead = &ptls_libaegis_aegis128l, + .hash = &ptls_openssl_sha256}; + +ptls_aead_algorithm_t ptls_libaegis_aegis256 = { + .name = "AEGIS-256", + .confidentiality_limit = PTLS_AEGIS256_CONFIDENTIALITY_LIMIT, + .integrity_limit = PTLS_AEGIS256_INTEGRITY_LIMIT, + .ctr_cipher = NULL, + .ecb_cipher = NULL, + .key_size = PTLS_AEGIS256_KEY_SIZE, + .iv_size = PTLS_AEGIS256_IV_SIZE, + .tag_size = PTLS_AEGIS256_TAG_SIZE, + .tls12 = { .fixed_iv_size = 0, .record_iv_size = 0 }, + .non_temporal = 0, + .align_bits = 0, + .context_size = sizeof(struct aegis256_context_t), + .setup_crypto = aegis256_setup_crypto, +}; +ptls_cipher_suite_t ptls_openssl_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384, + .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384, + .aead = &ptls_libaegis_aegis256, + .hash = &ptls_openssl_sha384}; +#endif + + + +ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = {// ciphers used with sha384 (must be first) +#if PTLS_HAVE_AEGIS + &ptls_openssl_aegis256sha384, +#endif + &ptls_openssl_aes256gcmsha384, + + // ciphers used with sha256 +#if PTLS_HAVE_AEGIS + &ptls_openssl_aegis128lsha256, +#endif + &ptls_openssl_aes128gcmsha256, #if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 &ptls_openssl_chacha20poly1305sha256, #endif diff --git a/lib/picotls.c b/lib/picotls.c index 14ea227da..906bc97f6 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -39,6 +39,10 @@ #include "picotls-probes.h" #endif +#ifdef PTLS_HAVE_AEGIS +#include +#endif + #define PTLS_MAX_PLAINTEXT_RECORD_SIZE 16384 #define PTLS_MAX_ENCRYPTED_RECORD_SIZE (16384 + 256) diff --git a/t/openssl.c b/t/openssl.c index 4ca49aa38..9daec5e61 100644 --- a/t/openssl.c +++ b/t/openssl.c @@ -562,9 +562,11 @@ int main(int argc, char **argv) .server = {.create_opener = &ech_create_opener, .retry_configs = {(uint8_t *)ECH_CONFIG_LIST, sizeof(ECH_CONFIG_LIST) - 1}}}, .sign_certificate = &openssl_sign_certificate.super}; - assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */ ptls_context_t openssl_ctx_sha256only = openssl_ctx; - ++openssl_ctx_sha256only.cipher_suites; + while (openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size != 32) { + assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */ + ++openssl_ctx_sha256only.cipher_suites; + } assert(openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size == 32); /* sha256 */ ctx = ctx_peer = &openssl_ctx; diff --git a/t/picotls.c b/t/picotls.c index 6116de02b..ecca51d3c 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -494,6 +494,34 @@ static void test_chacha20poly1305(void) } } +#ifdef PTLS_HAVE_AEGIS +static void test_aegis128l(void) +{ + ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AEGIS128L_SHA256), + *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AEGIS128L_SHA256); + + if (cs != NULL && cs_peer != NULL) { + test_ciphersuite(cs, cs_peer); + test_ciphersuite_stream(cs, cs_peer); + test_aad_ciphersuite(cs, cs_peer); + test_aad96_ciphersuite(cs, cs_peer); + } +} + +static void test_aegis256(void) +{ + ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AEGIS256_SHA384), + *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AEGIS256_SHA384); + + if (cs != NULL && cs_peer != NULL) { + test_ciphersuite(cs, cs_peer); + test_ciphersuite_stream(cs, cs_peer); + test_aad_ciphersuite(cs, cs_peer); + test_aad96_ciphersuite(cs, cs_peer); + } +} +#endif + static void test_ffx(void) { static uint8_t ffx_test_source[32] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', @@ -2112,6 +2140,10 @@ void test_picotls(void) subtest("aes128gcm", test_aes128gcm); subtest("aes256gcm", test_aes256gcm); subtest("chacha20poly1305", test_chacha20poly1305); +#ifdef PTLS_HAVE_AEGIS + subtest("aegis-128l", test_aegis128l); + subtest("aegis-256", test_aegis256); +#endif subtest("aes128ecb", test_aes128ecb); subtest("aes256ecb", test_aes256ecb); subtest("aes128ctr", test_aes128ctr); diff --git a/t/ptlsbench.c b/t/ptlsbench.c index 62ac3595e..1b27607eb 100644 --- a/t/ptlsbench.c +++ b/t/ptlsbench.c @@ -253,6 +253,10 @@ static ptls_bench_entry_t aead_list[] = { {"minicrypto", "aes128gcm", &ptls_minicrypto_aes128gcm, &ptls_minicrypto_sha256, 0}, {"minicrypto", "aes256gcm", &ptls_minicrypto_aes256gcm, &ptls_minicrypto_sha384, 0}, {"minicrypto", "chacha20poly1305", &ptls_minicrypto_chacha20poly1305, &ptls_minicrypto_sha256, 1}, +#ifdef PTLS_HAVE_AEGIS + {"minicrypto", "aegis128l", &ptls_minicrypto_aegis128l, &ptls_minicrypto_sha256, 1}, + {"minicrypto", "aegis256", &ptls_minicrypto_aegis256, &ptls_minicrypto_sha384, 1}, +#endif #ifdef _WINDOWS {"ptlsbcrypt", "aes128gcm", &ptls_bcrypt_aes128gcm, &ptls_bcrypt_sha256, 1}, {"ptlsbcrypt", "aes256gcm", &ptls_bcrypt_aes256gcm, &ptls_bcrypt_sha384, 1}, From 958ed1a78727c8d5d29071f3e5b83cbbad79dbb9 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 9 Aug 2023 01:56:18 +0200 Subject: [PATCH 007/151] Introduce ptls_{openssl,minicrypto}_cipher_suites_all --- include/picotls/minicrypto.h | 1 + include/picotls/openssl.h | 8 ++++++++ lib/cifra.c | 20 ++++++++++++++------ lib/openssl.c | 30 ++++++++++++++++++++---------- t/cli.c | 6 +++++- t/minicrypto.c | 4 ++-- t/openssl.c | 2 +- 7 files changed, 51 insertions(+), 20 deletions(-) diff --git a/include/picotls/minicrypto.h b/include/picotls/minicrypto.h index 21f5c1c6f..ca3a31d9d 100644 --- a/include/picotls/minicrypto.h +++ b/include/picotls/minicrypto.h @@ -58,6 +58,7 @@ extern ptls_cipher_suite_t ptls_minicrypto_aegis128lsha256; extern ptls_cipher_suite_t ptls_minicrypto_aegis256sha384; #endif extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[]; +extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[]; typedef struct st_ptls_asn1_pkcs8_private_key_t { ptls_iovec_t vec; diff --git a/include/picotls/openssl.h b/include/picotls/openssl.h index e0761ed08..987b9b1f2 100644 --- a/include/picotls/openssl.h +++ b/include/picotls/openssl.h @@ -85,6 +85,7 @@ extern ptls_hash_algorithm_t ptls_openssl_sha512; extern ptls_cipher_suite_t ptls_openssl_aes128gcmsha256; extern ptls_cipher_suite_t ptls_openssl_aes256gcmsha384; extern ptls_cipher_suite_t *ptls_openssl_cipher_suites[]; +extern ptls_cipher_suite_t *ptls_openssl_cipher_suites_all[]; extern ptls_cipher_suite_t *ptls_openssl_tls12_cipher_suites[]; #if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 @@ -93,6 +94,13 @@ extern ptls_aead_algorithm_t ptls_openssl_chacha20poly1305; extern ptls_cipher_suite_t ptls_openssl_chacha20poly1305sha256; #endif +#ifdef PTLS_HAVE_AEGIS +extern ptls_aead_algorithm_t ptls_openssl_aegis128l; +extern ptls_aead_algorithm_t ptls_openssl_aegis256; +extern ptls_cipher_suite_t ptls_openssl_aegis128lsha256; +extern ptls_cipher_suite_t ptls_openssl_aegis256sha384; +#endif + extern ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_rsa_aes128gcmsha256; extern ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_ecdsa_aes128gcmsha256; extern ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_rsa_aes256gcmsha384; diff --git a/lib/cifra.c b/lib/cifra.c index 507014ef2..d51f2b703 100644 --- a/lib/cifra.c +++ b/lib/cifra.c @@ -24,15 +24,23 @@ #include "picotls/minicrypto.h" ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha384 (must be first) -#ifdef PTLS_HAVE_AEGIS - &ptls_minicrypto_aegis256sha384, -#endif &ptls_minicrypto_aes256gcmsha384, // ciphers used with sha256 -#ifdef PTLS_HAVE_AEGIS - &ptls_minicrypto_aegis128lsha256, -#endif &ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_chacha20poly1305sha256, NULL}; + +ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = {// ciphers used with sha384 (must be first) +#ifdef PTLS_HAVE_AEGIS + &ptls_minicrypto_aegis256sha384, +#endif + &ptls_minicrypto_aes256gcmsha384, + + // ciphers used with sha256 +#ifdef PTLS_HAVE_AEGIS + &ptls_minicrypto_aegis128lsha256, +#endif + &ptls_minicrypto_aes128gcmsha256, + &ptls_minicrypto_chacha20poly1305sha256, + NULL}; diff --git a/lib/openssl.c b/lib/openssl.c index daf1dbaaf..b03533909 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -2167,7 +2167,7 @@ ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_ecdsa_chacha20poly1305sha256 = { #if PTLS_HAVE_AEGIS -ptls_aead_algorithm_t ptls_libaegis_aegis128l = { +ptls_aead_algorithm_t ptls_openssl_aegis128l = { .name = "AEGIS-128L", .confidentiality_limit = PTLS_AEGIS128L_CONFIDENTIALITY_LIMIT, .integrity_limit = PTLS_AEGIS128L_INTEGRITY_LIMIT, @@ -2184,10 +2184,10 @@ ptls_aead_algorithm_t ptls_libaegis_aegis128l = { }; ptls_cipher_suite_t ptls_openssl_aegis128lsha256 = {.id = PTLS_CIPHER_SUITE_AEGIS128L_SHA256, .name = PTLS_CIPHER_SUITE_NAME_AEGIS128L_SHA256, - .aead = &ptls_libaegis_aegis128l, + .aead = &ptls_openssl_aegis128l, .hash = &ptls_openssl_sha256}; -ptls_aead_algorithm_t ptls_libaegis_aegis256 = { +ptls_aead_algorithm_t ptls_openssl_aegis256 = { .name = "AEGIS-256", .confidentiality_limit = PTLS_AEGIS256_CONFIDENTIALITY_LIMIT, .integrity_limit = PTLS_AEGIS256_INTEGRITY_LIMIT, @@ -2204,28 +2204,38 @@ ptls_aead_algorithm_t ptls_libaegis_aegis256 = { }; ptls_cipher_suite_t ptls_openssl_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384, .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384, - .aead = &ptls_libaegis_aegis256, + .aead = &ptls_openssl_aegis256, .hash = &ptls_openssl_sha384}; #endif ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = {// ciphers used with sha384 (must be first) -#if PTLS_HAVE_AEGIS - &ptls_openssl_aegis256sha384, -#endif &ptls_openssl_aes256gcmsha384, // ciphers used with sha256 -#if PTLS_HAVE_AEGIS - &ptls_openssl_aegis128lsha256, -#endif &ptls_openssl_aes128gcmsha256, #if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 &ptls_openssl_chacha20poly1305sha256, #endif NULL}; +ptls_cipher_suite_t *ptls_openssl_cipher_suites_all[] = {// ciphers used with sha384 (must be first) +#if PTLS_HAVE_AEGIS + &ptls_openssl_aegis256sha384, +#endif + &ptls_openssl_aes256gcmsha384, + + // ciphers used with sha256 +#if PTLS_HAVE_AEGIS + &ptls_openssl_aegis128lsha256, +#endif + &ptls_openssl_aes128gcmsha256, +#if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 + &ptls_openssl_chacha20poly1305sha256, +#endif + NULL}; + ptls_cipher_suite_t *ptls_openssl_tls12_cipher_suites[] = {&ptls_openssl_tls12_ecdhe_rsa_aes128gcmsha256, &ptls_openssl_tls12_ecdhe_ecdsa_aes128gcmsha256, &ptls_openssl_tls12_ecdhe_rsa_aes256gcmsha384, diff --git a/t/cli.c b/t/cli.c index ef3c1ed81..e5d1473d9 100644 --- a/t/cli.c +++ b/t/cli.c @@ -558,6 +558,10 @@ int main(int argc, char **argv) #if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 MATCH(chacha20poly1305sha256); #endif +#if PTLS_HAVE_AEGIS + MATCH(aegis128lsha256); + MATCH(aegis256sha384); +#endif #undef MATCH if (cipher_suites[i] == NULL) { fprintf(stderr, "unknown cipher-suite: %s\n", optarg); @@ -635,7 +639,7 @@ int main(int argc, char **argv) if (cipher_suites[0] == NULL) { size_t i; for (i = 0; ptls_openssl_cipher_suites[i] != NULL; ++i) - cipher_suites[i] = ptls_openssl_cipher_suites[i]; + cipher_suites[i] = ptls_openssl_cipher_suites_all[i]; } if (argc != 2) { fprintf(stderr, "missing host and port\n"); diff --git a/t/minicrypto.c b/t/minicrypto.c index 17a05d26f..cf49ce811 100644 --- a/t/minicrypto.c +++ b/t/minicrypto.c @@ -64,7 +64,7 @@ static void test_secp256r1_sign(void) static void test_hrr(void) { ptls_key_exchange_algorithm_t *client_keyex[] = {&ptls_minicrypto_x25519, &ptls_minicrypto_secp256r1, NULL}; - ptls_context_t client_ctx = {ptls_minicrypto_random_bytes, &ptls_get_time, client_keyex, ptls_minicrypto_cipher_suites}; + ptls_context_t client_ctx = {ptls_minicrypto_random_bytes, &ptls_get_time, client_keyex, ptls_minicrypto_cipher_suites_all}; ptls_t *client, *server; ptls_buffer_t cbuf, sbuf, decbuf; uint8_t cbuf_small[16384], sbuf_small[16384], decbuf_small[16384]; @@ -153,7 +153,7 @@ int main(int argc, char **argv) ptls_context_t ctxbuf = {ptls_minicrypto_random_bytes, &ptls_get_time, ptls_minicrypto_key_exchanges, - ptls_minicrypto_cipher_suites, + ptls_minicrypto_cipher_suites_all, {&cert, 1}, {{NULL}}, NULL, diff --git a/t/openssl.c b/t/openssl.c index 9daec5e61..b3188ff0a 100644 --- a/t/openssl.c +++ b/t/openssl.c @@ -555,7 +555,7 @@ int main(int argc, char **argv) ptls_context_t openssl_ctx = {.random_bytes = ptls_openssl_random_bytes, .get_time = &ptls_get_time, .key_exchanges = ptls_openssl_key_exchanges, - .cipher_suites = ptls_openssl_cipher_suites, + .cipher_suites = ptls_openssl_cipher_suites_all, .tls12_cipher_suites = ptls_openssl_tls12_cipher_suites, .certificates = {&cert, 1}, .ech = {.client = {.ciphers = ptls_openssl_hpke_cipher_suites, .kems = ptls_openssl_hpke_kems}, From b0bbfa77cc0feb96989a4ff37887e181035d306d Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 9 Aug 2023 09:13:25 +0900 Subject: [PATCH 008/151] [cli] we are copying from `ptls_openssl_cipher_suites` --- t/cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/cli.c b/t/cli.c index e5d1473d9..79070859c 100644 --- a/t/cli.c +++ b/t/cli.c @@ -639,7 +639,7 @@ int main(int argc, char **argv) if (cipher_suites[0] == NULL) { size_t i; for (i = 0; ptls_openssl_cipher_suites[i] != NULL; ++i) - cipher_suites[i] = ptls_openssl_cipher_suites_all[i]; + cipher_suites[i] = ptls_openssl_cipher_suites[i]; } if (argc != 2) { fprintf(stderr, "missing host and port\n"); From 8d0d79873f06c5c21b099c601d3939d32c2280ec Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 9 Aug 2023 09:20:41 +0900 Subject: [PATCH 009/151] [cli] regonize aegis in `-y` option; the option now recognizes RFC8446-style names --- t/cli.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/t/cli.c b/t/cli.c index 79070859c..99969ca27 100644 --- a/t/cli.c +++ b/t/cli.c @@ -547,26 +547,28 @@ int main(int argc, char **argv) request_key_update = 1; break; case 'y': { - size_t i; - for (i = 0; cipher_suites[i] != NULL; ++i) - ; -#define MATCH(name) \ - if (cipher_suites[i] == NULL && strcasecmp(optarg, #name) == 0) \ - cipher_suites[i] = &ptls_openssl_##name - MATCH(aes128gcmsha256); - MATCH(aes256gcmsha384); -#if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 - MATCH(chacha20poly1305sha256); -#endif -#if PTLS_HAVE_AEGIS - MATCH(aegis128lsha256); - MATCH(aegis256sha384); -#endif -#undef MATCH - if (cipher_suites[i] == NULL) { - fprintf(stderr, "unknown cipher-suite: %s\n", optarg); + /* find the cipher suite to be added from `ptls_openssl_cipher_suites_all` */ + ptls_cipher_suite_t *added = NULL; + for (size_t i = 0; ptls_openssl_cipher_suites_all[i] != NULL; ++i) { + if (strcasecmp(ptls_openssl_cipher_suites_all[i]->name, optarg) == 0) { + added = ptls_openssl_cipher_suites_all[i]; + break; + } + } + if (added == NULL) { + fprintf(stderr, "unknown cipher-suite: %s, use the name defined in RFC 8446, e.g., \"%s\"\n", optarg, + ptls_openssl_cipher_suites[0]->name); exit(1); } + + size_t slot; + for (slot = 0; cipher_suites[slot] != NULL; ++slot) { + if (cipher_suites[slot]->id == added->id) { + fprintf(stderr, "cipher-suite %s is already in list\n", added->name); + exit(1); + } + } + cipher_suites[slot] = added; } break; case 'h': usage(argv[0]); From 62527e496bc5fde9a709df3e1c9b00f831b5fc71 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 10 Aug 2023 10:02:59 +0900 Subject: [PATCH 010/151] in help, display the list of cipher-suites supported --- t/cli.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/t/cli.c b/t/cli.c index 99969ca27..20f2b55bd 100644 --- a/t/cli.c +++ b/t/cli.c @@ -386,8 +386,7 @@ static void usage(const char *cmd) " -u update the traffic key when handshake is complete\n" " -v verify peer using the default certificates\n" " -V CA-root-file verify peer using the CA Root File\n" - " -y cipher-suite cipher-suite to be used, e.g., aes128gcmsha256 (default:\n" - " all)\n" + " -y cipher-suite cipher-suite to be used\n" " -h print this help\n" "\n" "Supported named groups: secp256r1" @@ -411,8 +410,15 @@ static void usage(const char *cmd) #if PTLS_OPENSSL_HAVE_ED25519 ", ed25519" #endif - "\n\n", + "\n", cmd); + printf("Supported cipher suites:"); + for (size_t i = 0; ptls_openssl_cipher_suites_all[i] != NULL; ++i) { + if (i != 0) + printf(","); + printf(" %s", ptls_openssl_cipher_suites_all[i]->name); + } + printf("\n\n"); } int main(int argc, char **argv) @@ -556,8 +562,7 @@ int main(int argc, char **argv) } } if (added == NULL) { - fprintf(stderr, "unknown cipher-suite: %s, use the name defined in RFC 8446, e.g., \"%s\"\n", optarg, - ptls_openssl_cipher_suites[0]->name); + fprintf(stderr, "unknown cipher-suite: %s, see -h for list of cipher-suites supported\n", optarg); exit(1); } From 2d4f75744dcacbf1f640b092f081092d99a21141 Mon Sep 17 00:00:00 2001 From: Frederik Deweerdt Date: Tue, 22 Aug 2023 15:10:45 -0700 Subject: [PATCH 011/151] only update the traffic key when a key schedule is available (ie. in 1.3 only) --- lib/picotls.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index 906bc97f6..d03bf408a 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5885,9 +5885,11 @@ int ptls_send(ptls_t *tls, ptls_buffer_t *sendbuf, const void *input, size_t inl assert(tls->traffic_protection.enc.aead != NULL); /* "For AES-GCM, up to 2^24.5 full-size records (about 24 million) may be encrypted on a given connection while keeping a - * safety margin of approximately 2^-57 for Authenticated Encryption (AE) security." (RFC 8446 section 5.5) + * safety margin of approximately 2^-57 for Authenticated Encryption (AE) security." (RFC 8446 section 5.5). + * + * Key updates do not happen with tls 1.2, check `key_schedule` to see if we are using tls/1.3 */ - if (tls->traffic_protection.enc.seq >= 16777216) + if (tls->traffic_protection.enc.seq >= 16777216 && tls->key_schedule != NULL) tls->needs_key_update = 1; if (tls->needs_key_update) { From 52c2797104dbb2aafd847664f1935676ac9b32c1 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 10:39:27 -0700 Subject: [PATCH 012/151] Incorporate mbedtls in cmake --- CMakeLists.txt | 20 ++ cmake/FindMbedTLS.cmake | 15 + include/picotls/ptls_mbedtls.h | 42 +++ lib/ptls_mbedtls.c | 586 +++++++++++++++++++++++++++++++++ t/ptls_mbedtls.c | 349 ++++++++++++++++++++ 5 files changed, 1012 insertions(+) create mode 100644 cmake/FindMbedTLS.cmake create mode 100644 include/picotls/ptls_mbedtls.h create mode 100644 lib/ptls_mbedtls.c create mode 100644 t/ptls_mbedtls.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 42692a520..bec745882 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ IF (WITH_FUSION) MESSAGE(STATUS "Enabling 'fusion' AES-GCM engine") ENDIF () OPTION(WITH_AEGIS "enable AEGIS (requires libaegis)" ${WITH_AEGIS}) +OPTION(WITH_MBEDTLS "enable MBEDTLS" ${WITH_MBEDTLS}) SET(CMAKE_C_FLAGS "-std=c99 -Wall -O2 -g ${CC_WARNING_FLAGS} ${CMAKE_C_FLAGS}") INCLUDE_DIRECTORIES( @@ -199,6 +200,25 @@ IF (WITH_FUSION) LIST(APPEND PTLSBENCH_LIBS picotls-fusion) ENDIF () +IF (WITH_MBEDTLS) + FIND_PACKAGE(MbedTLS) + IF (NOT MbedTLS) + MESSAGE (FATAL_ERROR "MbedTLS not found") + ELSE () + message(STATUS "mbedtls/include: ${MBEDTLS_INCLUDE_DIRS}") + message(STATUS "mbedtls libraries: ${MBEDTLS_LIBRARIES}") + INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) + ADD_LIBRARY(picotls-mbedtls lib/ptls_mbedtls.c) + ADD_EXECUTABLE(test-mbedtls.t + deps/picotest/picotest.c + lib/picotls.c + t/ptls_mbedtls.c) + TARGET_LINK_LIBRARIES(test-mbedtls.t + picotls-minicrypto picotls-mbedtls + ${MBEDTLS_LIBRARIES}) + ENDIF() +ENDIF () + ADD_EXECUTABLE(ptlsbench t/ptlsbench.c) SET_TARGET_PROPERTIES(ptlsbench PROPERTIES COMPILE_FLAGS "-DPTLS_MEMORY_DEBUG=1") TARGET_LINK_LIBRARIES(ptlsbench ${PTLSBENCH_LIBS}) diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake new file mode 100644 index 000000000..2bddc77e1 --- /dev/null +++ b/cmake/FindMbedTLS.cmake @@ -0,0 +1,15 @@ +# - Try to find MbedTLS +# set(MBEDTLS_LIBRARY mbedtls) +# set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_SOURCE_DIR}/include) +find_path(MBEDTLS_INCLUDE_DIRS + NAMES mbedtls/build_info.h psa/crypto.h + HINTS ${MBEDTLS_PREFIX}/include/ + ${CMAKE_SOURCE_DIR}/../mbedtls/include/ + ${CMAKE_BINARY_DIR}/../mbedtls/include/ + ../mbedtls/include/ ) + +set(MBEDTLS_HINTS ${MBEDTLS_PREFIX}/build ${CMAKE_BINARY_DIR}/../mbedtls/build ../mbedtls/build) + +find_library(MBEDTLS_LIBRARY mbedtls HINTS ${MBEDTLS_HINTS}) + +mark_as_advanced(MBEDTLS_LIBRARY MBEDTLS_INCLUDE_DIRS) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h new file mode 100644 index 000000000..18f67370e --- /dev/null +++ b/include/picotls/ptls_mbedtls.h @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2023, Christian Huitema +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ +#ifndef picotls_mbedtls_h +#define picotls_mbedtls_h + +#ifdef __cplusplus +extern "C" { +#endif +#include "picotls.h" + +extern ptls_hash_algorithm_t ptls_mbedtls_sha256; + +extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; + +extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; + +#ifdef __cplusplus +} +#endif +#endif /* picotls_mbedtls_h */ \ No newline at end of file diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c new file mode 100644 index 000000000..6c2bf82b6 --- /dev/null +++ b/lib/ptls_mbedtls.c @@ -0,0 +1,586 @@ +#ifdef _WINDOWS +#include "wincompat.h" +#endif + +#include +#include +#include +#include +#include "mbedtls/build_info.h" +#include "psa/crypto.h" +#include "psa/crypto_struct.h" +#include "mbedtls/sha256.h" +#include "mbedtls/aes.h" + +/* Definitions for hash algorithms. +* In Picotls, these are described by the stucture +* ptls_hash_algorithm_t, which include the function +* pointer for creation of the hash context. +* +* The structure contains a function pointer to the +* "create" function that creates a hash operation, +* which itself contains three function pointers: +* +* void (*update)(struct st_ptls_hash_context_t *ctx, const void *src, size_t len); +* void (*final)(struct st_ptls_hash_context_t *ctx, void *md, ptls_hash_final_mode_t mode); +* struct st_ptls_hash_context_t *(*clone_)(struct st_ptls_hash_context_t *src); +* +* TODO: develop shim for other hash methods besides SHA256 +*/ + +typedef struct st_ptls_mbedtls_sha256_ctx_t { + ptls_hash_context_t super; + mbedtls_sha256_context mctx; +} ptls_mbedtls_sha256_ctx_t; + +static void ptls_mbedtls_sha256_update(struct st_ptls_hash_context_t* _ctx, const void* src, size_t len) +{ + ptls_mbedtls_sha256_ctx_t* ctx = (ptls_mbedtls_sha256_ctx_t*)_ctx; + + (void)mbedtls_sha256_update(&ctx->mctx, (const uint8_t*)src, len); +} + +static void ptls_mbedtls_sha256_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode); + +static struct st_ptls_hash_context_t* ptls_mbedtls_sha256_clone(struct st_ptls_hash_context_t* _src) +{ + ptls_mbedtls_sha256_ctx_t* ctx = (ptls_mbedtls_sha256_ctx_t*)malloc(sizeof(ptls_mbedtls_sha256_ctx_t)); + + if (ctx != NULL) { + ptls_mbedtls_sha256_ctx_t* src = (ptls_mbedtls_sha256_ctx_t*)_src; + memset(&ctx->mctx, 0, sizeof(mbedtls_sha256_context)); + ctx->super.clone_ = ptls_mbedtls_sha256_clone; + ctx->super.update = ptls_mbedtls_sha256_update; + ctx->super.final = ptls_mbedtls_sha256_final; + mbedtls_sha256_clone(&ctx->mctx, &src->mctx); + } + return (ptls_hash_context_t*)ctx; +} + +static void ptls_mbedtls_sha256_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode) +{ + ptls_mbedtls_sha256_ctx_t* ctx = (ptls_mbedtls_sha256_ctx_t*)_ctx; + + if (mode == PTLS_HASH_FINAL_MODE_SNAPSHOT) { + struct st_ptls_hash_context_t* cloned = ptls_mbedtls_sha256_clone(_ctx); + + if (cloned != NULL) { + ptls_mbedtls_sha256_final(cloned, md, PTLS_HASH_FINAL_MODE_FREE); + } + } else { + if (md != NULL) { + (void)mbedtls_sha256_finish(&ctx->mctx, (uint8_t*)md); + } + + if (mode == PTLS_HASH_FINAL_MODE_FREE) { + mbedtls_sha256_free(&ctx->mctx); + free(ctx); + } + else { + /* if mode = reset, reset the context */ + mbedtls_sha256_init(&ctx->mctx); + mbedtls_sha256_starts(&ctx->mctx, 0 /* is224 = 0 */); + } + } +} + +ptls_hash_context_t* ptls_mbedtls_sha256_create(void) +{ + ptls_mbedtls_sha256_ctx_t* ctx = (ptls_mbedtls_sha256_ctx_t*)malloc(sizeof(ptls_mbedtls_sha256_ctx_t)); + + if (ctx != NULL) { + memset(&ctx->mctx, 0, sizeof(mbedtls_sha256_context)); + ctx->super.clone_ = ptls_mbedtls_sha256_clone; + ctx->super.update = ptls_mbedtls_sha256_update; + ctx->super.final = ptls_mbedtls_sha256_final; + if (mbedtls_sha256_starts(&ctx->mctx, 0 /* is224 = 0 */) != 0) { + free(ctx); + ctx = NULL; + } + } + return (ptls_hash_context_t*)ctx; +} + +ptls_hash_algorithm_t ptls_mbedtls_sha256 = {"sha256", PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, ptls_mbedtls_sha256_create, +PTLS_ZERO_DIGEST_SHA256}; + + +/* definitions for symmetric crypto algorithms. +* Each algorithm (ECB or CTR) is represented by an "algorithm" +* entry in which the 'setup" function is used to initialize +* The "setup" function creates an object of type +* ptls_cipher_context_t, with three function pointers: +* +* void (*do_dispose)(struct st_ptls_cipher_context_t *ctx); +* void (*do_init)(struct st_ptls_cipher_context_t *ctx, const void *iv); +* void (*do_transform)(struct st_ptls_cipher_context_t *ctx, void *output, const void *input, size_t len); +* +* "do_init" sets the IV value. In CTR mode, this is the nonce value, which +* will be incremented after each block. In CTR mode, this also sets the +* "stream block". +* + */ +struct ptls_mbedtls_symmetric_param_t { + uint8_t iv[PTLS_MAX_IV_SIZE]; + uint8_t *key_object; + int is_enc; +}; + +struct st_ptls_mbedtls_aes_context_t { + ptls_cipher_context_t super; + mbedtls_aes_context aes_ctx; + uint8_t nonce_counter[16]; + uint8_t stream_block[16]; + int is_enc; /* MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT */ +}; + +static void ptls_mbedtls_aes_ctr_init(ptls_cipher_context_t *_ctx, const void *iv) +{ + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + + if (iv == NULL) { + memset(ctx->nonce_counter, 0, 16); + } + else { + memcpy(ctx->nonce_counter, iv, 16); + } + memset(ctx->stream_block, 0, 16); +} + +static void ptls_mbedtls_aes_ecb_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) +{ + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + + /* Call the encryption */ + if (mbedtls_aes_crypt_ecb(&ctx->aes_ctx, ctx->is_enc, (const uint8_t*)input, (uint8_t*)output) != 0) { + memset(output, 0, len); + } +} + +static void ptls_mbedtls_aes_ctr_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) +{ + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + size_t nc_off = 0; + + if (mbedtls_aes_crypt_ctr(&ctx->aes_ctx, len, &nc_off, ctx->nonce_counter, ctx->stream_block, + (const uint8_t*)input, (uint8_t*)output) != 0) { + memset(output, 0, len); + } +} + +static void ptls_mbedtls_aes_ctr_dispose(ptls_cipher_context_t *_ctx) +{ + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + mbedtls_aes_free(&ctx->aes_ctx); +} + +static int ptls_mbedtls_cipher_setup_crypto_aes(ptls_cipher_context_t* _ctx, int is_enc, const void* key, unsigned int keybits) +{ + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + int ret = 0; + + memset(ctx->nonce_counter, 0, 16); + memset(ctx->stream_block, 0, 16); + + ctx->super.do_dispose = ptls_mbedtls_aes_ctr_dispose; + ctx->super.do_init = ptls_mbedtls_aes_ctr_init; + ctx->super.do_transform = NULL; + + mbedtls_aes_init(&ctx->aes_ctx); + if (is_enc) { + ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key, keybits); + ctx->is_enc = MBEDTLS_AES_ENCRYPT; + } + else { + ret = mbedtls_aes_setkey_dec(&ctx->aes_ctx, key, keybits); + ctx->is_enc = MBEDTLS_AES_DECRYPT; + } + + return ret; + +} + +static int ptls_mbedtls_cipher_setup_crypto_aes128_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +{ + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + int ret = ptls_mbedtls_cipher_setup_crypto_aes(_ctx, is_enc, key, 128); + + if (ret == 0) { + ctx->super.do_transform = ptls_mbedtls_aes_ecb_transform; + } + + return ret; +} + +static int ptls_mbedtls_cipher_setup_crypto_aes128_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +{ +#ifdef _WINDOWS + UNREFERENCED_PARAMETER(is_enc); +#endif + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + int ret = ptls_mbedtls_cipher_setup_crypto_aes(_ctx, 1, key, 128); /* No difference between CTR encrypt and decrypt */ + + if (ret == 0) { + ctx->super.do_transform = ptls_mbedtls_aes_ctr_transform; + } + + return ret; +} + + +static int ptls_mbedtls_cipher_setup_crypto_aes256_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +{ + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + int ret = ptls_mbedtls_cipher_setup_crypto_aes(_ctx, is_enc, key, 256); + + if (ret == 0) { + ctx->super.do_transform = ptls_mbedtls_aes_ecb_transform; + } + + return ret; +} + +static int ptls_mbedtls_cipher_setup_crypto_aes256_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +{ +#ifdef _WINDOWS + UNREFERENCED_PARAMETER(is_enc); +#endif + struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + int ret = ptls_mbedtls_cipher_setup_crypto_aes(_ctx, 1, key, 256); /* No difference between CTR encrypt and decrypt */ + + if (ret == 0) { + ctx->super.do_transform = ptls_mbedtls_aes_ctr_transform; + } + + return ret; +} + +ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { + "AES128-ECB", + PTLS_AES128_KEY_SIZE, + PTLS_AES_BLOCK_SIZE, + 0 /* iv size */, + sizeof(struct st_ptls_mbedtls_aes_context_t), + ptls_mbedtls_cipher_setup_crypto_aes128_ecb}; + +ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = {"AES256-ECB", +PTLS_AES256_KEY_SIZE, +PTLS_AES_BLOCK_SIZE, +0 /* iv size */, +sizeof(struct st_ptls_mbedtls_aes_context_t), +ptls_mbedtls_cipher_setup_crypto_aes256_ecb}; + +ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = {"AES128-CTR", +PTLS_AES128_KEY_SIZE, +PTLS_AES_BLOCK_SIZE, +0 /* iv size */, +sizeof(struct st_ptls_mbedtls_aes_context_t), +ptls_mbedtls_cipher_setup_crypto_aes128_ctr}; + +ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = {"AES256-CTR", +PTLS_AES256_KEY_SIZE, +PTLS_AES_BLOCK_SIZE, +0 /* iv size */, +sizeof(struct st_ptls_mbedtls_aes_context_t), +ptls_mbedtls_cipher_setup_crypto_aes256_ctr}; + +/* Definitions of AEAD algorithms. +* +* For the picotls API, AEAD algorithms are created by calling: +* +* ptls_aead_context_t *ptls_aead_new(ptls_aead_algorithm_t *aead, +* ptls_hash_algorithm_t *hash, int is_enc, const void *secret, +* const char *label_prefix) +* That procedure will allocate memory and create keys, and then call +* a provider specific function: +* +* if (aead->setup_crypto(ctx, is_enc, key, iv) != 0) { +* free(ctx); +* return NULL; +* } +* +* The function will finish completing the aead structure, perform +* initialization, and then document the function pointers: +* +* ctx->super.dispose_crypto: release all resourc +* ctx->super.do_get_iv: return IV +* ctx->super.do_set_iv: set IV value +* ctx->super.do_decrypt: decrypt function +* ctx->super.do_encrypt_init: start encrypting one message +* ctx->super.do_encrypt_update: feed more ciphertext to descriptor +* ctx->super.do_encrypt_final: finalize encryption, including AEAD checksum +* ctx->super.do_encrypt: single shot variant of init/update/final +* ctx->super.do_encrypt_v: scatter gather version of do encrypt +* +* The aead context also documents the underlying "ECB" and "CTR" modes. +* In QUIC, these are used for PN encryption. +* +* TODO: declare other lagorithms besides AES128_GCM +*/ + +struct ptls_mbedtls_aead_param_t { + uint8_t static_iv[PTLS_MAX_IV_SIZE]; + psa_algorithm_t alg; + psa_key_id_t key; + psa_aead_operation_t op; + size_t extra_bytes; + int is_op_in_progress; +}; + +struct ptls_mbedtls_aead_context_t { + struct st_ptls_aead_context_t super; + struct ptls_mbedtls_aead_param_t mctx; +}; + +void ptls_mbedtls_aead_dispose_crypto(struct st_ptls_aead_context_t* _ctx) +{ + struct ptls_mbedtls_aead_context_t* ctx = + (struct ptls_mbedtls_aead_context_t*)_ctx; + if (ctx->mctx.is_op_in_progress) { + psa_aead_abort(&ctx->mctx.op); + ctx->mctx.is_op_in_progress = 0; + } + psa_destroy_key(ctx->mctx.key); +} + + +static void ptls_mbedtls_aead_get_iv(ptls_aead_context_t *_ctx, void *iv) +{ + struct ptls_mbedtls_aead_context_t* ctx = + (struct ptls_mbedtls_aead_context_t*)_ctx; + + memcpy(iv, ctx->mctx.static_iv, ctx->super.algo->iv_size); +} + +static void ptls_mbedtls_aead_set_iv(ptls_aead_context_t *_ctx, const void *iv) +{ + struct ptls_mbedtls_aead_context_t* ctx = + (struct ptls_mbedtls_aead_context_t*)_ctx; + + memcpy(ctx->mctx.static_iv, iv, ctx->super.algo->iv_size); +} + +void ptls_mbedtls_aead_do_encrypt_init(struct st_ptls_aead_context_t* _ctx, uint64_t seq, const void* aad, size_t aadlen) +{ + struct ptls_mbedtls_aead_context_t* ctx = + (struct ptls_mbedtls_aead_context_t*)_ctx; + psa_status_t status; + + if (ctx->mctx.is_op_in_progress) { + psa_aead_abort(&ctx->mctx.op); /* required on errors, harmless on success */ + ctx->mctx.is_op_in_progress = 0; + } + + ctx->mctx.is_op_in_progress = 1; + memset(&ctx->mctx.op, 0, sizeof(ctx->mctx.op)); + + status = psa_aead_encrypt_setup(&ctx->mctx.op, ctx->mctx.key, ctx->mctx.alg); + + if (status == PSA_SUCCESS) { + /* set the nonce. */ + uint8_t iv[PTLS_MAX_IV_SIZE]; + ptls_aead__build_iv(ctx->super.algo, iv, ctx->mctx.static_iv, seq); + status = psa_aead_set_nonce(&ctx->mctx.op, iv, ctx->super.algo->iv_size); + } + + if (status == PSA_SUCCESS) { + status = psa_aead_update_ad(&ctx->mctx.op, aad, aadlen); + } + + if (status != PSA_SUCCESS) { + psa_aead_abort(&ctx->mctx.op); /* required on errors, harmless on success */ + ctx->mctx.is_op_in_progress = 0; + } +} + +size_t ptls_mbedtls_aead_do_encrypt_update(struct st_ptls_aead_context_t* _ctx, void* output, const void* input, size_t inlen) +{ + size_t olen = 0; + struct ptls_mbedtls_aead_context_t* ctx = + (struct ptls_mbedtls_aead_context_t*)_ctx; + + if (ctx->mctx.is_op_in_progress) { + size_t available = inlen + ctx->mctx.extra_bytes; + psa_status_t status = psa_aead_update(&ctx->mctx.op, input, inlen, (uint8_t *)output, available + ctx->super.algo->tag_size, &olen); + + if (status == PSA_SUCCESS) { + if (olen < available) { + ctx->mctx.extra_bytes = available - olen; + } + else { + ctx->mctx.extra_bytes = 0; + } + } + else { + psa_aead_abort(&ctx->mctx.op); /* required on errors */ + ctx->mctx.is_op_in_progress = 0; + } + } + + return olen; +} + +size_t ptls_mbedtls_aead_do_encrypt_final(struct st_ptls_aead_context_t* _ctx, void* output) +{ + size_t olen = 0; + struct ptls_mbedtls_aead_context_t* ctx = + (struct ptls_mbedtls_aead_context_t*)_ctx; + + if (ctx->mctx.is_op_in_progress) { + unsigned char tag[PSA_AEAD_TAG_MAX_SIZE]; + size_t olen_tag = 0; + size_t available = ctx->mctx.extra_bytes; + uint8_t* p = (uint8_t*)output; + psa_status_t status = psa_aead_finish(&ctx->mctx.op, p, available + ctx->super.algo->tag_size, &olen, + tag, sizeof(tag), &olen_tag); + + if (status == PSA_SUCCESS) { + p += olen; + memcpy(p, tag, ctx->super.algo->tag_size); + olen += ctx->super.algo->tag_size; + } + else { + psa_aead_abort(&ctx->mctx.op); /* required on errors */ + } + ctx->mctx.is_op_in_progress = 0; + } + + return(olen); +} + +void ptls_mbedtls_aead_do_encrypt_v(struct st_ptls_aead_context_t* _ctx, void* output, ptls_iovec_t* input, size_t incnt, uint64_t seq, + const void* aad, size_t aadlen) +{ + unsigned char* p = (uint8_t*)output; + + ptls_mbedtls_aead_do_encrypt_init(_ctx, seq, aad, aadlen); + + for (size_t i = 0; i < incnt; i++) { + p += ptls_mbedtls_aead_do_encrypt_update(_ctx, p, input[i].base, input[i].len); + } + + (void)ptls_mbedtls_aead_do_encrypt_final(_ctx, p); +} + +void ptls_mbedtls_aead_do_encrypt(struct st_ptls_aead_context_t* _ctx, void* output, const void* input, size_t inlen, uint64_t seq, + const void* aad, size_t aadlen, ptls_aead_supplementary_encryption_t* supp) +{ + ptls_iovec_t in_v; + in_v.base = (uint8_t*)input; + in_v.len = inlen; + + ptls_mbedtls_aead_do_encrypt_v(_ctx, output, &in_v, 1, seq, aad, aadlen); +} + +size_t ptls_mbedtls_aead_do_decrypt(struct st_ptls_aead_context_t* _ctx, void* output, const void* input, size_t inlen, uint64_t seq, + const void* aad, size_t aadlen) +{ + size_t o_len = 0; + uint8_t iv[PTLS_MAX_IV_SIZE]; + struct ptls_mbedtls_aead_context_t* ctx = + (struct ptls_mbedtls_aead_context_t*)_ctx; + psa_status_t status; + /* set the nonce. */ + ptls_aead__build_iv(ctx->super.algo, iv, ctx->mctx.static_iv, seq); + + status = psa_aead_decrypt(ctx->mctx.key, ctx->mctx.alg, iv, ctx->super.algo->iv_size, (uint8_t*)aad, aadlen, + (uint8_t*)input, inlen, (uint8_t*)output, inlen, &o_len); + if (status != PSA_SUCCESS) { + o_len = inlen + 1; + } + return o_len; +} + +static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) +{ + int ret = 0; + struct ptls_mbedtls_aead_context_t* ctx = + (struct ptls_mbedtls_aead_context_t*)_ctx; + size_t key_bits; + psa_key_type_t key_type; + + /* set mbed specific context to NULL, just to be sure */ + memset(&ctx->mctx, 0, sizeof(struct ptls_mbedtls_aead_param_t)); + + /* deduce the PSA algorithm from the name */ + if (strcmp(ctx->super.algo->name, "AES128-GCM") == 0) { + ctx->mctx.alg = PSA_ALG_GCM; + key_bits = 128; + key_type = PSA_KEY_TYPE_AES; + } else if (strcmp(ctx->super.algo->name, "AES256-GCM") == 0) { + ctx->mctx.alg = PSA_ALG_GCM; + key_bits = 256; + key_type = PSA_KEY_TYPE_AES; + } else if (strcmp(ctx->super.algo->name, "AES128-GCM_8") == 0) { + ctx->mctx.alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 8); + key_bits = 128; + key_type = PSA_KEY_TYPE_AES; + } else if (strcmp(ctx->super.algo->name, "CHACHA20-POLY1305") == 0) { + ctx->mctx.alg = PSA_ALG_CHACHA20_POLY1305; + key_bits = 256; + key_type = PSA_KEY_TYPE_CHACHA20; + } else { + ret = PTLS_ERROR_LIBRARY; + } + + /* Initialize the key attributes */ + if (ret == 0) { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_usage_flags(&attributes, + (is_enc)?PSA_KEY_USAGE_ENCRYPT:PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, ctx->mctx.alg); + psa_set_key_type(&attributes, key_type); + psa_set_key_bits(&attributes, key_bits); + /* Import key */ + if (psa_import_key(&attributes, key_bytes, key_bits / 8, + &ctx->mctx.key) != PSA_SUCCESS) { + ret = PTLS_ERROR_LIBRARY; + } + } + + if (ret == 0) { + /* Store the static IV */ + if (ctx->super.algo->iv_size > PTLS_MAX_IV_SIZE) { + ret = PTLS_ERROR_LIBRARY; + } + else { + memcpy(ctx->mctx.static_iv, iv, ctx->super.algo->iv_size); + ctx->mctx.is_op_in_progress = 0; + } + } + + /* set the pointers to the individual functions */ + if (ret == 0) { + if (is_enc) { + ctx->super.do_encrypt_init = ptls_mbedtls_aead_do_encrypt_init; + ctx->super.do_encrypt_update = ptls_mbedtls_aead_do_encrypt_update; + ctx->super.do_encrypt_final = ptls_mbedtls_aead_do_encrypt_final; + ctx->super.do_encrypt = ptls_mbedtls_aead_do_encrypt; + ctx->super.do_encrypt_v = ptls_mbedtls_aead_do_encrypt_v; + } + else { + ctx->super.do_decrypt = ptls_mbedtls_aead_do_decrypt; + } + ctx->super.dispose_crypto = ptls_mbedtls_aead_dispose_crypto; + ctx->super.do_get_iv = ptls_mbedtls_aead_get_iv; + ctx->super.do_set_iv = ptls_mbedtls_aead_set_iv; + } + + return ret; +} + +ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = { + "AES128-GCM", + PTLS_AESGCM_CONFIDENTIALITY_LIMIT, + PTLS_AESGCM_INTEGRITY_LIMIT, + &ptls_mbedtls_aes128ecb, + &ptls_mbedtls_aes128ctr, + PTLS_AES128_KEY_SIZE, + PTLS_AESGCM_IV_SIZE, + PTLS_AESGCM_TAG_SIZE, + {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + ptls_mbedtls_aead_setup_crypto +}; diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c new file mode 100644 index 000000000..2b14e92f6 --- /dev/null +++ b/t/ptls_mbedtls.c @@ -0,0 +1,349 @@ +/* +* Copyright (c) 2023, Christian Huitema +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifdef _WINDOWS +#include "wincompat.h" +#endif + +#include +#include +#include +#include +#include +#include "mbedtls/build_info.h" +#include "psa/crypto.h" +#include "psa/crypto_struct.h" +#include "picotls/ptls_mbedtls.h" +#include "picotls/minicrypto.h" +#include "../deps/picotest/picotest.h" + +static int hash_trial(ptls_hash_algorithm_t* algo, const uint8_t* input, size_t len1, size_t len2, uint8_t* final_hash) +{ + int ret = 0; + ptls_hash_context_t* hash_ctx = algo->create(); + + hash_ctx->update(hash_ctx, input, len1); + if (len2 > 0) { + hash_ctx->update(hash_ctx, input + len1, len2); + } + hash_ctx->final(hash_ctx, final_hash, PTLS_HASH_FINAL_MODE_FREE); + + return ret; +} + +static int hash_reset_trial(ptls_hash_algorithm_t* algo, const uint8_t* input, size_t len1, size_t len2, + uint8_t* hash1, uint8_t* hash2) +{ + int ret = 0; + ptls_hash_context_t* hash_ctx = algo->create(); + + hash_ctx->update(hash_ctx, input, len1); + hash_ctx->final(hash_ctx, hash1, PTLS_HASH_FINAL_MODE_RESET); + hash_ctx->update(hash_ctx, input + len1, len2); + hash_ctx->final(hash_ctx, hash2, PTLS_HASH_FINAL_MODE_FREE); + + return ret; +} + +static int test_hash(ptls_hash_algorithm_t* algo, ptls_hash_algorithm_t* ref) +{ + int ret = 0; + uint8_t input[1234]; + uint8_t final_hash[32]; + uint8_t final_ref[32]; + uint8_t hash1[32], hash2[32], href1[32], href2[32]; + + memset(input, 0xba, sizeof(input)); + + ret = hash_trial(algo, input, sizeof(input), 0, final_hash); + if (ret == 0) { + ret = hash_trial(ref, input, sizeof(input), 0, final_ref); + } + if (ret == 0) { + if (memcmp(final_hash, final_ref, ref->digest_size) != 0) { + ret = -1; + } + } + if (ret == 0) { + ret = hash_trial(algo, input, sizeof(input) - 17, 17, final_hash); + } + if (ret == 0) { + if (memcmp(final_hash, final_ref, ref->digest_size) != 0) { + ret = -1; + } + } + + if (ret == 0) { + ret = hash_reset_trial(algo, input, sizeof(input) - 126, 126, hash1, hash2); + } + if (ret == 0) { + ret = hash_reset_trial(ref, input, sizeof(input) - 126, 126, href1, href2); + } + if (ret == 0) { + if (memcmp(hash1, href1, ref->digest_size) != 0) { + ret = -1; + } + else if (memcmp(hash2, href2, ref->digest_size) != 0) { + ret = -1; + } + } + + return ret; +} + +static int cipher_trial(ptls_cipher_algorithm_t * cipher, const uint8_t * key, const uint8_t * iv, int is_enc, const uint8_t * v_in, uint8_t * v_out1, uint8_t * v_out2, size_t len) +{ + int ret = 0; + ptls_cipher_context_t* test_cipher = ptls_cipher_new(cipher, is_enc, key); + if (test_cipher == NULL) { + ret = -1; + } else { + if (test_cipher->do_init != NULL) { + ptls_cipher_init(test_cipher, iv); + } + ptls_cipher_encrypt(test_cipher, v_out1, v_in, len); + if (test_cipher->do_init != NULL) { + ptls_cipher_init(test_cipher, iv); + } + ptls_cipher_encrypt(test_cipher, v_out2, v_out1, len); + ptls_cipher_free(test_cipher); + } + + return ret; +} + +static int test_cipher(ptls_cipher_algorithm_t * cipher, ptls_cipher_algorithm_t * cipher_ref) +{ + uint8_t key[32]; + uint8_t iv[16]; + uint8_t v_in[16]; + uint8_t v_out_1a[16], v_out_2a[16], v_out_1b[16], v_out_2b[16], v_out_1d[16], v_out_2d[16]; + int ret = 0; + + /* Set initial values */ + memset(key, 0x55, sizeof(key)); + memset(iv, 0x33, sizeof(iv)); + memset(v_in, 0xaa, sizeof(v_in)); + + /* Encryption test */ + ret = cipher_trial(cipher, key, iv, 1, v_in, v_out_1a, v_out_2a, 16); + if (ret == 0) { + ret = cipher_trial(cipher_ref, key, iv, 1, v_in, v_out_1b, v_out_2b, 16); + } + if (ret == 0) { + if (memcmp(v_out_1a, v_out_1b, 16) != 0) { + ret = -1; + } + else if (memcmp(v_out_2a, v_out_2b, 16) != 0) { + ret = -1; + } + } + /* decryption test */ + if (ret == 0) { + ret = cipher_trial(cipher, key, iv, 0, v_out_2a, v_out_1d, v_out_2d, 16); + } + if (ret == 0) { + if (memcmp(v_out_1a, v_out_1d, 16) != 0) { + ret = -1; + } + else if (memcmp(v_out_2d, v_in, 16) != 0) { + ret = -1; + } + } + + return ret; +} + +static int label_test(ptls_hash_algorithm_t * hash, uint8_t * v_out, size_t o_len, const uint8_t * secret, + char const * label, char const * label_prefix) +{ + uint8_t h_val_v[32]; + ptls_iovec_t h_val = { 0 }; + ptls_iovec_t s_vec = { 0 }; + s_vec.base = (uint8_t *)secret; + s_vec.len = 32; + h_val.base = h_val_v; + h_val.len = 32; + memset(h_val_v, 0, sizeof(h_val_v)); + + ptls_hkdf_expand_label(hash, v_out, o_len, s_vec, label, h_val, label_prefix); + return 0; +} + +static int test_label(ptls_hash_algorithm_t* hash, ptls_hash_algorithm_t* ref) +{ + int ret = 0; + uint8_t v_out[16], v_ref[16]; + uint8_t secret[32]; + char const* label = "label"; + char const* label_prefix = "label_prefix"; + memset(secret, 0x5e, sizeof(secret)); + + ret = label_test(hash, v_out, 16, secret, label, label_prefix); + + if (ret == 0) { + ret = label_test(ref, v_ref, 16, secret, label, label_prefix); + } + + if (ret == 0 && memcmp(v_out, v_ref, 16) != 0) { + ret = -1; + } + + return ret; +} + +static int aead_trial(ptls_aead_algorithm_t * algo, ptls_hash_algorithm_t * hash, const uint8_t * secret, int is_enc, + const uint8_t * v_in, size_t len, uint8_t * aad, size_t aad_len, uint64_t seq, uint8_t * v_out, size_t * o_len) +{ + int ret = 0; + ptls_aead_context_t* aead = ptls_aead_new(algo, hash, is_enc, secret, "test_aead"); + + if (aead == NULL) { + ret = -1; + } + else{ + if (is_enc) { + *o_len = ptls_aead_encrypt(aead, v_out, v_in, len, seq, aad, aad_len); + if (*o_len != len + algo->tag_size) { + ret = -1; + } + } + else { + *o_len = ptls_aead_decrypt(aead, v_out, v_in, len, seq, aad, aad_len); + if (*o_len != len - algo->tag_size) { + ret = -1; + } + } + ptls_aead_free(aead); + } + return ret; +} + +static int test_aead(ptls_aead_algorithm_t* algo, ptls_hash_algorithm_t* hash, ptls_aead_algorithm_t* ref, ptls_hash_algorithm_t* hash_ref) +{ + uint8_t secret[32]; + uint8_t v_in[1234]; + uint8_t aad[17]; + uint8_t v_out_a[1250], v_out_b[1250], v_out_r[1250]; + size_t olen_a, olen_b, olen_r; + uint64_t seq = 12345; + int ret = 0; + + memset(secret, 0x58, sizeof(secret)); + memset(v_in, 0x12, sizeof(v_in)); + memset(aad, 0xaa, sizeof(aad)); + + ret = aead_trial(algo, hash, secret, 1, v_in, sizeof(v_in), aad, sizeof(aad), seq, v_out_a, &olen_a); + if (ret == 0) { + ret = aead_trial(ref, hash_ref, secret, 1, v_in, sizeof(v_in), aad, sizeof(aad), seq, v_out_b, &olen_b); + } + if (ret == 0 && (olen_a != olen_b || memcmp(v_out_a, v_out_b, olen_a) != 0)) { + ret = -1; + } + if (ret == 0) { + ret = aead_trial(ref, hash_ref, secret, 0, v_out_a, olen_a, aad, sizeof(aad), seq, v_out_r, &olen_r); + } + if (ret == 0 && (olen_r != sizeof(v_in) || memcmp(v_in, v_out_r, sizeof(v_in)) != 0)) { + ret = -1; + } + return ret; +} + +static void test_sha256(void) +{ + if (test_hash(&ptls_mbedtls_sha256, &ptls_minicrypto_sha256) != 0) { + ok(!"fail"); + return; + } + ok(!!"success"); +} + +static void test_label_sha256(void) +{ + if (test_label(&ptls_mbedtls_sha256, &ptls_minicrypto_sha256) != 0) { + ok(!"fail"); + return; + } + ok(!!"success"); +} + +static void test_aes128ecb(void) +{ + if (test_cipher(ptls_mbedtls_aes128ecb, ptls_minicrypto_aes128ecb) != 0) { + ok(!"fail"); + } + ok(!!"success"); +} + +static void test_aes128ctr(void) +{ + if (test_cipher(ptls_mbedtls_aes128ctr, ptls_minicrypto_aes128ctr) != 0) { + ok(!"fail"); + } + ok(!!"success"); +} + +static void test_aes256ecb(void) +{ + if (test_cipher(ptls_mbedtls_aes256ecb, ptls_minicrypto_aes256ecb) != 0) { + ok(!"fail"); + } + ok(!!"success"); +} + +static void test_aes256ctr(void) +{ + if (test_cipher(ptls_mbedtls_aes256ctr, ptls_minicrypto_aes2568ctr) != 0) { + ok(!"fail"); + } + ok(!!"success"); +} + +static void test_aes128gcm_sha256(void) +{ + if (test_aead(&ptls_mbedtls_aes128gcm, &ptls_mbedtls_sha256, &ptls_minicrypto_aes128gcm, &ptls_minicrypto_sha256) != 0) { + ok(!"fail"); + } + ok(!!"success"); +} + +int main(int argc, char **argv) +{ + /* Initialize the PSA crypto library. */ + if ((status = psa_crypto_init()) != PSA_SUCCESS) { + note("psa_crypto_init fails."); + return done_testing(); + } + /* Series of test to check consistency between wrapped mbedtls and minicrypto */ + subtest("sha256", test_sha256); + subtest("label_sha256", test_label_sha256); + subtest("aes128ecb", test_aes128ecb); + subtest("aes128ctr", test_aes128ctr); + subtest("aes256ecb", test_aes256ecb); + subtest("aes256ctr", test_aes256ctr); + subtest("aes128gcm_sha256", test_aes128gcm_sha256); + + /* Deinitialize the PSA crypto library. */ + mbedtls_psa_crypto_free(); + + return done_testing(); +} From aac44919b23ff7f1ce691fa67e7f8fff1af76907 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 10:47:47 -0700 Subject: [PATCH 013/151] include find mbedtls --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index bec745882..9be3421a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ ENDIF () FIND_PACKAGE(PkgConfig REQUIRED) INCLUDE(cmake/dtrace-utils.cmake) INCLUDE(cmake/boringssl-adjust.cmake) +INCLUDE(cmake/FindMbedTLS.cmake) CHECK_DTRACE(${PROJECT_SOURCE_DIR}/picotls-probes.d) IF ((CMAKE_SIZEOF_VOID_P EQUAL 8) AND From e5cd27567b21d62d2da16b0d0add08b0e98a6a9f Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 10:49:47 -0700 Subject: [PATCH 014/151] Add cmake module path --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9be3421a7..3200ae609 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ ENDIF () FIND_PACKAGE(PkgConfig REQUIRED) INCLUDE(cmake/dtrace-utils.cmake) INCLUDE(cmake/boringssl-adjust.cmake) -INCLUDE(cmake/FindMbedTLS.cmake) +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") CHECK_DTRACE(${PROJECT_SOURCE_DIR}/picotls-probes.d) IF ((CMAKE_SIZEOF_VOID_P EQUAL 8) AND From be89606ccfe7923e9903786f405abd21ba43775d Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 11:04:36 -0700 Subject: [PATCH 015/151] Add find package --- cmake/FindMbedTLS.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake index 2bddc77e1..ae3d4e80e 100644 --- a/cmake/FindMbedTLS.cmake +++ b/cmake/FindMbedTLS.cmake @@ -11,5 +11,11 @@ find_path(MBEDTLS_INCLUDE_DIRS set(MBEDTLS_HINTS ${MBEDTLS_PREFIX}/build ${CMAKE_BINARY_DIR}/../mbedtls/build ../mbedtls/build) find_library(MBEDTLS_LIBRARY mbedtls HINTS ${MBEDTLS_HINTS}) +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set PTLS_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(MbedTLS REQUIRED_VARS + MBEDTLS_LIBRARY + MBEDTLS_INCLUDE_DIRS) mark_as_advanced(MBEDTLS_LIBRARY MBEDTLS_INCLUDE_DIRS) From 4a01610e8233d06b3f16ae3a781b3627b4b5d56d Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 11:14:21 -0700 Subject: [PATCH 016/151] Update MbedTLS find --- cmake/FindMbedTLS.cmake | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake index ae3d4e80e..b2638f911 100644 --- a/cmake/FindMbedTLS.cmake +++ b/cmake/FindMbedTLS.cmake @@ -8,14 +8,24 @@ find_path(MBEDTLS_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/../mbedtls/include/ ../mbedtls/include/ ) -set(MBEDTLS_HINTS ${MBEDTLS_PREFIX}/build ${CMAKE_BINARY_DIR}/../mbedtls/build ../mbedtls/build) + + +set(MBEDTLS_HINTS ${MBEDTLS_PREFIX}/build/library + ${CMAKE_BINARY_DIR}/../mbedtls/build/library + ../mbedtls/build/library ../mbedtls/library) find_library(MBEDTLS_LIBRARY mbedtls HINTS ${MBEDTLS_HINTS}) +find_library(MBEDTLS_CRYPTO mbedcrypto HINTS ${MBEDTLS_HINTS}) +find_library(MBEDTLS_X509 mbedx509 HINTS ${MBEDTLS_HINTS}) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set PTLS_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(MbedTLS REQUIRED_VARS MBEDTLS_LIBRARY + MBEDTLS_CRYPTO + MBEDTLS_X509 MBEDTLS_INCLUDE_DIRS) - -mark_as_advanced(MBEDTLS_LIBRARY MBEDTLS_INCLUDE_DIRS) + +if(MbedTLS_FOUND) + set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDTLS_CRYPTO} ${MBEDTLS_X509}) + mark_as_advanced(MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) From 7a53976a314c042f302ead80918ba6ffed788a7a Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 11:22:40 -0700 Subject: [PATCH 017/151] Add missing endif --- cmake/FindMbedTLS.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake index b2638f911..e71403ea0 100644 --- a/cmake/FindMbedTLS.cmake +++ b/cmake/FindMbedTLS.cmake @@ -26,6 +26,7 @@ find_package_handle_standard_args(MbedTLS REQUIRED_VARS MBEDTLS_X509 MBEDTLS_INCLUDE_DIRS) -if(MbedTLS_FOUND) +if (MbedTLS_FOUND) set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDTLS_CRYPTO} ${MBEDTLS_X509}) mark_as_advanced(MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) +endif () \ No newline at end of file From 5aac49fca43f37a236c64f66352cf73fc6013560 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 11:25:06 -0700 Subject: [PATCH 018/151] Check mbedtls found condition --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3200ae609..571d7a544 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,7 +203,7 @@ ENDIF () IF (WITH_MBEDTLS) FIND_PACKAGE(MbedTLS) - IF (NOT MbedTLS) + IF (NOT MbedTLS_FOUND) MESSAGE (FATAL_ERROR "MbedTLS not found") ELSE () message(STATUS "mbedtls/include: ${MBEDTLS_INCLUDE_DIRS}") From bbb502ee882c1857de820f73384dd7e46f204cf5 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 11:26:13 -0700 Subject: [PATCH 019/151] Struggling with Found condition. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 571d7a544..9bce67ce7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,9 +203,7 @@ ENDIF () IF (WITH_MBEDTLS) FIND_PACKAGE(MbedTLS) - IF (NOT MbedTLS_FOUND) - MESSAGE (FATAL_ERROR "MbedTLS not found") - ELSE () + IF (MbedTLS_FOUND) message(STATUS "mbedtls/include: ${MBEDTLS_INCLUDE_DIRS}") message(STATUS "mbedtls libraries: ${MBEDTLS_LIBRARIES}") INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) @@ -217,6 +215,8 @@ IF (WITH_MBEDTLS) TARGET_LINK_LIBRARIES(test-mbedtls.t picotls-minicrypto picotls-mbedtls ${MBEDTLS_LIBRARIES}) + ELSE () + MESSAGE (FATAL_ERROR "MbedTLS not found") ENDIF() ENDIF () From 262d334610d1daa3e7621f41ac40e3338b3d6a1f Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 11:30:25 -0700 Subject: [PATCH 020/151] Remove error condition for debug --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bce67ce7..b44a64125 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,7 +203,7 @@ ENDIF () IF (WITH_MBEDTLS) FIND_PACKAGE(MbedTLS) - IF (MbedTLS_FOUND) + # IF (MbedTLS_FOUND) message(STATUS "mbedtls/include: ${MBEDTLS_INCLUDE_DIRS}") message(STATUS "mbedtls libraries: ${MBEDTLS_LIBRARIES}") INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) @@ -215,9 +215,9 @@ IF (WITH_MBEDTLS) TARGET_LINK_LIBRARIES(test-mbedtls.t picotls-minicrypto picotls-mbedtls ${MBEDTLS_LIBRARIES}) - ELSE () - MESSAGE (FATAL_ERROR "MbedTLS not found") - ENDIF() + #ELSE () + # MESSAGE (FATAL_ERROR "MbedTLS not found") + #ENDIF() ENDIF () ADD_EXECUTABLE(ptlsbench t/ptlsbench.c) From 17dee3e2a7d5683b86251b7a86876983161e38bb Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 11:34:16 -0700 Subject: [PATCH 021/151] update mbedtls test --- t/ptls_mbedtls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 2b14e92f6..fd2b4f198 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -288,7 +288,7 @@ static void test_label_sha256(void) static void test_aes128ecb(void) { - if (test_cipher(ptls_mbedtls_aes128ecb, ptls_minicrypto_aes128ecb) != 0) { + if (test_cipher(&ptls_mbedtls_aes128ecb, &ptls_minicrypto_aes128ecb) != 0) { ok(!"fail"); } ok(!!"success"); @@ -296,7 +296,7 @@ static void test_aes128ecb(void) static void test_aes128ctr(void) { - if (test_cipher(ptls_mbedtls_aes128ctr, ptls_minicrypto_aes128ctr) != 0) { + if (test_cipher(&ptls_mbedtls_aes128ctr, &ptls_minicrypto_aes128ctr) != 0) { ok(!"fail"); } ok(!!"success"); @@ -304,7 +304,7 @@ static void test_aes128ctr(void) static void test_aes256ecb(void) { - if (test_cipher(ptls_mbedtls_aes256ecb, ptls_minicrypto_aes256ecb) != 0) { + if (test_cipher(&ptls_mbedtls_aes256ecb, &ptls_minicrypto_aes256ecb) != 0) { ok(!"fail"); } ok(!!"success"); @@ -312,7 +312,7 @@ static void test_aes256ecb(void) static void test_aes256ctr(void) { - if (test_cipher(ptls_mbedtls_aes256ctr, ptls_minicrypto_aes2568ctr) != 0) { + if (test_cipher(&ptls_mbedtls_aes256ctr, &ptls_minicrypto_aes2568ctr) != 0) { ok(!"fail"); } ok(!!"success"); @@ -329,7 +329,7 @@ static void test_aes128gcm_sha256(void) int main(int argc, char **argv) { /* Initialize the PSA crypto library. */ - if ((status = psa_crypto_init()) != PSA_SUCCESS) { + if (psa_crypto_init() != PSA_SUCCESS) { note("psa_crypto_init fails."); return done_testing(); } From 3d5657ce87fd080f56d6c4b8add0cb7b73605b2d Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 11:35:17 -0700 Subject: [PATCH 022/151] fix typo --- t/ptls_mbedtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index fd2b4f198..a4f9eeef3 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -312,7 +312,7 @@ static void test_aes256ecb(void) static void test_aes256ctr(void) { - if (test_cipher(&ptls_mbedtls_aes256ctr, &ptls_minicrypto_aes2568ctr) != 0) { + if (test_cipher(&ptls_mbedtls_aes256ctr, &ptls_minicrypto_aes256ctr) != 0) { ok(!"fail"); } ok(!!"success"); From b29d4b4b0fdcd7603a5667c66d6d865baf2ddeac Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 13:01:14 -0700 Subject: [PATCH 023/151] Add github action for mbedtls --- .github/workflows/mbedtls.yml | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/mbedtls.yml diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml new file mode 100644 index 000000000..298d2351c --- /dev/null +++ b/.github/workflows/mbedtls.yml @@ -0,0 +1,36 @@ +--- +name: "MbedTLS-test" + +on: [push, pull_request] + +jobs: + mbedtls: + name: MbedTLS-test + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + submodules: 'recursive' + + - name: Installing MbedTLS + run: | + git clone https://github.com/Mbed-TLS/mbedtls + cd mbedtls + cmake --build . + cd build + make + cd ../.. + + - name: Compile picotls + run: | + cmake "-DWITH_MBEDTLS=ON" . + make + + - name: Run test + run: | + ./test-mbedtls.t \ No newline at end of file From ce37fa0ceacfc6151991a8d9826978617cf86db7 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 14:08:10 -0700 Subject: [PATCH 024/151] Debugging github action. --- .github/workflows/mbedtls.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml index 298d2351c..fb2b23cd9 100644 --- a/.github/workflows/mbedtls.yml +++ b/.github/workflows/mbedtls.yml @@ -21,6 +21,8 @@ jobs: run: | git clone https://github.com/Mbed-TLS/mbedtls cd mbedtls + echo "cloned mbedtls" + ls cmake --build . cd build make From 684008cb9b4a3a79d14233c25c977fc892d8a351 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 14:13:42 -0700 Subject: [PATCH 025/151] Decomposing the build steps --- .github/workflows/mbedtls.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml index fb2b23cd9..8f8109ea0 100644 --- a/.github/workflows/mbedtls.yml +++ b/.github/workflows/mbedtls.yml @@ -22,9 +22,10 @@ jobs: git clone https://github.com/Mbed-TLS/mbedtls cd mbedtls echo "cloned mbedtls" - ls - cmake --build . + mkdir build cd build + cmake -S .. . + echo "cmake done" make cd ../.. From 8bca3c2c405324cc8bcb7442e4e1c8bc2b50f8fd Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 14:21:20 -0700 Subject: [PATCH 026/151] More debugging of github action --- .github/workflows/mbedtls.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml index 8f8109ea0..dc7ebcadc 100644 --- a/.github/workflows/mbedtls.yml +++ b/.github/workflows/mbedtls.yml @@ -27,10 +27,14 @@ jobs: cmake -S .. . echo "cmake done" make + echo "compiled MbedTLS" + pwd cd ../.. - name: Compile picotls run: | + echo "building picotls with MbedTLS" + pwd cmake "-DWITH_MBEDTLS=ON" . make From 12bd1944add05fc1674fbbc97524724bf3380aed Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 14:29:59 -0700 Subject: [PATCH 027/151] Build mbedtls parallel to picotls --- .github/workflows/mbedtls.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml index dc7ebcadc..93d14de85 100644 --- a/.github/workflows/mbedtls.yml +++ b/.github/workflows/mbedtls.yml @@ -19,6 +19,7 @@ jobs: - name: Installing MbedTLS run: | + cd .. git clone https://github.com/Mbed-TLS/mbedtls cd mbedtls echo "cloned mbedtls" @@ -29,7 +30,7 @@ jobs: make echo "compiled MbedTLS" pwd - cd ../.. + cd ../../picotls - name: Compile picotls run: | From ccecfa5dfa5d87b02cfc9a2fadbfef7aaccf7b27 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 17:12:59 -0700 Subject: [PATCH 028/151] Add sha512 and sha384 --- include/picotls/ptls_mbedtls.h | 4 ++ lib/ptls_mbedtls.c | 107 ++++++++++++++++++++++++++++++++- t/ptls_mbedtls.c | 32 +++++++++- 3 files changed, 139 insertions(+), 4 deletions(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index 18f67370e..0ab1d9f2f 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -28,6 +28,10 @@ extern "C" { #include "picotls.h" extern ptls_hash_algorithm_t ptls_mbedtls_sha256; +extern ptls_hash_algorithm_t ptls_mbedtls_sha512; +#if defined(MBEDTLS_SHA384_C) +extern ptls_hash_algorithm_t ptls_mbedtls_sha384; +#endif extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 6c2bf82b6..e19a09f52 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -6,10 +6,12 @@ #include #include #include +#include "mbedtls/config.h" #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "psa/crypto_struct.h" #include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" #include "mbedtls/aes.h" /* Definitions for hash algorithms. @@ -25,7 +27,6 @@ * void (*final)(struct st_ptls_hash_context_t *ctx, void *md, ptls_hash_final_mode_t mode); * struct st_ptls_hash_context_t *(*clone_)(struct st_ptls_hash_context_t *src); * -* TODO: develop shim for other hash methods besides SHA256 */ typedef struct st_ptls_mbedtls_sha256_ctx_t { @@ -105,6 +106,110 @@ ptls_hash_algorithm_t ptls_mbedtls_sha256 = {"sha256", PTLS_SHA256_BLOCK_SIZE, P PTLS_ZERO_DIGEST_SHA256}; +/* SHA 512 follows the same general architecture as SHA 256. + * The SHA 384 module is using the same code, with an option to + * deliver a shorter hash. + */ + + +typedef struct st_ptls_mbedtls_sha512_ctx_t { + ptls_hash_context_t super; + mbedtls_sha512_context mctx; +} ptls_mbedtls_sha512_ctx_t; + +static void ptls_mbedtls_sha512_update(struct st_ptls_hash_context_t* _ctx, const void* src, size_t len) +{ + ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)_ctx; + + (void)mbedtls_sha512_update(&ctx->mctx, (const uint8_t*)src, len); +} + +static void ptls_mbedtls_sha512_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode); + +static struct st_ptls_hash_context_t* ptls_mbedtls_sha512_clone(struct st_ptls_hash_context_t* _src) +{ + ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)malloc(sizeof(ptls_mbedtls_sha512_ctx_t)); + + if (ctx != NULL) { + ptls_mbedtls_sha512_ctx_t* src = (ptls_mbedtls_sha512_ctx_t*)_src; + memset(&ctx->mctx, 0, sizeof(mbedtls_sha512_context)); + ctx->super.clone_ = ptls_mbedtls_sha512_clone; + ctx->super.update = ptls_mbedtls_sha512_update; + ctx->super.final = ptls_mbedtls_sha512_final; + mbedtls_sha512_clone(&ctx->mctx, &src->mctx); + } + return (ptls_hash_context_t*)ctx; +} + +static void ptls_mbedtls_sha512_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode) +{ + ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)_ctx; + + if (mode == PTLS_HASH_FINAL_MODE_SNAPSHOT) { + struct st_ptls_hash_context_t* cloned = ptls_mbedtls_sha512_clone(_ctx); + + if (cloned != NULL) { + ptls_mbedtls_sha512_final(cloned, md, PTLS_HASH_FINAL_MODE_FREE); + } + } else { + if (md != NULL) { + (void)mbedtls_sha512_finish(&ctx->mctx, (uint8_t*)md); + } + + if (mode == PTLS_HASH_FINAL_MODE_FREE) { + mbedtls_sha512_free(&ctx->mctx); + free(ctx); + } + else { + /* if mode = reset, reset the context */ + mbedtls_sha512_init(&ctx->mctx); + mbedtls_sha512_starts(&ctx->mctx, 0 /* is224 = 0 */); + } + } +} + +ptls_hash_context_t* ptls_mbedtls_sha512_create(void) +{ + ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)malloc(sizeof(ptls_mbedtls_sha512_ctx_t)); + + if (ctx != NULL) { + memset(&ctx->mctx, 0, sizeof(mbedtls_sha512_context)); + ctx->super.clone_ = ptls_mbedtls_sha512_clone; + ctx->super.update = ptls_mbedtls_sha512_update; + ctx->super.final = ptls_mbedtls_sha512_final; + if (mbedtls_sha512_starts(&ctx->mctx, 0 /* is384 = 0 */) != 0) { + free(ctx); + ctx = NULL; + } + } + return (ptls_hash_context_t*)ctx; +} + +ptls_hash_algorithm_t ptls_mbedtls_sha512 = {"SHA512", PTLS_SHA512_BLOCK_SIZE, PTLS_SHA512_DIGEST_SIZE, ptls_mbedtls_sha512_create, +PTLS_ZERO_DIGEST_SHA512}; + +#if defined(MBEDTLS_SHA384_C) +ptls_hash_context_t* ptls_mbedtls_sha384_create(void) +{ + ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)malloc(sizeof(ptls_mbedtls_sha512_ctx_t)); + + if (ctx != NULL) { + memset(&ctx->mctx, 0, sizeof(mbedtls_sha512_context)); + ctx->super.clone_ = ptls_mbedtls_sha512_clone; + ctx->super.update = ptls_mbedtls_sha512_update; + ctx->super.final = ptls_mbedtls_sha512_final; + if (mbedtls_sha512_starts(&ctx->mctx, 1 /* is384 = 1 */) != 0) { + free(ctx); + ctx = NULL; + } + } + return (ptls_hash_context_t*)ctx; +} + +ptls_hash_algorithm_t ptls_mbedtls_sha512 = {"SHA384", PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, ptls_mbedtls_sha384_create, +PTLS_ZERO_DIGEST_SHA384}; +#endif /* MBEDTLS_SHA384_C */ + /* definitions for symmetric crypto algorithms. * Each algorithm (ECB or CTR) is represented by an "algorithm" * entry in which the 'setup" function is used to initialize diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index a4f9eeef3..643204cc3 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -29,6 +29,7 @@ #include #include #include +#include "mbedtls/config.h" #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "psa/crypto_struct.h" @@ -68,9 +69,9 @@ static int test_hash(ptls_hash_algorithm_t* algo, ptls_hash_algorithm_t* ref) { int ret = 0; uint8_t input[1234]; - uint8_t final_hash[32]; - uint8_t final_ref[32]; - uint8_t hash1[32], hash2[32], href1[32], href2[32]; + uint8_t final_hash[64]; + uint8_t final_ref[64]; + uint8_t hash1[64], hash2[64], href1[64], href2[64]; memset(input, 0xba, sizeof(input)); @@ -277,6 +278,27 @@ static void test_sha256(void) ok(!!"success"); } +static void test_sha512(void) +{ + if (test_hash(&ptls_mbedtls_sha512, &ptls_minicrypto_sha512) != 0) { + ok(!"fail"); + return; + } + ok(!!"success"); +} + + +#if defined(MBEDTLS_SHA384_C) +static void test_sha384(void) +{ + if (test_hash(&ptls_mbedtls_sha384, &ptls_minicrypto_sha384) != 0) { + ok(!"fail"); + return; + } + ok(!!"success"); +} +#endif + static void test_label_sha256(void) { if (test_label(&ptls_mbedtls_sha256, &ptls_minicrypto_sha256) != 0) { @@ -335,6 +357,10 @@ int main(int argc, char **argv) } /* Series of test to check consistency between wrapped mbedtls and minicrypto */ subtest("sha256", test_sha256); + subtest("sha512", test_sha256); +#if defined(MBEDTLS_SHA384_C) + subtest("sha384", test_sha256); +#endif subtest("label_sha256", test_label_sha256); subtest("aes128ecb", test_aes128ecb); subtest("aes128ctr", test_aes128ctr); From bc75434991922794088a80e9f496e9689080f2a1 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 17:57:31 -0700 Subject: [PATCH 029/151] Update sha384 definitions and test --- lib/ptls_mbedtls.c | 36 ++++++++++++++++-------------------- t/ptls_mbedtls.c | 15 ++------------- 2 files changed, 18 insertions(+), 33 deletions(-) diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index e19a09f52..26f2aa731 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -6,7 +6,7 @@ #include #include #include -#include "mbedtls/config.h" +#include "mbedtls/mbedtls_config.h" #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "psa/crypto_struct.h" @@ -115,6 +115,7 @@ PTLS_ZERO_DIGEST_SHA256}; typedef struct st_ptls_mbedtls_sha512_ctx_t { ptls_hash_context_t super; mbedtls_sha512_context mctx; + int is384; } ptls_mbedtls_sha512_ctx_t; static void ptls_mbedtls_sha512_update(struct st_ptls_hash_context_t* _ctx, const void* src, size_t len) @@ -163,12 +164,12 @@ static void ptls_mbedtls_sha512_final(struct st_ptls_hash_context_t* _ctx, void* else { /* if mode = reset, reset the context */ mbedtls_sha512_init(&ctx->mctx); - mbedtls_sha512_starts(&ctx->mctx, 0 /* is224 = 0 */); + mbedtls_sha512_starts(&ctx->mctx, ctx->is384); } } } -ptls_hash_context_t* ptls_mbedtls_sha512_create(void) +ptls_hash_context_t* ptls_mbedtls_sha512_384_create(int is384) { ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)malloc(sizeof(ptls_mbedtls_sha512_ctx_t)); @@ -177,7 +178,9 @@ ptls_hash_context_t* ptls_mbedtls_sha512_create(void) ctx->super.clone_ = ptls_mbedtls_sha512_clone; ctx->super.update = ptls_mbedtls_sha512_update; ctx->super.final = ptls_mbedtls_sha512_final; - if (mbedtls_sha512_starts(&ctx->mctx, 0 /* is384 = 0 */) != 0) { + ctx->is384 = is384; + + if (mbedtls_sha512_starts(&ctx->mctx, is384) != 0) { free(ctx); ctx = NULL; } @@ -185,28 +188,22 @@ ptls_hash_context_t* ptls_mbedtls_sha512_create(void) return (ptls_hash_context_t*)ctx; } +ptls_hash_context_t* ptls_mbedtls_sha512_create(void) +{ + return ptls_mbedtls_sha512_384_create(0); +} + ptls_hash_algorithm_t ptls_mbedtls_sha512 = {"SHA512", PTLS_SHA512_BLOCK_SIZE, PTLS_SHA512_DIGEST_SIZE, ptls_mbedtls_sha512_create, PTLS_ZERO_DIGEST_SHA512}; #if defined(MBEDTLS_SHA384_C) ptls_hash_context_t* ptls_mbedtls_sha384_create(void) { - ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)malloc(sizeof(ptls_mbedtls_sha512_ctx_t)); - - if (ctx != NULL) { - memset(&ctx->mctx, 0, sizeof(mbedtls_sha512_context)); - ctx->super.clone_ = ptls_mbedtls_sha512_clone; - ctx->super.update = ptls_mbedtls_sha512_update; - ctx->super.final = ptls_mbedtls_sha512_final; - if (mbedtls_sha512_starts(&ctx->mctx, 1 /* is384 = 1 */) != 0) { - free(ctx); - ctx = NULL; - } - } - return (ptls_hash_context_t*)ctx; + return ptls_mbedtls_sha512_384_create(1); } -ptls_hash_algorithm_t ptls_mbedtls_sha512 = {"SHA384", PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, ptls_mbedtls_sha384_create, +ptls_hash_algorithm_t ptls_mbedtls_sha384 = {"SHA384", PTLS_SHA384_BLOCK_SIZE, +PTLS_SHA384_DIGEST_SIZE, ptls_mbedtls_sha384_create, PTLS_ZERO_DIGEST_SHA384}; #endif /* MBEDTLS_SHA384_C */ @@ -332,7 +329,6 @@ static int ptls_mbedtls_cipher_setup_crypto_aes128_ctr(ptls_cipher_context_t *_c return ret; } - static int ptls_mbedtls_cipher_setup_crypto_aes256_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key) { struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; @@ -420,7 +416,7 @@ ptls_mbedtls_cipher_setup_crypto_aes256_ctr}; * The aead context also documents the underlying "ECB" and "CTR" modes. * In QUIC, these are used for PN encryption. * -* TODO: declare other lagorithms besides AES128_GCM +* TODO: declare other algorithms besides AES128_GCM */ struct ptls_mbedtls_aead_param_t { diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 643204cc3..59e6a228d 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -29,7 +29,7 @@ #include #include #include -#include "mbedtls/config.h" +#include "mbedtls/mbedtls_config.h" #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "psa/crypto_struct.h" @@ -278,16 +278,6 @@ static void test_sha256(void) ok(!!"success"); } -static void test_sha512(void) -{ - if (test_hash(&ptls_mbedtls_sha512, &ptls_minicrypto_sha512) != 0) { - ok(!"fail"); - return; - } - ok(!!"success"); -} - - #if defined(MBEDTLS_SHA384_C) static void test_sha384(void) { @@ -357,9 +347,8 @@ int main(int argc, char **argv) } /* Series of test to check consistency between wrapped mbedtls and minicrypto */ subtest("sha256", test_sha256); - subtest("sha512", test_sha256); #if defined(MBEDTLS_SHA384_C) - subtest("sha384", test_sha256); + subtest("sha384", test_sha384); #endif subtest("label_sha256", test_label_sha256); subtest("aes128ecb", test_aes128ecb); From 251d42b85b3d03ebd49bc18a312f3d19680f738e Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 19:51:35 -0700 Subject: [PATCH 030/151] Add aes256gcm --- include/picotls/ptls_mbedtls.h | 1 + lib/ptls_mbedtls.c | 16 ++++++++++++++++ t/ptls_mbedtls.c | 16 ++++++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index 0ab1d9f2f..f0a59ede9 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -39,6 +39,7 @@ extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; +extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; #ifdef __cplusplus } diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 26f2aa731..68a7971cc 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -685,3 +685,19 @@ ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = { sizeof(struct ptls_mbedtls_aead_context_t), ptls_mbedtls_aead_setup_crypto }; + +ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = { + "AES256-GCM", + PTLS_AESGCM_CONFIDENTIALITY_LIMIT, + PTLS_AESGCM_INTEGRITY_LIMIT, + &ptls_mbedtls_aes256ecb, + &ptls_mbedtls_aes256ctr, + PTLS_AES256_KEY_SIZE, + PTLS_AESGCM_IV_SIZE, + PTLS_AESGCM_TAG_SIZE, + {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + ptls_mbedtls_aead_setup_crypto +}; diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 59e6a228d..3d91979a7 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -241,7 +241,7 @@ static int aead_trial(ptls_aead_algorithm_t * algo, ptls_hash_algorithm_t * hash static int test_aead(ptls_aead_algorithm_t* algo, ptls_hash_algorithm_t* hash, ptls_aead_algorithm_t* ref, ptls_hash_algorithm_t* hash_ref) { - uint8_t secret[32]; + uint8_t secret[64]; uint8_t v_in[1234]; uint8_t aad[17]; uint8_t v_out_a[1250], v_out_b[1250], v_out_r[1250]; @@ -338,6 +338,16 @@ static void test_aes128gcm_sha256(void) ok(!!"success"); } +#if defined(MBEDTLS_SHA384_C) +static void test_aes256gcm_sha384(void) +{ + if (test_aead(&ptls_mbedtls_aes256gcm, &ptls_mbedtls_sha384, &ptls_minicrypto_aes256gcm, &ptls_minicrypto_sha384) != 0) { + ok(!"fail"); + } + ok(!!"success"); +} +#endif + int main(int argc, char **argv) { /* Initialize the PSA crypto library. */ @@ -356,7 +366,9 @@ int main(int argc, char **argv) subtest("aes256ecb", test_aes256ecb); subtest("aes256ctr", test_aes256ctr); subtest("aes128gcm_sha256", test_aes128gcm_sha256); - +#if defined(MBEDTLS_SHA384_C) + subtest("aes256gcm_sha384", test_aes256gcm_sha384); +#endif /* Deinitialize the PSA crypto library. */ mbedtls_psa_crypto_free(); From ca4b8cbd3e8550943490caff92e80845cf659096 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 21:02:01 -0700 Subject: [PATCH 031/151] Add chachapoly --- lib/ptls_mbedtls.c | 79 ++++++++++++++++++++++++++++++++++++++++++---- t/ptls_mbedtls.c | 8 +++++ 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 68a7971cc..4f4c4eba1 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -13,6 +13,7 @@ #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" #include "mbedtls/aes.h" +#include "mbedtls/chacha20.h" /* Definitions for hash algorithms. * In Picotls, these are described by the stucture @@ -222,11 +223,6 @@ PTLS_ZERO_DIGEST_SHA384}; * "stream block". * */ -struct ptls_mbedtls_symmetric_param_t { - uint8_t iv[PTLS_MAX_IV_SIZE]; - uint8_t *key_object; - int is_enc; -}; struct st_ptls_mbedtls_aes_context_t { ptls_cipher_context_t super; @@ -385,6 +381,59 @@ PTLS_AES_BLOCK_SIZE, sizeof(struct st_ptls_mbedtls_aes_context_t), ptls_mbedtls_cipher_setup_crypto_aes256_ctr}; +struct st_ptls_mbedtls_chacha20_context_t { + ptls_cipher_context_t super; + mbedtls_chacha20_context mctx; +}; + +static void ptls_mbedtls_chacha20_init(ptls_cipher_context_t *_ctx, const void *iv) +{ + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + + (void)mbedtls_chacha20_starts(mbedtls_chacha20_context * ctx, (const uint8_t*)iv, 0); +} + +static void ptls_mbedtls_chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) +{ + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + size_t nc_off = 0; + + if (mbedtls_chacha20_update(&ctx->mctx, len, + (const uint8_t*)input, (uint8_t*)output) != 0) { + memset(output, 0, len); + } +} + +static void ptls_mbedtls_chacha20_dispose(ptls_cipher_context_t *_ctx) +{ + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + mbedtls_chacha20_free(&ctx->mctx); +} + +static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +{ + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + int ret = 0; + + mbedtls_chacha20_init(&ctx->mctx); + ret = mbedtls_chacha20_setkey(&ctx->mctx, (const uint8_t*)key); + + ctx->super.do_dispose = ptls_mbedtls_chacha20_dispose; + ctx->super.do_init = ptls_mbedtls_chacha20_init; + ctx->super.do_transform = NULL; + + if (ret == 0) { + ctx->super.do_transform = ptls_mbedtls_chacha20_transform; + } + + return ret; +} + +ptls_cipher_algorithm_t ptls_minicrypto_chacha20 = { + "CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_chacha20_context_t), + ptls_mbedtls_cipher_setup_crypto_chacha20}; + + /* Definitions of AEAD algorithms. * * For the picotls API, AEAD algorithms are created by calling: @@ -674,8 +723,8 @@ ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = { "AES128-GCM", PTLS_AESGCM_CONFIDENTIALITY_LIMIT, PTLS_AESGCM_INTEGRITY_LIMIT, - &ptls_mbedtls_aes128ecb, &ptls_mbedtls_aes128ctr, + &ptls_mbedtls_aes128ecb, PTLS_AES128_KEY_SIZE, PTLS_AESGCM_IV_SIZE, PTLS_AESGCM_TAG_SIZE, @@ -690,8 +739,8 @@ ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = { "AES256-GCM", PTLS_AESGCM_CONFIDENTIALITY_LIMIT, PTLS_AESGCM_INTEGRITY_LIMIT, - &ptls_mbedtls_aes256ecb, &ptls_mbedtls_aes256ctr, + &ptls_mbedtls_aes256ecb, PTLS_AES256_KEY_SIZE, PTLS_AESGCM_IV_SIZE, PTLS_AESGCM_TAG_SIZE, @@ -701,3 +750,19 @@ ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = { sizeof(struct ptls_mbedtls_aead_context_t), ptls_mbedtls_aead_setup_crypto }; + +ptls_aead_algorithm_t ptls_minicrypto_chacha20poly1305 = { + "CHACHA20-POLY1305", + PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT, + PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT, + &ptls_minicrypto_chacha20, + NULL, + PTLS_CHACHA20_KEY_SIZE, + PTLS_CHACHA20POLY1305_IV_SIZE, + PTLS_CHACHA20POLY1305_TAG_SIZE, + {PTLS_TLS12_CHACHAPOLY_FIXED_IV_SIZE, PTLS_TLS12_CHACHAPOLY_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + ptls_mbedtls_aead_setup_crypto +}; \ No newline at end of file diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 3d91979a7..87dacf188 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -348,6 +348,14 @@ static void test_aes256gcm_sha384(void) } #endif +static void test_chacha20poly1305_sha256(void) +{ + if (test_aead(&ptls_minicrypto_chacha20poly1305, &ptls_mbedtls_sha256, &ptls_minicrypto_chacha20poly1305, &ptls_minicrypto_sha256) != 0) { + ok(!"fail"); + } + ok(!!"success"); +} + int main(int argc, char **argv) { /* Initialize the PSA crypto library. */ From 511863166c425cc49060f4c8d301c05b553f05c5 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 21:03:14 -0700 Subject: [PATCH 032/151] Add test definition. --- t/ptls_mbedtls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 87dacf188..c19000ecb 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -377,6 +377,7 @@ int main(int argc, char **argv) #if defined(MBEDTLS_SHA384_C) subtest("aes256gcm_sha384", test_aes256gcm_sha384); #endif + subtest("chacha20poly1305_sha256", test_chacha20poly1305_sha256); /* Deinitialize the PSA crypto library. */ mbedtls_psa_crypto_free(); From 0ad6f7f1ae6eac519c3ec57845952bce017f3e77 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 21:20:55 -0700 Subject: [PATCH 033/151] Fix copy paste errors --- lib/ptls_mbedtls.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 4f4c4eba1..80a836bc3 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -388,15 +388,14 @@ struct st_ptls_mbedtls_chacha20_context_t { static void ptls_mbedtls_chacha20_init(ptls_cipher_context_t *_ctx, const void *iv) { - struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; - (void)mbedtls_chacha20_starts(mbedtls_chacha20_context * ctx, (const uint8_t*)iv, 0); + (void)mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t*)iv, 0); } static void ptls_mbedtls_chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) { - struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; - size_t nc_off = 0; + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; if (mbedtls_chacha20_update(&ctx->mctx, len, (const uint8_t*)input, (uint8_t*)output) != 0) { @@ -406,13 +405,13 @@ static void ptls_mbedtls_chacha20_transform(ptls_cipher_context_t *_ctx, void *o static void ptls_mbedtls_chacha20_dispose(ptls_cipher_context_t *_ctx) { - struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; mbedtls_chacha20_free(&ctx->mctx); } static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx, int is_enc, const void *key) { - struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; int ret = 0; mbedtls_chacha20_init(&ctx->mctx); From 62736e7b17487cb63e2250d9142f829c1db260d5 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 21:26:49 -0700 Subject: [PATCH 034/151] Another typo to fix --- t/ptls_mbedtls.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index c19000ecb..5a5f29dea 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -330,6 +330,14 @@ static void test_aes256ctr(void) ok(!!"success"); } +static void test_chacha20(void) +{ + if (test_cipher(&ptls_mbedtls_chacha20, &ptls_minicrypto_chacha20) != 0) { + ok(!"fail"); + } + ok(!!"success"); +} + static void test_aes128gcm_sha256(void) { if (test_aead(&ptls_mbedtls_aes128gcm, &ptls_mbedtls_sha256, &ptls_minicrypto_aes128gcm, &ptls_minicrypto_sha256) != 0) { @@ -350,7 +358,7 @@ static void test_aes256gcm_sha384(void) static void test_chacha20poly1305_sha256(void) { - if (test_aead(&ptls_minicrypto_chacha20poly1305, &ptls_mbedtls_sha256, &ptls_minicrypto_chacha20poly1305, &ptls_minicrypto_sha256) != 0) { + if (test_aead(&ptls_mbedtls_chacha20poly1305, &ptls_mbedtls_sha256, &ptls_minicrypto_chacha20poly1305, &ptls_minicrypto_sha256) != 0) { ok(!"fail"); } ok(!!"success"); From 4510592270ac21536032b20bbc3b9e91ad62f30b Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 21:43:10 -0700 Subject: [PATCH 035/151] Fix declarations --- include/picotls/ptls_mbedtls.h | 2 ++ lib/ptls_mbedtls.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index f0a59ede9..d3be13fcb 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -37,9 +37,11 @@ extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; +extern ptls_cipher_algorithm_t ptls_minicrypto_chacha20; extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; +extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; #ifdef __cplusplus } diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 80a836bc3..a5474940d 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -750,7 +750,7 @@ ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = { ptls_mbedtls_aead_setup_crypto }; -ptls_aead_algorithm_t ptls_minicrypto_chacha20poly1305 = { +ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { "CHACHA20-POLY1305", PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT, PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT, From f8186754c502b0c0c4786f62fd8c6566a86c7cd4 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 21:51:54 -0700 Subject: [PATCH 036/151] use chacha20 test --- t/ptls_mbedtls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 5a5f29dea..2bd5f73e3 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -381,6 +381,7 @@ int main(int argc, char **argv) subtest("aes128ctr", test_aes128ctr); subtest("aes256ecb", test_aes256ecb); subtest("aes256ctr", test_aes256ctr); + subtest("chacha20", test_chacha20); subtest("aes128gcm_sha256", test_aes128gcm_sha256); #if defined(MBEDTLS_SHA384_C) subtest("aes256gcm_sha384", test_aes256gcm_sha384); From 25894aecf1386e255bcc28f8699902a8ef6e29a7 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 22:22:01 -0700 Subject: [PATCH 037/151] Fix chacha20 declaration --- include/picotls/ptls_mbedtls.h | 2 +- lib/ptls_mbedtls.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index d3be13fcb..2d2790c04 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -37,7 +37,7 @@ extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; -extern ptls_cipher_algorithm_t ptls_minicrypto_chacha20; +extern ptls_cipher_algorithm_t ptls_mbedtls_chacha20; extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index a5474940d..110dd1db7 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -428,7 +428,7 @@ static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx return ret; } -ptls_cipher_algorithm_t ptls_minicrypto_chacha20 = { +ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { "CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_chacha20_context_t), ptls_mbedtls_cipher_setup_crypto_chacha20}; From 167be771691e8122576059d6d5623c4c72b84a96 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 22:48:25 -0700 Subject: [PATCH 038/151] One last typo, hopefully --- lib/ptls_mbedtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 110dd1db7..9e8fe9020 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -754,7 +754,7 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { "CHACHA20-POLY1305", PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT, PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT, - &ptls_minicrypto_chacha20, + &ptls_mbedptls_chacha20, NULL, PTLS_CHACHA20_KEY_SIZE, PTLS_CHACHA20POLY1305_IV_SIZE, From 9b80cac86411874a01f6ab4502dd4307c81007ec Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 6 Sep 2023 22:59:51 -0700 Subject: [PATCH 039/151] That's for coding when half asleep --- lib/ptls_mbedtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 9e8fe9020..f33e43477 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -754,7 +754,7 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { "CHACHA20-POLY1305", PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT, PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT, - &ptls_mbedptls_chacha20, + &ptls_mbedtls_chacha20, NULL, PTLS_CHACHA20_KEY_SIZE, PTLS_CHACHA20POLY1305_IV_SIZE, From e4cc1ffe505398a54d072e4bc567c7df6fa5f591 Mon Sep 17 00:00:00 2001 From: Roberto Guimaraes Date: Thu, 7 Sep 2023 15:33:48 +0900 Subject: [PATCH 040/151] Provide capability to segment session resumption using user-supplied value --- include/picotls.h | 7 +++++++ lib/picotls.c | 36 +++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index b701e780b..04b885a92 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -922,6 +922,13 @@ struct st_ptls_context_t { * (optional) list of supported tls12 cipher-suites terminated by NULL */ ptls_cipher_suite_t **tls12_cipher_suites; + /** + * (optional) session ID Context to segment resumption + */ + struct { + uint8_t bytes[PTLS_SHA256_DIGEST_SIZE]; + uint8_t is_set : 1; + } ticket_context; }; typedef struct st_ptls_raw_extension_t { diff --git a/lib/picotls.c b/lib/picotls.c index d03bf408a..f9bb5ef0d 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -1706,10 +1706,13 @@ static int encode_session_identifier(ptls_context_t *ctx, ptls_buffer_t *buf, ui ptls_buffer_push16(buf, csid); /* ticket_age_add */ ptls_buffer_push32(buf, ticket_age_add); - /* server-name */ + /* sessin ID context */ ptls_buffer_push_block(buf, 2, { - if (server_name != NULL) + if (ctx->ticket_context.is_set) { + ptls_buffer_pushv(buf, ctx->ticket_context.bytes, sizeof(ctx->ticket_context.bytes)); + } else if (server_name != NULL) { ptls_buffer_pushv(buf, server_name, strlen(server_name)); + } }); /* alpn */ ptls_buffer_push_block(buf, 1, { @@ -1722,7 +1725,7 @@ static int encode_session_identifier(ptls_context_t *ctx, ptls_buffer_t *buf, ui return ret; } -int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t *ticket_age_add, ptls_iovec_t *server_name, +int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t *ticket_age_add, ptls_iovec_t *ticket_ctx, uint16_t *key_exchange_id, uint16_t *csid, ptls_iovec_t *negotiated_protocol, const uint8_t *src, const uint8_t *const end) { @@ -1748,7 +1751,7 @@ int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t * if ((ret = ptls_decode32(ticket_age_add, &src, end)) != 0) goto Exit; ptls_decode_open_block(src, end, 2, { - *server_name = ptls_iovec_init(src, end - src); + *ticket_ctx = ptls_iovec_init(src, end - src); src = end; }); ptls_decode_open_block(src, end, 1, { @@ -4006,7 +4009,7 @@ static int try_psk_handshake(ptls_t *tls, size_t *psk_index, int *accept_early_d ptls_iovec_t ch_trunc) { ptls_buffer_t decbuf; - ptls_iovec_t ticket_psk, ticket_server_name, ticket_negotiated_protocol; + ptls_iovec_t ticket_psk, ticket_ctx, ticket_negotiated_protocol; uint64_t issue_at, now = tls->ctx->get_time->cb(tls->ctx->get_time); uint32_t age_add; uint16_t ticket_key_exchange_id, ticket_csid; @@ -4029,7 +4032,7 @@ static int try_psk_handshake(ptls_t *tls, size_t *psk_index, int *accept_early_d default: /* decryption failure */ continue; } - if (decode_session_identifier(&issue_at, &ticket_psk, &age_add, &ticket_server_name, &ticket_key_exchange_id, &ticket_csid, + if (decode_session_identifier(&issue_at, &ticket_psk, &age_add, &ticket_ctx, &ticket_key_exchange_id, &ticket_csid, &ticket_negotiated_protocol, decbuf.base, decbuf.base + decbuf.off) != 0) continue; /* check age */ @@ -4046,15 +4049,22 @@ static int try_psk_handshake(ptls_t *tls, size_t *psk_index, int *accept_early_d if (tls->ctx->max_early_data_size != 0 && delta <= PTLS_EARLY_DATA_MAX_DELAY) *accept_early_data = 1; } - /* check server-name */ - if (ticket_server_name.len != 0) { - if (tls->server_name == NULL) - continue; - if (!vec_is_string(ticket_server_name, tls->server_name)) + /* check ticket context */ + if (tls->ctx->ticket_context.is_set) { + if (!(ticket_ctx.len == sizeof(tls->ctx->ticket_context.bytes) && + memcmp(ticket_ctx.base, tls->ctx->ticket_context.bytes, ticket_ctx.len) == 0)) continue; } else { - if (tls->server_name != NULL) - continue; + /* check server-name */ + if (ticket_ctx.len != 0) { + if (tls->server_name == NULL) + continue; + if (!vec_is_string(ticket_ctx, tls->server_name)) + continue; + } else { + if (tls->server_name != NULL) + continue; + } } { /* check key-exchange */ ptls_key_exchange_algorithm_t **a; From 480f189ed8b4ffdb478bf30052341dcae3ee515f Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Thu, 7 Sep 2023 12:25:31 -0700 Subject: [PATCH 041/151] Fix initialization of chacha20-ctr --- lib/ptls_mbedtls.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index f33e43477..d78ac14ec 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -386,11 +386,13 @@ struct st_ptls_mbedtls_chacha20_context_t { mbedtls_chacha20_context mctx; }; -static void ptls_mbedtls_chacha20_init(ptls_cipher_context_t *_ctx, const void *iv) +static void ptls_mbedtls_chacha20_init(ptls_cipher_context_t *_ctx, const void *v_iv) { struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; + const uint8_t* iv = (const uint8_t*)v_iv; + uint32_t ctr = iv[0] | ((uint32_t)iv[1] << 8) | ((uint32_t)iv[2] << 16) | ((uint32_t)iv[3] << 24); - (void)mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t*)iv, 0); + (void)mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t*)(iv+4), ctr); } static void ptls_mbedtls_chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) From c06bc1b61c4ddba083b017cda4ac6f12162c1549 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Thu, 7 Sep 2023 12:46:35 -0700 Subject: [PATCH 042/151] Add mbedtls to ptlsbench --- CMakeLists.txt | 2 ++ t/ptlsbench.c | 28 +++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b44a64125..c4ffd50d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,6 +215,8 @@ IF (WITH_MBEDTLS) TARGET_LINK_LIBRARIES(test-mbedtls.t picotls-minicrypto picotls-mbedtls ${MBEDTLS_LIBRARIES}) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPTLS_HAVE_MBEDTLS=1") + LIST(APPEND PTLSBENCH_LIBS picotls-mbedtls ${MBEDTLS_LIBRARIES}) #ELSE () # MESSAGE (FATAL_ERROR "MbedTLS not found") #ENDIF() diff --git a/t/ptlsbench.c b/t/ptlsbench.c index 1b27607eb..684d99c0d 100644 --- a/t/ptlsbench.c +++ b/t/ptlsbench.c @@ -57,6 +57,12 @@ #endif #endif +#ifdef PTLS_HAVE_MBEDTLS +#include "mbedtls/build_info.h" +#include "psa/crypto.h" +#include "picotls/ptls_mbedtls.h" +#endif + /* Time in microseconds */ static uint64_t bench_time() { @@ -269,7 +275,15 @@ static ptls_bench_entry_t aead_list[] = { {"openssl", "chacha20poly1305", &ptls_openssl_chacha20poly1305, &ptls_minicrypto_sha256, 1}, #endif {"openssl", "aes128gcm", &ptls_openssl_aes128gcm, &ptls_minicrypto_sha256, 1}, - {"openssl", "aes256gcm", &ptls_openssl_aes256gcm, &ptls_minicrypto_sha384, 1}}; + {"openssl", "aes256gcm", &ptls_openssl_aes256gcm, &ptls_minicrypto_sha384, 1}, +#ifdef PTLS_HAVE_MBEDTLS + {"mbedtls", "aes128gcm",& ptls_mbedtls_aes128gcm,& ptls_mbedtls_sha256, 1}, +#if defined(MBEDTLS_SHA384_C) + { "mbedtls", "aes256gcm", &ptls_mbedtls_aes256gcm, &ptls_mbedtls_sha384, 1 }, +#endif + { "mbedtls", "chacha20poly1305", &ptls_mbedtls_chacha20poly1305, &ptls_mbedtls_sha256, 1 }, +#endif +}; static size_t nb_aead_list = sizeof(aead_list) / sizeof(ptls_bench_entry_t); @@ -323,6 +337,13 @@ int main(int argc, char **argv) } #endif +#ifdef PTLS_HAVE_MBEDTLS + if (psa_crypto_init() != PSA_SUCCESS) { + note("psa_crypto_init fails."); + exit(-1); + } +#endif + if (argc == 2 && strcmp(argv[1], "-f") == 0) { force_all_tests = 1; } else if (argc > 1) { @@ -346,5 +367,10 @@ int main(int argc, char **argv) printf("Unexpected value of test sum s = %llx\n", (unsigned long long)s); } +#ifdef PTLS_HAVE_MBEDTLS + /* Deinitialize the PSA crypto library. */ + mbedtls_psa_crypto_free(); +#endif + return ret; } From 833b34ae17c6a3d95db119a1cacc8f289b9cb44e Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Thu, 7 Sep 2023 12:50:43 -0700 Subject: [PATCH 043/151] Fix debug message --- t/ptlsbench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/ptlsbench.c b/t/ptlsbench.c index 684d99c0d..c86c6d5bf 100644 --- a/t/ptlsbench.c +++ b/t/ptlsbench.c @@ -339,7 +339,7 @@ int main(int argc, char **argv) #ifdef PTLS_HAVE_MBEDTLS if (psa_crypto_init() != PSA_SUCCESS) { - note("psa_crypto_init fails."); + fprintf(stderr, "psa_crypto_init fails.\n"); exit(-1); } #endif From 8f1542d7badf692d640817f6eaf75d68e8c3c856 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Thu, 7 Sep 2023 13:16:55 -0700 Subject: [PATCH 044/151] Condition fusion to PTLS_HAVE_FUSION --- CMakeLists.txt | 3 ++- t/ptlsbench.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4ffd50d7..a40ca4ad6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,7 +197,8 @@ IF (WITH_FUSION) ADD_DEPENDENCIES(test-fusion.t generate-picotls-probes) ENDIF () SET(TEST_EXES ${TEST_EXES} test-fusion.t) - + + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPTLS_HAVE_FUSION=1") LIST(APPEND PTLSBENCH_LIBS picotls-fusion) ENDIF () diff --git a/t/ptlsbench.c b/t/ptlsbench.c index c86c6d5bf..8fdb6fdb7 100644 --- a/t/ptlsbench.c +++ b/t/ptlsbench.c @@ -36,8 +36,10 @@ #include "picotls/minicrypto.h" #include "picotls/openssl.h" #ifndef _WINDOWS +#ifdef PTLS_HAVE_FUSION #include "picotls/fusion.h" #endif +#endif #include #ifdef _WINDOWS @@ -268,9 +270,11 @@ static ptls_bench_entry_t aead_list[] = { {"ptlsbcrypt", "aes256gcm", &ptls_bcrypt_aes256gcm, &ptls_bcrypt_sha384, 1}, #endif #if !defined(_WINDOWS) +#ifdef PTLS_HAVE_FUSION {"fusion", "aes128gcm", &ptls_fusion_aes128gcm, &ptls_minicrypto_sha256, 1}, {"fusion", "aes256gcm", &ptls_fusion_aes256gcm, &ptls_minicrypto_sha384, 1}, #endif +#endif #if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 {"openssl", "chacha20poly1305", &ptls_openssl_chacha20poly1305, &ptls_minicrypto_sha256, 1}, #endif From 815a6b59afac56e3288c57d8ea50a9c362a8e724 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Thu, 7 Sep 2023 17:00:08 -0700 Subject: [PATCH 045/151] Declare cipher suites --- include/picotls/ptls_mbedtls.h | 7 +++++++ lib/ptls_mbedtls.c | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index 2d2790c04..279fa7cc4 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -43,6 +43,13 @@ extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; + +extern ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256; +#if defined(MBEDTLS_SHA384_C) +extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; +#endif +extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; + #ifdef __cplusplus } #endif diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index d78ac14ec..b78aa3e69 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -766,4 +766,21 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { 0, sizeof(struct ptls_mbedtls_aead_context_t), ptls_mbedtls_aead_setup_crypto -}; \ No newline at end of file +}; + +ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256 = {.id = PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, +.name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256, +.aead = &ptls_mbedtls_aes128gcm, +.hash = &ptls_mbedtls_sha256}; + +#if defined(MBEDTLS_SHA384_C) +ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = {.id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, +.name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384, +.aead = &ptls_mbedtls_aes256gcm, +.hash = &ptls_mbedtls_sha384}; +#endif + +ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256, +.name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256, +.aead = &ptls_mbedtls_chacha20poly1305, +.hash = &ptls_mbedtls_sha256}; \ No newline at end of file From e922949c4fa6e0d46bc9f1f36710899be7ae0763 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Fri, 8 Sep 2023 13:44:32 -0700 Subject: [PATCH 046/151] Add support for MbedTLS random --- include/picotls/ptls_mbedtls.h | 2 ++ lib/ptls_mbedtls.c | 12 ++++++++++++ t/ptls_mbedtls.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index 279fa7cc4..397a224b4 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -50,6 +50,8 @@ extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; #endif extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; +void ptls_mbedtls_random_bytes(void* buf, size_t len); + #ifdef __cplusplus } #endif diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index b78aa3e69..73e4df486 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -15,6 +15,18 @@ #include "mbedtls/aes.h" #include "mbedtls/chacha20.h" +/* Random number generator. +* This is a call to the PSA random number generator, which according +* to the documentation meets cryptographic requirements. +*/ + +void ptls_mbedtls_random_bytes(void* buf, size_t len) +{ + if (psa_generate_random((uint8_t*)buf, len) != 0) { + memset(buf, 0, len); + } +} + /* Definitions for hash algorithms. * In Picotls, these are described by the stucture * ptls_hash_algorithm_t, which include the function diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 2bd5f73e3..0dec6fed9 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -37,6 +37,34 @@ #include "picotls/minicrypto.h" #include "../deps/picotest/picotest.h" +static int test_random() +{ + /* The random test is just trying to check that we call the API properly. + * This is done by getting a vector of 1021 bytes, computing the sum of + * all values, and comparing to theoretical min and max, + * computed as average +- 8*standard deviation for sum of 1021 terms. + * 8 random deviations results in an extremely low probability of random + * failure. + * Note that this does not actually test the random generator. + */ + + uint8_t buf[PTLS_MBEDTLS_RANDOM_TEST_LENGTH]; + uint64_t sum = 0; + const uint64_t max_sum_1021 = 149505; + const uint64_t min_sum_1021 = 110849; + int ret = 0; + + ptls_mbedtls_random_bytes(buf, PTLS_MBEDTLS_RANDOM_TEST_LENGTH); + for (size_t i = 0; i < PTLS_MBEDTLS_RANDOM_TEST_LENGTH; i++) { + sum += buf[i]; + } + if (sum > max_sum_1021 || sum < min_sum_1021) { + ret = -1; + } + + return ret; +} + static int hash_trial(ptls_hash_algorithm_t* algo, const uint8_t* input, size_t len1, size_t len2, uint8_t* final_hash) { int ret = 0; @@ -371,6 +399,8 @@ int main(int argc, char **argv) note("psa_crypto_init fails."); return done_testing(); } + /* Test of the port of the mbedtls random generator */ + subtest("random", test_random); /* Series of test to check consistency between wrapped mbedtls and minicrypto */ subtest("sha256", test_sha256); #if defined(MBEDTLS_SHA384_C) From 5701e4a161b61bfb2ccd9a53b5bb6122f9e6ae3d Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 12 Sep 2023 14:48:14 +0900 Subject: [PATCH 047/151] typo --- lib/picotls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/picotls.c b/lib/picotls.c index f9bb5ef0d..e2a3e0422 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -1706,7 +1706,7 @@ static int encode_session_identifier(ptls_context_t *ctx, ptls_buffer_t *buf, ui ptls_buffer_push16(buf, csid); /* ticket_age_add */ ptls_buffer_push32(buf, ticket_age_add); - /* sessin ID context */ + /* session ID context */ ptls_buffer_push_block(buf, 2, { if (ctx->ticket_context.is_set) { ptls_buffer_pushv(buf, ctx->ticket_context.bytes, sizeof(ctx->ticket_context.bytes)); From b06746d3474ea0eda57419d3e99113443401e884 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 13 Sep 2023 09:25:25 +0900 Subject: [PATCH 048/151] [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 943c8a9a559ae7bb2f2002af99e3b3014db07259 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Tue, 12 Sep 2023 17:27:51 -0700 Subject: [PATCH 049/151] use high level PSA API --- include/picotls/ptls_mbedtls.h | 33 +- lib/ptls_mbedtls.c | 586 ++++++++++++++++++--------------- 2 files changed, 341 insertions(+), 278 deletions(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index 397a224b4..93dba6e25 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -27,30 +27,25 @@ extern "C" { #endif #include "picotls.h" -extern ptls_hash_algorithm_t ptls_mbedtls_sha256; -extern ptls_hash_algorithm_t ptls_mbedtls_sha512; + extern ptls_hash_algorithm_t ptls_mbedtls_sha256; + extern ptls_hash_algorithm_t ptls_mbedtls_sha512; #if defined(MBEDTLS_SHA384_C) -extern ptls_hash_algorithm_t ptls_mbedtls_sha384; + extern ptls_hash_algorithm_t ptls_mbedtls_sha384; #endif -extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; -extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; -extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; -extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; -extern ptls_cipher_algorithm_t ptls_mbedtls_chacha20; + extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; + extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; + extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; + extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; + extern ptls_cipher_algorithm_t ptls_mbedtls_chacha20; -extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; -extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; -extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; + extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; + extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; + extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; - -extern ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256; -#if defined(MBEDTLS_SHA384_C) -extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; -#endif -extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; - -void ptls_mbedtls_random_bytes(void* buf, size_t len); + int ptls_mbedtls_init(); + void ptls_mbedtls_free(); + void ptls_mbedtls_random_bytes(void* buf, size_t len); #ifdef __cplusplus } diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 73e4df486..a01f8902b 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -10,21 +10,37 @@ #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "psa/crypto_struct.h" -#include "mbedtls/sha256.h" -#include "mbedtls/sha512.h" -#include "mbedtls/aes.h" + #include "mbedtls/chacha20.h" +#include "mbedtls/ecdh.h" + +/* Init and free functions. Init should be used before starting using +* library functions. Free should be used before leaving the program. +*/ + +void ptls_mbedtls_free() +{ + mbedtls_psa_crypto_free(); +} + +int ptls_mbedtls_init() +{ + int ret = 0; + psa_status_t status; + if ((status = psa_crypto_init()) != PSA_SUCCESS) { + ret = -1; + } + + return ret; +} /* Random number generator. * This is a call to the PSA random number generator, which according * to the documentation meets cryptographic requirements. */ - void ptls_mbedtls_random_bytes(void* buf, size_t len) { - if (psa_generate_random((uint8_t*)buf, len) != 0) { - memset(buf, 0, len); - } + psa_generate_random((uint8_t*)buf, len); } /* Definitions for hash algorithms. @@ -42,72 +58,85 @@ void ptls_mbedtls_random_bytes(void* buf, size_t len) * */ -typedef struct st_ptls_mbedtls_sha256_ctx_t { +typedef struct st_ptls_mbedtls_hash_ctx_t { ptls_hash_context_t super; - mbedtls_sha256_context mctx; -} ptls_mbedtls_sha256_ctx_t; + psa_algorithm_t alg; + size_t hash_size; + psa_hash_operation_t operation; +} ptls_mbedtls_hash_ctx_t; -static void ptls_mbedtls_sha256_update(struct st_ptls_hash_context_t* _ctx, const void* src, size_t len) +static void ptls_mbedtls_hash_update(struct st_ptls_hash_context_t* _ctx, const void* src, size_t len) { - ptls_mbedtls_sha256_ctx_t* ctx = (ptls_mbedtls_sha256_ctx_t*)_ctx; + ptls_mbedtls_hash_ctx_t* ctx = (ptls_mbedtls_hash_ctx_t*)_ctx; - (void)mbedtls_sha256_update(&ctx->mctx, (const uint8_t*)src, len); + (void) psa_hash_update(&ctx->operation, (const uint8_t *) src, len); } -static void ptls_mbedtls_sha256_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode); +static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode); -static struct st_ptls_hash_context_t* ptls_mbedtls_sha256_clone(struct st_ptls_hash_context_t* _src) +static struct st_ptls_hash_context_t* ptls_mbedtls_hash_clone(struct st_ptls_hash_context_t* _src) { - ptls_mbedtls_sha256_ctx_t* ctx = (ptls_mbedtls_sha256_ctx_t*)malloc(sizeof(ptls_mbedtls_sha256_ctx_t)); + ptls_mbedtls_hash_ctx_t* ctx = (ptls_mbedtls_hash_ctx_t*)malloc(sizeof(ptls_mbedtls_hash_ctx_t)); + const ptls_mbedtls_hash_ctx_t* src = (const ptls_mbedtls_hash_ctx_t*)_src; if (ctx != NULL) { - ptls_mbedtls_sha256_ctx_t* src = (ptls_mbedtls_sha256_ctx_t*)_src; - memset(&ctx->mctx, 0, sizeof(mbedtls_sha256_context)); - ctx->super.clone_ = ptls_mbedtls_sha256_clone; - ctx->super.update = ptls_mbedtls_sha256_update; - ctx->super.final = ptls_mbedtls_sha256_final; - mbedtls_sha256_clone(&ctx->mctx, &src->mctx); + ptls_mbedtls_hash_ctx_t* src = (ptls_mbedtls_hash_ctx_t*)_src; + memset(&ctx->operation, 0, sizeof(mbedtls_sha256_context)); + ctx->super.clone_ = ptls_mbedtls_hash_clone; + ctx->super.update = ptls_mbedtls_hash_update; + ctx->super.final = ptls_mbedtls_hash_final; + ctx->alg = src->alg; + ctx->hash_size = src->hash_size; + if (psa_hash_clone(&src->operation, &ctx->operation) != 0) { + free(ctx); + ctx = NULL; + } } return (ptls_hash_context_t*)ctx; } -static void ptls_mbedtls_sha256_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode) +static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode) { - ptls_mbedtls_sha256_ctx_t* ctx = (ptls_mbedtls_sha256_ctx_t*)_ctx; + ptls_mbedtls_hash_ctx_t* ctx = (ptls_mbedtls_hash_ctx_t*)_ctx; if (mode == PTLS_HASH_FINAL_MODE_SNAPSHOT) { - struct st_ptls_hash_context_t* cloned = ptls_mbedtls_sha256_clone(_ctx); + struct st_ptls_hash_context_t* cloned = ptls_mbedtls_hash_clone(_ctx); if (cloned != NULL) { - ptls_mbedtls_sha256_final(cloned, md, PTLS_HASH_FINAL_MODE_FREE); + ptls_mbedtls_hash_final(cloned, md, PTLS_HASH_FINAL_MODE_FREE); } } else { if (md != NULL) { - (void)mbedtls_sha256_finish(&ctx->mctx, (uint8_t*)md); + size_t hash_length = 0; + if (psa_hash_finish(&ctx->operation, md, ctx->hash_size, &hash_length) != 0) { + memset(md, 0, ctx->hash_size); + } } if (mode == PTLS_HASH_FINAL_MODE_FREE) { - mbedtls_sha256_free(&ctx->mctx); + (void)psa_hash_abort(&ctx->operation); free(ctx); } else { /* if mode = reset, reset the context */ - mbedtls_sha256_init(&ctx->mctx); - mbedtls_sha256_starts(&ctx->mctx, 0 /* is224 = 0 */); + memset(&ctx->operation, 0, sizeof(ctx->operation)); + (void)psa_hash_setup(&ctx->operation, ctx->alg); } } } -ptls_hash_context_t* ptls_mbedtls_sha256_create(void) +ptls_hash_context_t* ptls_mbedtls_hash_create(psa_algorithm_t alg, size_t hash_size) { - ptls_mbedtls_sha256_ctx_t* ctx = (ptls_mbedtls_sha256_ctx_t*)malloc(sizeof(ptls_mbedtls_sha256_ctx_t)); + ptls_mbedtls_hash_ctx_t* ctx = (ptls_mbedtls_hash_ctx_t*)malloc(sizeof(ptls_mbedtls_hash_ctx_t)); if (ctx != NULL) { - memset(&ctx->mctx, 0, sizeof(mbedtls_sha256_context)); - ctx->super.clone_ = ptls_mbedtls_sha256_clone; - ctx->super.update = ptls_mbedtls_sha256_update; - ctx->super.final = ptls_mbedtls_sha256_final; - if (mbedtls_sha256_starts(&ctx->mctx, 0 /* is224 = 0 */) != 0) { + memset(&ctx->operation, 0, sizeof(ctx->operation)); + ctx->alg = alg; + ctx->hash_size = hash_size; + ctx->super.clone_ = ptls_mbedtls_hash_clone; + ctx->super.update = ptls_mbedtls_hash_update; + ctx->super.final = ptls_mbedtls_hash_final; + if (psa_hash_setup(&ctx->operation, alg) != 0){ free(ctx); ctx = NULL; } @@ -115,96 +144,19 @@ ptls_hash_context_t* ptls_mbedtls_sha256_create(void) return (ptls_hash_context_t*)ctx; } -ptls_hash_algorithm_t ptls_mbedtls_sha256 = {"sha256", PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, ptls_mbedtls_sha256_create, -PTLS_ZERO_DIGEST_SHA256}; - - -/* SHA 512 follows the same general architecture as SHA 256. - * The SHA 384 module is using the same code, with an option to - * deliver a shorter hash. - */ - - -typedef struct st_ptls_mbedtls_sha512_ctx_t { - ptls_hash_context_t super; - mbedtls_sha512_context mctx; - int is384; -} ptls_mbedtls_sha512_ctx_t; - -static void ptls_mbedtls_sha512_update(struct st_ptls_hash_context_t* _ctx, const void* src, size_t len) -{ - ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)_ctx; - - (void)mbedtls_sha512_update(&ctx->mctx, (const uint8_t*)src, len); -} - -static void ptls_mbedtls_sha512_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode); - -static struct st_ptls_hash_context_t* ptls_mbedtls_sha512_clone(struct st_ptls_hash_context_t* _src) +ptls_hash_context_t* ptls_mbedtls_sha256_create(void) { - ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)malloc(sizeof(ptls_mbedtls_sha512_ctx_t)); - - if (ctx != NULL) { - ptls_mbedtls_sha512_ctx_t* src = (ptls_mbedtls_sha512_ctx_t*)_src; - memset(&ctx->mctx, 0, sizeof(mbedtls_sha512_context)); - ctx->super.clone_ = ptls_mbedtls_sha512_clone; - ctx->super.update = ptls_mbedtls_sha512_update; - ctx->super.final = ptls_mbedtls_sha512_final; - mbedtls_sha512_clone(&ctx->mctx, &src->mctx); - } - return (ptls_hash_context_t*)ctx; + return ptls_mbedtls_hash_create(PSA_ALG_SHA_256, PTLS_SHA256_DIGEST_SIZE); } -static void ptls_mbedtls_sha512_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode) +ptls_hash_context_t* ptls_mbedtls_sha512_create(void) { - ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)_ctx; - - if (mode == PTLS_HASH_FINAL_MODE_SNAPSHOT) { - struct st_ptls_hash_context_t* cloned = ptls_mbedtls_sha512_clone(_ctx); - - if (cloned != NULL) { - ptls_mbedtls_sha512_final(cloned, md, PTLS_HASH_FINAL_MODE_FREE); - } - } else { - if (md != NULL) { - (void)mbedtls_sha512_finish(&ctx->mctx, (uint8_t*)md); - } - - if (mode == PTLS_HASH_FINAL_MODE_FREE) { - mbedtls_sha512_free(&ctx->mctx); - free(ctx); - } - else { - /* if mode = reset, reset the context */ - mbedtls_sha512_init(&ctx->mctx); - mbedtls_sha512_starts(&ctx->mctx, ctx->is384); - } - } + return ptls_mbedtls_hash_create(PSA_ALG_SHA_512, PTLS_SHA512_DIGEST_SIZE); } -ptls_hash_context_t* ptls_mbedtls_sha512_384_create(int is384) -{ - ptls_mbedtls_sha512_ctx_t* ctx = (ptls_mbedtls_sha512_ctx_t*)malloc(sizeof(ptls_mbedtls_sha512_ctx_t)); - if (ctx != NULL) { - memset(&ctx->mctx, 0, sizeof(mbedtls_sha512_context)); - ctx->super.clone_ = ptls_mbedtls_sha512_clone; - ctx->super.update = ptls_mbedtls_sha512_update; - ctx->super.final = ptls_mbedtls_sha512_final; - ctx->is384 = is384; - - if (mbedtls_sha512_starts(&ctx->mctx, is384) != 0) { - free(ctx); - ctx = NULL; - } - } - return (ptls_hash_context_t*)ctx; -} - -ptls_hash_context_t* ptls_mbedtls_sha512_create(void) -{ - return ptls_mbedtls_sha512_384_create(0); -} +ptls_hash_algorithm_t ptls_mbedtls_sha256 = {"sha256", PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, ptls_mbedtls_sha256_create, +PTLS_ZERO_DIGEST_SHA256}; ptls_hash_algorithm_t ptls_mbedtls_sha512 = {"SHA512", PTLS_SHA512_BLOCK_SIZE, PTLS_SHA512_DIGEST_SIZE, ptls_mbedtls_sha512_create, PTLS_ZERO_DIGEST_SHA512}; @@ -212,7 +164,7 @@ PTLS_ZERO_DIGEST_SHA512}; #if defined(MBEDTLS_SHA384_C) ptls_hash_context_t* ptls_mbedtls_sha384_create(void) { - return ptls_mbedtls_sha512_384_create(1); + return ptls_mbedtls_hash_create(PSA_ALG_SHA_384, PTLS_SHA384_DIGEST_SIZE); } ptls_hash_algorithm_t ptls_mbedtls_sha384 = {"SHA384", PTLS_SHA384_BLOCK_SIZE, @@ -220,179 +172,196 @@ PTLS_SHA384_DIGEST_SIZE, ptls_mbedtls_sha384_create, PTLS_ZERO_DIGEST_SHA384}; #endif /* MBEDTLS_SHA384_C */ -/* definitions for symmetric crypto algorithms. -* Each algorithm (ECB or CTR) is represented by an "algorithm" -* entry in which the 'setup" function is used to initialize -* The "setup" function creates an object of type -* ptls_cipher_context_t, with three function pointers: -* -* void (*do_dispose)(struct st_ptls_cipher_context_t *ctx); -* void (*do_init)(struct st_ptls_cipher_context_t *ctx, const void *iv); -* void (*do_transform)(struct st_ptls_cipher_context_t *ctx, void *output, const void *input, size_t len); -* -* "do_init" sets the IV value. In CTR mode, this is the nonce value, which -* will be incremented after each block. In CTR mode, this also sets the -* "stream block". -* - */ - -struct st_ptls_mbedtls_aes_context_t { +/* +* Generic implementation of a cipher using the PSA API +*/ +struct st_ptls_mbedtls_cipher_context_t { ptls_cipher_context_t super; - mbedtls_aes_context aes_ctx; - uint8_t nonce_counter[16]; - uint8_t stream_block[16]; - int is_enc; /* MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT */ + psa_algorithm_t alg; + size_t iv_length; + int is_enc; + int is_op_in_progress; + mbedtls_svc_key_id_t key; + psa_cipher_operation_t operation; }; -static void ptls_mbedtls_aes_ctr_init(ptls_cipher_context_t *_ctx, const void *iv) + +static void ptls_mbedtls_cipher_init(ptls_cipher_context_t *_ctx, const void *iv) { - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + + if (ctx->is_op_in_progress) { + psa_cipher_abort(&ctx->operation); + ctx->is_op_in_progress = 0; + } - if (iv == NULL) { - memset(ctx->nonce_counter, 0, 16); + memset(&ctx->operation, 0, sizeof(ctx->operation)); + if (ctx->is_enc) { + (void)psa_cipher_encrypt_setup(&ctx->operation, ctx->key, ctx->alg); } else { - memcpy(ctx->nonce_counter, iv, 16); + (void)psa_cipher_decrypt_setup(&ctx->operation, ctx->key, ctx->alg); } - memset(ctx->stream_block, 0, 16); -} - -static void ptls_mbedtls_aes_ecb_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) -{ - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; - - /* Call the encryption */ - if (mbedtls_aes_crypt_ecb(&ctx->aes_ctx, ctx->is_enc, (const uint8_t*)input, (uint8_t*)output) != 0) { - memset(output, 0, len); + if (ctx->iv_length > 0) { + (void)psa_cipher_set_iv(&ctx->operation, (const uint8_t*)iv, ctx->iv_length); } + ctx->is_op_in_progress = 1; } -static void ptls_mbedtls_aes_ctr_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) +static void ptls_mbedtls_cipher_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) { - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; - size_t nc_off = 0; + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + size_t outlen = 0; - if (mbedtls_aes_crypt_ctr(&ctx->aes_ctx, len, &nc_off, ctx->nonce_counter, ctx->stream_block, - (const uint8_t*)input, (uint8_t*)output) != 0) { - memset(output, 0, len); - } + (void) psa_cipher_update(&ctx->operation, (const uint8_t*)input, len, (uint8_t*)output, len, &outlen); } -static void ptls_mbedtls_aes_ctr_dispose(ptls_cipher_context_t *_ctx) +static void ptls_mbedtls_cipher_dispose(ptls_cipher_context_t *_ctx) { - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; - mbedtls_aes_free(&ctx->aes_ctx); + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + if (ctx->is_op_in_progress) { + psa_cipher_abort(&ctx->operation); + ctx->is_op_in_progress = 0; + } + psa_destroy_key(ctx->key); } -static int ptls_mbedtls_cipher_setup_crypto_aes(ptls_cipher_context_t* _ctx, int is_enc, const void* key, unsigned int keybits) +static int ptls_mbedtls_cipher_setup_key(mbedtls_svc_key_id_t* key_id, int is_enc, psa_algorithm_t alg, psa_key_type_t key_type, + size_t key_bits, uint8_t * key_bytes) { - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; int ret = 0; - memset(ctx->nonce_counter, 0, 16); - memset(ctx->stream_block, 0, 16); - - ctx->super.do_dispose = ptls_mbedtls_aes_ctr_dispose; - ctx->super.do_init = ptls_mbedtls_aes_ctr_init; - ctx->super.do_transform = NULL; - - mbedtls_aes_init(&ctx->aes_ctx); - if (is_enc) { - ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key, keybits); - ctx->is_enc = MBEDTLS_AES_ENCRYPT; - } - else { - ret = mbedtls_aes_setkey_dec(&ctx->aes_ctx, key, keybits); - ctx->is_enc = MBEDTLS_AES_DECRYPT; + psa_set_key_usage_flags(&attributes, + (is_enc)?PSA_KEY_USAGE_ENCRYPT:PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, key_type); + psa_set_key_bits(&attributes, key_bits); + /* Import key */ + if (psa_import_key(&attributes, key_bytes, key_bits / 8, + key_id) != PSA_SUCCESS) { + ret = PTLS_ERROR_LIBRARY; } return ret; - } -static int ptls_mbedtls_cipher_setup_crypto_aes128_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +static int ptls_mbedtls_cipher_setup_crypto(ptls_cipher_context_t* _ctx, int is_enc, const void* key_bytes, + psa_algorithm_t alg, size_t iv_length, psa_key_type_t key_type, size_t key_bits) { - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; - int ret = ptls_mbedtls_cipher_setup_crypto_aes(_ctx, is_enc, key, 128); + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + int ret = 0; - if (ret == 0) { - ctx->super.do_transform = ptls_mbedtls_aes_ecb_transform; - } + ctx->alg = alg; + ctx->is_enc = is_enc; + ctx->iv_length = iv_length; - return ret; -} + /* Initialize the key attributes */ + ret = ptls_mbedtls_cipher_setup_key(&ctx->key, is_enc, alg, key_type, key_bits, key_bytes); + /* Finish initializing the context */ + ctx->super.do_dispose = ptls_mbedtls_cipher_dispose; + ctx->super.do_init = ptls_mbedtls_cipher_init; + ctx->super.do_transform = NULL; -static int ptls_mbedtls_cipher_setup_crypto_aes128_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key) -{ -#ifdef _WINDOWS - UNREFERENCED_PARAMETER(is_enc); -#endif - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; - int ret = ptls_mbedtls_cipher_setup_crypto_aes(_ctx, 1, key, 128); /* No difference between CTR encrypt and decrypt */ if (ret == 0) { - ctx->super.do_transform = ptls_mbedtls_aes_ctr_transform; + ctx->super.do_transform = ptls_mbedtls_cipher_transform; } return ret; } -static int ptls_mbedtls_cipher_setup_crypto_aes256_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +/* +* Implementation of AES128_ECB using the PSA API: +*/ +static int ptls_mbedtls_cipher_setup_aes128_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) { - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; - int ret = ptls_mbedtls_cipher_setup_crypto_aes(_ctx, is_enc, key, 256); + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, + PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 128); +} - if (ret == 0) { - ctx->super.do_transform = ptls_mbedtls_aes_ecb_transform; - } +ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { + "AES128-ECB", + PTLS_AES128_KEY_SIZE, + PTLS_AES_BLOCK_SIZE, + 0 /* iv size */, + sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_aes128_ecb}; - return ret; +/* +* Implementation of AES256_ECB using the PSA API: +*/ +static int ptls_mbedtls_cipher_setup_aes256_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +{ + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, + PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 256); } -static int ptls_mbedtls_cipher_setup_crypto_aes256_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key) -{ -#ifdef _WINDOWS - UNREFERENCED_PARAMETER(is_enc); -#endif - struct st_ptls_mbedtls_aes_context_t *ctx = (struct st_ptls_mbedtls_aes_context_t *)_ctx; - int ret = ptls_mbedtls_cipher_setup_crypto_aes(_ctx, 1, key, 256); /* No difference between CTR encrypt and decrypt */ +ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { + "AES256-ECB", + PTLS_AES128_KEY_SIZE, + PTLS_AES_BLOCK_SIZE, + 0 /* iv size */, + sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_aes256_ecb}; - if (ret == 0) { - ctx->super.do_transform = ptls_mbedtls_aes_ctr_transform; - } +/* +* Implementation of AES128_CTR using the PSA API: +*/ - return ret; +static int ptls_mbedtls_cipher_setup_aes128_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +{ + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, + PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 128); } -ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { - "AES128-ECB", +ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { + "AES128-CTR", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, - 0 /* iv size */, - sizeof(struct st_ptls_mbedtls_aes_context_t), - ptls_mbedtls_cipher_setup_crypto_aes128_ecb}; - -ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = {"AES256-ECB", -PTLS_AES256_KEY_SIZE, -PTLS_AES_BLOCK_SIZE, -0 /* iv size */, -sizeof(struct st_ptls_mbedtls_aes_context_t), -ptls_mbedtls_cipher_setup_crypto_aes256_ecb}; - -ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = {"AES128-CTR", -PTLS_AES128_KEY_SIZE, -PTLS_AES_BLOCK_SIZE, -0 /* iv size */, -sizeof(struct st_ptls_mbedtls_aes_context_t), -ptls_mbedtls_cipher_setup_crypto_aes128_ctr}; - -ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = {"AES256-CTR", -PTLS_AES256_KEY_SIZE, -PTLS_AES_BLOCK_SIZE, -0 /* iv size */, -sizeof(struct st_ptls_mbedtls_aes_context_t), -ptls_mbedtls_cipher_setup_crypto_aes256_ctr}; + 16 /* iv size */, + sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_aes128_ctr}; + +/* +* Implementation of AES128_CTR using the PSA API: +*/ +static int ptls_mbedtls_cipher_setup_aes256_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +{ + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, + PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 256); +} + +ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { + "AES128-CTR", + PTLS_AES256_KEY_SIZE, + PTLS_AES_BLOCK_SIZE, + 16 /* iv size */, + sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_aes256_ctr}; + + +#if 0 +/* +* Implementation of CHACHA20 using the PSA API. +* This is disabled for now, as there seems to be an issue when +* setting the 16 bytes long IV that we need. +*/ +static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +{ + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, + PSA_ALG_STREAM_CIPHER, 16, PSA_KEY_TYPE_CHACHA20, 256); +} + +ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { + "CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_crypto_chacha20}; +#else +/* Implementation of ChaCha20 using the low level ChaCha20 API. +* TODO: remove this and the reference to chacha20.h as soon as +* the IV bug in the generic implementation is fixed. +*/ struct st_ptls_mbedtls_chacha20_context_t { ptls_cipher_context_t super; mbedtls_chacha20_context mctx; @@ -445,7 +414,7 @@ static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { "CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_chacha20_context_t), ptls_mbedtls_cipher_setup_crypto_chacha20}; - +#endif /* Definitions of AEAD algorithms. * @@ -780,19 +749,118 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { ptls_mbedtls_aead_setup_crypto }; -ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256 = {.id = PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, -.name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256, -.aead = &ptls_mbedtls_aes128gcm, -.hash = &ptls_mbedtls_sha256}; +/* Key exchange algorithms. +* The Picotls framework defines these algorithms as ptls_key_exchange_algorithm_t, +* a structure containing two function pointers: +* +* int (*create)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx); +* int (*exchange)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, +* ptls_iovec_t peerkey); +* The "create" call is used on the client. It documents the ptls_key_exchange_context_t, which contains +* the public key prepared by the client, as an iovec, and a function pointer: +* +* int (*on_exchange)(struct st_ptls_key_exchange_context_t **keyex, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey); +* +* The public key of the client is passed to the server an ends up as "peerkey" argument to the (exchange) function. +* That function documents the server's public key, and the secret coputed by combining server and client key. +* +* When the client receives the server hello, the stack calls the "on_exchange" callback, passing the context +* previously created by the client and the public key of the peer, so the client can compute its own +* version of the secret. +* +* The following code uses the MbedTLS API to create the "create", "exchange" and "on_exchange" functions. +*/ -#if defined(MBEDTLS_SHA384_C) -ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = {.id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, -.name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384, -.aead = &ptls_mbedtls_aes256gcm, -.hash = &ptls_mbedtls_sha384}; +/* TODO: use the PSA API, +* psa_generate_key +* +*/ +#define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 +#define TYPE_MBEDTLS_ECDH_UNCOMPRESSED_PUBLIC_KEY 4 + +struct ptls_mbedtls_ecdh_key_exchange_context_t { + ptls_key_exchange_context_t super; + mbedtls_ecdh_context ecdh_ctx; + uint8_t pub[PTLS_MBEDTLS_ECDH_PUBKEY_MAX]; +}; + +#if 0 +static int ptls_mbedtls_ecdh_gen_public(struct ptls_mbedtls_ecdh_key_exchange_context_t * ctx) +{ + int ret = 0; + ret = mbedtls_ecdh_setup(&ctx->ecdh_ctx, ctx->group_id /* MBEDTLS_ECP_DP_CURVE25519 */); + if (ret == 0) { + ret = mbedtls_ecdh_make_params(&ctx->ecdh_ctx, &cli_olen, cli_to_srv, + sizeof(cli_to_srv), + mbedtls_ctr_drbg_random, &ptls_mbedtls_ctr_drbg); + } +} #endif -ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256, -.name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256, -.aead = &ptls_mbedtls_chacha20poly1305, -.hash = &ptls_mbedtls_sha256}; \ No newline at end of file +static int ptls_mbedtls_exchange_id_from_tls(int tls_id) +{ + int mbedtls_id = MBEDTLS_ECP_DP_NONE; + switch (tls_id) { + case PTLS_GROUP_SECP256R1: + mbedtls_id = MBEDTLS_ECP_DP_SECP256R1; + break; + case PTLS_GROUP_SECP384R1: + mbedtls_id = MBEDTLS_ECP_DP_SECP384R1; + break; + case PTLS_GROUP_SECP521R1: + mbedtls_id = MBEDTLS_ECP_DP_SECP521R1; + break; + case PTLS_GROUP_X25519: + mbedtls_id = MBEDTLS_ECP_DP_CURVE25519; + break; + case PTLS_GROUP_X448: + mbedtls_id = MBEDTLS_ECP_DP_CURVE448; + break; + default: + break; + } + return mbedtls_id; +} + +#if 0 +static int ptls_mbedtls_ecdh_on_exchange( + struct st_ptls_key_exchange_context_t** keyex, int release, ptls_iovec_t* secret, ptls_iovec_t peerkey) +{ + +} + +static int ptls_mbedtls_ecdh_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **keyex) +{ + /* TODO: simplify */ + struct ptls_mbedtls_ecdh_key_exchange_context_t *ctx; + int ret = 0; + int mbedtls_id = ptls_mbedtls_exchange_id_from_tls(algo->id); + + if (mbedtls_id == MBEDTLS_ECP_DP_NONE) { + return PTLS_ERROR_NOT_AVAILABLE; + } + if ((ctx = (struct ptls_mbedtls_ecdh_key_exchange_context_t*)malloc(sizeof(*ctx))) == NULL) { + return PTLS_ERROR_NO_MEMORY; + } + ctx->super = (ptls_key_exchange_context_t){algo, ptls_iovec_init(ctx->pub, sizeof(ctx->pub)), ptls_mbedtls_ecdh_on_exchange}; + ret = mbedtls_ecdh_setup(&ctx->ecdh_ctx, mbedtls_id); + ctx->pub[0] = TYPE_MBEDTLS_ECDH_UNCOMPRESSED_PUBLIC_KEY; + + + + + return 0; + + + + + + + + if (ret == 0) { + ret = mbedtls_ecdh_make_params(&ctx->ecdh_ctx, &cli_olen, cli_to_srv, + sizeof(cli_to_srv), + mbedtls_ctr_drbg_random, &ptls_mbedtls_ctr_drbg); + } +} +#endif \ No newline at end of file From 32b9845b369aeac6c9442bf18bbc7e871fd2f45d Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 13 Sep 2023 09:52:20 +0900 Subject: [PATCH 050/151] 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 051/151] 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 c112fc51029f0fcf234cd5c09095494594a9219a Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Tue, 12 Sep 2023 18:58:06 -0700 Subject: [PATCH 052/151] Fix test random --- t/ptls_mbedtls.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 0dec6fed9..f472f83b5 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -37,7 +37,9 @@ #include "picotls/minicrypto.h" #include "../deps/picotest/picotest.h" -static int test_random() +#define PTLS_MBEDTLS_RANDOM_TEST_LENGTH 1021; + +static int random_trial() { /* The random test is just trying to check that we call the API properly. * This is done by getting a vector of 1021 bytes, computing the sum of @@ -65,6 +67,15 @@ static int test_random() return ret; } +static void test_random(void) +{ + if (random_trial() != 0) { + ok(!"fail"); + return; + } + ok(!!"success"); +} + static int hash_trial(ptls_hash_algorithm_t* algo, const uint8_t* input, size_t len1, size_t len2, uint8_t* final_hash) { int ret = 0; From d91376594fdf69e31ded906acf97eacc0b00d996 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Tue, 12 Sep 2023 19:02:48 -0700 Subject: [PATCH 053/151] Fix typo --- t/ptls_mbedtls.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index f472f83b5..ebd1d8c86 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -37,8 +37,6 @@ #include "picotls/minicrypto.h" #include "../deps/picotest/picotest.h" -#define PTLS_MBEDTLS_RANDOM_TEST_LENGTH 1021; - static int random_trial() { /* The random test is just trying to check that we call the API properly. @@ -50,14 +48,14 @@ static int random_trial() * Note that this does not actually test the random generator. */ - uint8_t buf[PTLS_MBEDTLS_RANDOM_TEST_LENGTH]; + uint8_t buf[1021]; uint64_t sum = 0; const uint64_t max_sum_1021 = 149505; const uint64_t min_sum_1021 = 110849; int ret = 0; - ptls_mbedtls_random_bytes(buf, PTLS_MBEDTLS_RANDOM_TEST_LENGTH); - for (size_t i = 0; i < PTLS_MBEDTLS_RANDOM_TEST_LENGTH; i++) { + ptls_mbedtls_random_bytes(buf, sizeof(buf)); + for (size_t i = 0; i < sizeof(buf); i++) { sum += buf[i]; } if (sum > max_sum_1021 || sum < min_sum_1021) { From 0a3dccb5aca4627a5e287af998b6cb6f5ad8f585 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 13 Sep 2023 22:38:37 -0700 Subject: [PATCH 054/151] Add code of sec256r1 --- include/picotls/ptls_mbedtls.h | 2 + lib/ptls_mbedtls.c | 209 +++++++++++++++++++++++---------- 2 files changed, 150 insertions(+), 61 deletions(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index 93dba6e25..aff76ae31 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -43,6 +43,8 @@ extern "C" { extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; + extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; + int ptls_mbedtls_init(); void ptls_mbedtls_free(); void ptls_mbedtls_random_bytes(void* buf, size_t len); diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index a01f8902b..b48de0c48 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -10,8 +10,10 @@ #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "psa/crypto_struct.h" +#include "psa/crypto_values.h" #include "mbedtls/chacha20.h" + #include "mbedtls/ecdh.h" /* Init and free functions. Init should be used before starting using @@ -227,7 +229,7 @@ static void ptls_mbedtls_cipher_dispose(ptls_cipher_context_t *_ctx) } static int ptls_mbedtls_cipher_setup_key(mbedtls_svc_key_id_t* key_id, int is_enc, psa_algorithm_t alg, psa_key_type_t key_type, - size_t key_bits, uint8_t * key_bytes) + size_t key_bits, const uint8_t * key_bytes) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; int ret = 0; @@ -257,7 +259,7 @@ static int ptls_mbedtls_cipher_setup_crypto(ptls_cipher_context_t* _ctx, int is_ ctx->iv_length = iv_length; /* Initialize the key attributes */ - ret = ptls_mbedtls_cipher_setup_key(&ctx->key, is_enc, alg, key_type, key_bits, key_bytes); + ret = ptls_mbedtls_cipher_setup_key(&ctx->key, is_enc, alg, key_type, key_bits, (const uint8_t *)key_bytes); /* Finish initializing the context */ ctx->super.do_dispose = ptls_mbedtls_cipher_dispose; ctx->super.do_init = ptls_mbedtls_cipher_init; @@ -762,7 +764,7 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { * int (*on_exchange)(struct st_ptls_key_exchange_context_t **keyex, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey); * * The public key of the client is passed to the server an ends up as "peerkey" argument to the (exchange) function. -* That function documents the server's public key, and the secret coputed by combining server and client key. +* That function documents the server's public key, and the secret computed by combining server and client key. * * When the client receives the server hello, the stack calls the "on_exchange" callback, passing the context * previously created by the client and the public key of the peer, so the client can compute its own @@ -778,89 +780,174 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { #define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 #define TYPE_MBEDTLS_ECDH_UNCOMPRESSED_PUBLIC_KEY 4 -struct ptls_mbedtls_ecdh_key_exchange_context_t { +struct ptls_mbedtls_key_exchange_context_t { ptls_key_exchange_context_t super; - mbedtls_ecdh_context ecdh_ctx; + psa_algorithm_t psa_alg; + psa_ecc_family_t curve; + size_t curve_bits; + size_t secret_size; + psa_key_id_t private_key; uint8_t pub[PTLS_MBEDTLS_ECDH_PUBKEY_MAX]; }; -#if 0 -static int ptls_mbedtls_ecdh_gen_public(struct ptls_mbedtls_ecdh_key_exchange_context_t * ctx) +/* Set a private key for key exchange. For now, we only support ECC +*/ + +static int ptls_mbedtls_key_exchange_set_private_key(psa_key_id_t * private_key, + psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits) { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; int ret = 0; - ret = mbedtls_ecdh_setup(&ctx->ecdh_ctx, ctx->group_id /* MBEDTLS_ECP_DP_CURVE25519 */); - if (ret == 0) { - ret = mbedtls_ecdh_make_params(&ctx->ecdh_ctx, &cli_olen, cli_to_srv, - sizeof(cli_to_srv), - mbedtls_ctr_drbg_random, &ptls_mbedtls_ctr_drbg); + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&attributes, psa_alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve) ); + psa_set_key_bits(&attributes, curve_bits); + if (psa_generate_key(&attributes, private_key) != 0) { + ret = -1; } + return ret; } -#endif -static int ptls_mbedtls_exchange_id_from_tls(int tls_id) -{ - int mbedtls_id = MBEDTLS_ECP_DP_NONE; - switch (tls_id) { - case PTLS_GROUP_SECP256R1: - mbedtls_id = MBEDTLS_ECP_DP_SECP256R1; - break; - case PTLS_GROUP_SECP384R1: - mbedtls_id = MBEDTLS_ECP_DP_SECP384R1; - break; - case PTLS_GROUP_SECP521R1: - mbedtls_id = MBEDTLS_ECP_DP_SECP521R1; - break; - case PTLS_GROUP_X25519: - mbedtls_id = MBEDTLS_ECP_DP_CURVE25519; - break; - case PTLS_GROUP_X448: - mbedtls_id = MBEDTLS_ECP_DP_CURVE448; - break; - default: - break; - } - return mbedtls_id; +/* +* The key agreement is done by calling psa_raw_key_agreement +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, +psa_key_id_t private_key, +const uint8_t * peer_key, +size_t peer_key_length, +uint8_t * output, +size_t output_size, +size_t * output_length); +*/ + +int ptls_mbedtls_key_exchange_on_exchange(struct st_ptls_key_exchange_context_t** _pctx, int release, ptls_iovec_t* secret, ptls_iovec_t peerkey) +{ + int ret = 0; + struct ptls_mbedtls_key_exchange_context_t *keyex = (struct ptls_mbedtls_key_exchange_context_t *)*_pctx; + + if (secret != NULL) { + uint8_t* secbytes = (uint8_t*)malloc(keyex->secret_size); + + if (secbytes == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + } + else { + size_t olen; + if (psa_raw_key_agreement(keyex->psa_alg, keyex->private_key, (const uint8_t*)peerkey.base, peerkey.len, + secbytes, keyex->secret_size, &olen) == 0) { + *secret = ptls_iovec_init(secbytes, keyex->secret_size); + } + else { + free(secbytes); + ret = PTLS_ERROR_LIBRARY; + } + } + } + if (release) { + /* Clear the private key */ + psa_destroy_key(keyex->private_key); + /* Set context to NULL */ + *_pctx = NULL; + /* TODO: check whether allocated memory should be freed */ + } + + return ret; } -#if 0 -static int ptls_mbedtls_ecdh_on_exchange( - struct st_ptls_key_exchange_context_t** keyex, int release, ptls_iovec_t* secret, ptls_iovec_t peerkey) +int ptls_mbedtls_key_exchange_create(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_key_exchange_context_t** ctx, + psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) { + struct ptls_mbedtls_key_exchange_context_t *keyex; + size_t olen = 0; + if ((keyex = (struct ptls_mbedtls_key_exchange_context_t *)malloc(sizeof(struct ptls_mbedtls_key_exchange_context_t))) == NULL) + return PTLS_ERROR_NO_MEMORY; + /* Initialize the exchange context based on the algorithm definition */ + keyex->psa_alg = psa_alg; + keyex->curve = curve; + keyex->curve_bits = curve_bits; + keyex->secret_size = secret_size; + /* Initialize the private key and format the public key */ + if (ptls_mbedtls_key_exchange_set_private_key(&keyex->private_key, psa_alg, curve, curve_bits) != 0){ + free(keyex); + *ctx = NULL; + return PTLS_ERROR_LIBRARY; + } + /* According to the doc, format of public key is same as picotls */ + if (psa_export_public_key(keyex->private_key, keyex->pub, sizeof(keyex->pub), &olen) != 0) { + psa_destroy_key(keyex->private_key); + free(keyex); + *ctx = NULL; + return PTLS_ERROR_LIBRARY; + } + keyex->super.pubkey= ptls_iovec_init(keyex->pub, olen); + /* Initialize the ptls exchange context */ + keyex->super.algo = algo; + keyex->super.on_exchange = ptls_mbedtls_key_exchange_on_exchange; + *ctx = (ptls_key_exchange_context_t*)keyex; + return 0; } -static int ptls_mbedtls_ecdh_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **keyex) +static int ptls_mbedtls_key_exchange_exchange(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_iovec_t* pubkey, ptls_iovec_t* secret, + ptls_iovec_t peerkey, psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) { - /* TODO: simplify */ - struct ptls_mbedtls_ecdh_key_exchange_context_t *ctx; + /* generate a local private key for the selected algorithm */ + psa_key_id_t private_key; + size_t pubkey_len; + uint8_t* pubkey_bytes = NULL; + size_t secret_len; + uint8_t* secret_bytes = (uint8_t*)malloc(secret_size); int ret = 0; - int mbedtls_id = ptls_mbedtls_exchange_id_from_tls(algo->id); - if (mbedtls_id == MBEDTLS_ECP_DP_NONE) { - return PTLS_ERROR_NOT_AVAILABLE; + if (secret_bytes == NULL) { + return PTLS_ERROR_NO_MEMORY; } - if ((ctx = (struct ptls_mbedtls_ecdh_key_exchange_context_t*)malloc(sizeof(*ctx))) == NULL) { + pubkey_bytes = (uint8_t*)malloc(PTLS_MBEDTLS_ECDH_PUBKEY_MAX); + if (pubkey_bytes == NULL){ + free(secret_bytes); return PTLS_ERROR_NO_MEMORY; } - ctx->super = (ptls_key_exchange_context_t){algo, ptls_iovec_init(ctx->pub, sizeof(ctx->pub)), ptls_mbedtls_ecdh_on_exchange}; - ret = mbedtls_ecdh_setup(&ctx->ecdh_ctx, mbedtls_id); - ctx->pub[0] = TYPE_MBEDTLS_ECDH_UNCOMPRESSED_PUBLIC_KEY; - - - - - return 0; - + if (ptls_mbedtls_key_exchange_set_private_key(&private_key, psa_alg, curve, curve_bits) != 0) { + free(secret_bytes); + free(pubkey_bytes); + return PTLS_ERROR_LIBRARY; + } + /* Export public key and call key agrement function */ + if (psa_export_public_key(private_key, pubkey_bytes, PTLS_MBEDTLS_ECDH_PUBKEY_MAX, &pubkey_len) == 0 && + psa_raw_key_agreement(psa_alg, private_key, (const uint8_t*)peerkey.base, peerkey.len, + secret_bytes, secret_size, &secret_len) == 0) { + *secret = ptls_iovec_init(secret_bytes, secret_len); + *pubkey = ptls_iovec_init(pubkey_bytes, pubkey_len); + } + else { + free(secret_bytes); + free(pubkey_bytes); + return PTLS_ERROR_LIBRARY; + } + psa_destroy_key(private_key); + return ret; +} +/* Instantiation of the generic API with secp256r1 +*/ +static int ptls_mbedtls_secp256r1_create(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_key_exchange_context_t** ctx) +{ + return ptls_mbedtls_key_exchange_create(algo, ctx, + PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); +} - if (ret == 0) { - ret = mbedtls_ecdh_make_params(&ctx->ecdh_ctx, &cli_olen, cli_to_srv, - sizeof(cli_to_srv), - mbedtls_ctr_drbg_random, &ptls_mbedtls_ctr_drbg); - } +static int ptls_mbedtls_secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_iovec_t* pubkey, ptls_iovec_t* secret, + ptls_iovec_t peerkey) +{ + return ptls_mbedtls_key_exchange_exchange(algo, pubkey, secret, peerkey, + PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); } -#endif \ No newline at end of file + +ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = {.id = PTLS_GROUP_SECP256R1, +.name = PTLS_GROUP_NAME_SECP256R1, +.create = ptls_mbedtls_secp256r1_create, +.exchange = ptls_mbedtls_secp256r1_exchange}; \ No newline at end of file From b55b56a419787f4cabe5127307330fe623ffb6b4 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 14 Sep 2023 14:53:23 +0900 Subject: [PATCH 055/151] [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 056/151] 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 057/151] 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 1c24153be3f8f68cca85bd5454aa6e26cb7aee94 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 13 Sep 2023 23:08:17 -0700 Subject: [PATCH 058/151] Simplify aead setup --- lib/ptls_mbedtls.c | 58 +++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index b48de0c48..32a13f4ae 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -625,37 +625,17 @@ size_t ptls_mbedtls_aead_do_decrypt(struct st_ptls_aead_context_t* _ctx, void* o return o_len; } -static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) +static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv, + psa_algorithm_t psa_alg, size_t key_bits, psa_key_type_t key_type) { int ret = 0; struct ptls_mbedtls_aead_context_t* ctx = (struct ptls_mbedtls_aead_context_t*)_ctx; - size_t key_bits; - psa_key_type_t key_type; + /* set mbed specific context to NULL, just to be sure */ memset(&ctx->mctx, 0, sizeof(struct ptls_mbedtls_aead_param_t)); - - /* deduce the PSA algorithm from the name */ - if (strcmp(ctx->super.algo->name, "AES128-GCM") == 0) { - ctx->mctx.alg = PSA_ALG_GCM; - key_bits = 128; - key_type = PSA_KEY_TYPE_AES; - } else if (strcmp(ctx->super.algo->name, "AES256-GCM") == 0) { - ctx->mctx.alg = PSA_ALG_GCM; - key_bits = 256; - key_type = PSA_KEY_TYPE_AES; - } else if (strcmp(ctx->super.algo->name, "AES128-GCM_8") == 0) { - ctx->mctx.alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 8); - key_bits = 128; - key_type = PSA_KEY_TYPE_AES; - } else if (strcmp(ctx->super.algo->name, "CHACHA20-POLY1305") == 0) { - ctx->mctx.alg = PSA_ALG_CHACHA20_POLY1305; - key_bits = 256; - key_type = PSA_KEY_TYPE_CHACHA20; - } else { - ret = PTLS_ERROR_LIBRARY; - } + ctx->mctx.alg = psa_alg; /* Initialize the key attributes */ if (ret == 0) { @@ -703,6 +683,11 @@ static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, return ret; } +static int ptls_mbedtls_aead_setup_aes128gcm(ptls_aead_context_t* _ctx, int is_enc, const void* key_bytes, const void* iv) +{ + return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 128, PSA_KEY_TYPE_AES); +} + ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = { "AES128-GCM", PTLS_AESGCM_CONFIDENTIALITY_LIMIT, @@ -716,9 +701,14 @@ ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = { 0, 0, sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_crypto + ptls_mbedtls_aead_setup_aes128gcm }; +static int ptls_mbedtls_aead_setup_aes256gcm(ptls_aead_context_t* _ctx, int is_enc, const void* key_bytes, const void* iv) +{ + return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 256, PSA_KEY_TYPE_AES); +} + ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = { "AES256-GCM", PTLS_AESGCM_CONFIDENTIALITY_LIMIT, @@ -732,9 +722,14 @@ ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = { 0, 0, sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_crypto + ptls_mbedtls_aead_setup_aes256gcm }; +static int ptls_mbedtls_aead_setup_chacha20poly1305(ptls_aead_context_t* _ctx, int is_enc, const void* key_bytes, const void* iv) +{ + return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_CHACHA20_POLY1305, 256, PSA_KEY_TYPE_CHACHA20); +} + ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { "CHACHA20-POLY1305", PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT, @@ -748,7 +743,7 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { 0, 0, sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_crypto + ptls_mbedtls_aead_setup_chacha20poly1305 }; /* Key exchange algorithms. @@ -770,15 +765,10 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { * previously created by the client and the public key of the peer, so the client can compute its own * version of the secret. * -* The following code uses the MbedTLS API to create the "create", "exchange" and "on_exchange" functions. +* The following code uses the MbedTLS PSA API to create the "create", "exchange" and "on_exchange" functions. */ -/* TODO: use the PSA API, -* psa_generate_key -* -*/ -#define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 -#define TYPE_MBEDTLS_ECDH_UNCOMPRESSED_PUBLIC_KEY 4 +#define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 struct ptls_mbedtls_key_exchange_context_t { ptls_key_exchange_context_t super; From 3cd437be3c576c7781693d5fb19406167de1e0c6 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Thu, 14 Sep 2023 12:38:42 -0700 Subject: [PATCH 059/151] Add x25519 --- include/picotls/ptls_mbedtls.h | 5 +++ lib/ptls_mbedtls.c | 62 ++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index aff76ae31..b35ad39d3 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -43,7 +43,12 @@ extern "C" { extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; + extern ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256; + extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; + extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; + extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; + extern ptls_key_exchange_algorithm_t ptls_mbedtls_x25519; int ptls_mbedtls_init(); void ptls_mbedtls_free(); diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index 32a13f4ae..c38cfd0ec 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -1,3 +1,25 @@ +/* +* Copyright (c) 2023, Christian Huitema +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + #ifdef _WINDOWS #include "wincompat.h" #endif @@ -704,6 +726,11 @@ ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = { ptls_mbedtls_aead_setup_aes128gcm }; +ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256 = {.id = PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, +.name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256, +.aead = &ptls_mbedtls_aes128gcm, +.hash = &ptls_mbedtls_sha256}; + static int ptls_mbedtls_aead_setup_aes256gcm(ptls_aead_context_t* _ctx, int is_enc, const void* key_bytes, const void* iv) { return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 256, PSA_KEY_TYPE_AES); @@ -725,6 +752,12 @@ ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = { ptls_mbedtls_aead_setup_aes256gcm }; +ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = { + .id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, + .name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384, + .aead = &ptls_mbedtls_aes256gcm, + .hash = &ptls_mbedtls_sha384}; + static int ptls_mbedtls_aead_setup_chacha20poly1305(ptls_aead_context_t* _ctx, int is_enc, const void* key_bytes, const void* iv) { return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_CHACHA20_POLY1305, 256, PSA_KEY_TYPE_CHACHA20); @@ -746,6 +779,11 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { ptls_mbedtls_aead_setup_chacha20poly1305 }; +ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256, +.name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256, +.aead = &ptls_mbedtls_chacha20poly1305, +.hash = &ptls_mbedtls_sha256}; + /* Key exchange algorithms. * The Picotls framework defines these algorithms as ptls_key_exchange_algorithm_t, * a structure containing two function pointers: @@ -922,7 +960,7 @@ static int ptls_mbedtls_key_exchange_exchange(const struct st_ptls_key_exchange_ return ret; } -/* Instantiation of the generic API with secp256r1 +/* Instantiation of the generic key exchange API with secp256r1 */ static int ptls_mbedtls_secp256r1_create(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_key_exchange_context_t** ctx) { @@ -940,4 +978,24 @@ static int ptls_mbedtls_secp256r1_exchange(const struct st_ptls_key_exchange_alg ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = {.id = PTLS_GROUP_SECP256R1, .name = PTLS_GROUP_NAME_SECP256R1, .create = ptls_mbedtls_secp256r1_create, -.exchange = ptls_mbedtls_secp256r1_exchange}; \ No newline at end of file +.exchange = ptls_mbedtls_secp256r1_exchange}; + +/* Instantiation of the generic key exchange API with x25519 +*/ +static int ptls_mbedtls_x25519_create(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_key_exchange_context_t** ctx) +{ + return ptls_mbedtls_key_exchange_create(algo, ctx, + PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); +} + +static int ptls_mbedtls_x25519_exchange(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_iovec_t* pubkey, ptls_iovec_t* secret, + ptls_iovec_t peerkey) +{ + return ptls_mbedtls_key_exchange_exchange(algo, pubkey, secret, peerkey, + PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); +} + +ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = {.id = PTLS_GROUP_X25519, +.name = PTLS_GROUP_NAME_X25519, +.create = ptls_mbedtls_x25519_create, +.exchange = ptls_mbedtls_x25519_exchange}; From eec837c34f578370199740b42500f8a5e70dc1ab Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Thu, 14 Sep 2023 13:42:28 -0700 Subject: [PATCH 060/151] Add test of mbedtls key exchanges --- t/ptls_mbedtls.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index ebd1d8c86..ac6ea9ba6 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -36,6 +36,7 @@ #include "picotls/ptls_mbedtls.h" #include "picotls/minicrypto.h" #include "../deps/picotest/picotest.h" +#include "test.h" static int random_trial() { @@ -401,6 +402,24 @@ static void test_chacha20poly1305_sha256(void) ok(!!"success"); } +static void test_secp256r1(void) +{ + test_key_exchange(&ptls_mbedtls_secp256r1, &ptls_minicrypto_secp256r1); + test_key_exchange(&ptls_minicrypto_secp256r1, &ptls_mbedtls_secp256r1); +} + +static void test_x25519(void) +{ + test_key_exchange(&ptls_mbedtls_x25519, &ptls_minicrypto_x25519); + test_key_exchange(&ptls_minicrypto_x25519, &ptls_mbedtls_x25519); +} + +static void test_key_exchanges(void) +{ + subtest("secp256r1", test_secp256r1); + subtest("x25519", test_x25519); +} + int main(int argc, char **argv) { /* Initialize the PSA crypto library. */ @@ -426,6 +445,7 @@ int main(int argc, char **argv) subtest("aes256gcm_sha384", test_aes256gcm_sha384); #endif subtest("chacha20poly1305_sha256", test_chacha20poly1305_sha256); + subtest("key_exchanges", test_key_exchanges); /* Deinitialize the PSA crypto library. */ mbedtls_psa_crypto_free(); From cc9364ed5014c86b3da67f9da35a682c160698fd Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Thu, 14 Sep 2023 14:43:50 -0700 Subject: [PATCH 061/151] Fix reference to test_key_exchange --- t/ptls_mbedtls.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index ac6ea9ba6..61815b016 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -36,7 +36,6 @@ #include "picotls/ptls_mbedtls.h" #include "picotls/minicrypto.h" #include "../deps/picotest/picotest.h" -#include "test.h" static int random_trial() { @@ -402,6 +401,42 @@ static void test_chacha20poly1305_sha256(void) ok(!!"success"); } +/* Test key exchange. This is a cut and paste of the "test_key_exchange" + * defined in test.h and openssl.c, because referring to that common code + * causes a link error. + */ +static void test_key_exchange(ptls_key_exchange_algorithm_t *client, ptls_key_exchange_algorithm_t *server) +{ + ptls_key_exchange_context_t *ctx; + ptls_iovec_t client_secret, server_pubkey, server_secret; + int ret; + + /* fail */ + ret = server->exchange(server, &server_pubkey, &server_secret, (ptls_iovec_t){NULL}); + ok(ret != 0); + + /* perform ecdh */ + ret = client->create(client, &ctx); + ok(ret == 0); + ret = server->exchange(server, &server_pubkey, &server_secret, ctx->pubkey); + ok(ret == 0); + ret = ctx->on_exchange(&ctx, 1, &client_secret, server_pubkey); + ok(ret == 0); + ok(client_secret.len == server_secret.len); + ok(memcmp(client_secret.base, server_secret.base, client_secret.len) == 0); + + free(client_secret.base); + free(server_pubkey.base); + free(server_secret.base); + + /* client abort */ + ret = client->create(client, &ctx); + ok(ret == 0); + ret = ctx->on_exchange(&ctx, 1, NULL, ptls_iovec_init(NULL, 0)); + ok(ret == 0); + ok(ctx == NULL); +} + static void test_secp256r1(void) { test_key_exchange(&ptls_mbedtls_secp256r1, &ptls_minicrypto_secp256r1); From d462d0c045bd3b4b50cb8a42861dfc3597c3d974 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 17 Oct 2023 13:53:52 +0900 Subject: [PATCH 062/151] [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 063/151] 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 064/151] 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 065/151] 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 066/151] [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 067/151] 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 07b73c943b6c60c763f57283ff45b405719e9141 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 3 Nov 2023 18:30:54 +0900 Subject: [PATCH 068/151] clang-format --- include/picotls/ptls_mbedtls.h | 78 ++-- lib/ptls_mbedtls.c | 673 +++++++++++++++------------------ t/ptls_mbedtls.c | 116 +++--- t/ptlsbench.c | 6 +- 4 files changed, 414 insertions(+), 459 deletions(-) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/ptls_mbedtls.h index b35ad39d3..ac16ab221 100644 --- a/include/picotls/ptls_mbedtls.h +++ b/include/picotls/ptls_mbedtls.h @@ -1,24 +1,24 @@ /* -* Copyright (c) 2023, Christian Huitema -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ + * Copyright (c) 2023, Christian Huitema + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ #ifndef picotls_mbedtls_h #define picotls_mbedtls_h @@ -27,32 +27,32 @@ extern "C" { #endif #include "picotls.h" - extern ptls_hash_algorithm_t ptls_mbedtls_sha256; - extern ptls_hash_algorithm_t ptls_mbedtls_sha512; +extern ptls_hash_algorithm_t ptls_mbedtls_sha256; +extern ptls_hash_algorithm_t ptls_mbedtls_sha512; #if defined(MBEDTLS_SHA384_C) - extern ptls_hash_algorithm_t ptls_mbedtls_sha384; +extern ptls_hash_algorithm_t ptls_mbedtls_sha384; #endif - extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; - extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; - extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; - extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; - extern ptls_cipher_algorithm_t ptls_mbedtls_chacha20; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; +extern ptls_cipher_algorithm_t ptls_mbedtls_chacha20; - extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; - extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; - extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; +extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; +extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; +extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; - extern ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256; - extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; - extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; +extern ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256; +extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; +extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; - extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; - extern ptls_key_exchange_algorithm_t ptls_mbedtls_x25519; +extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; +extern ptls_key_exchange_algorithm_t ptls_mbedtls_x25519; - int ptls_mbedtls_init(); - void ptls_mbedtls_free(); - void ptls_mbedtls_random_bytes(void* buf, size_t len); +int ptls_mbedtls_init(); +void ptls_mbedtls_free(); +void ptls_mbedtls_random_bytes(void *buf, size_t len); #ifdef __cplusplus } diff --git a/lib/ptls_mbedtls.c b/lib/ptls_mbedtls.c index c38cfd0ec..ea9ca1b0e 100644 --- a/lib/ptls_mbedtls.c +++ b/lib/ptls_mbedtls.c @@ -1,24 +1,24 @@ /* -* Copyright (c) 2023, Christian Huitema -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ + * Copyright (c) 2023, Christian Huitema + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ #ifdef _WINDOWS #include "wincompat.h" @@ -39,8 +39,8 @@ #include "mbedtls/ecdh.h" /* Init and free functions. Init should be used before starting using -* library functions. Free should be used before leaving the program. -*/ + * library functions. Free should be used before leaving the program. + */ void ptls_mbedtls_free() { @@ -59,28 +59,28 @@ int ptls_mbedtls_init() } /* Random number generator. -* This is a call to the PSA random number generator, which according -* to the documentation meets cryptographic requirements. -*/ -void ptls_mbedtls_random_bytes(void* buf, size_t len) + * This is a call to the PSA random number generator, which according + * to the documentation meets cryptographic requirements. + */ +void ptls_mbedtls_random_bytes(void *buf, size_t len) { - psa_generate_random((uint8_t*)buf, len); + psa_generate_random((uint8_t *)buf, len); } /* Definitions for hash algorithms. -* In Picotls, these are described by the stucture -* ptls_hash_algorithm_t, which include the function -* pointer for creation of the hash context. -* -* The structure contains a function pointer to the -* "create" function that creates a hash operation, -* which itself contains three function pointers: -* -* void (*update)(struct st_ptls_hash_context_t *ctx, const void *src, size_t len); -* void (*final)(struct st_ptls_hash_context_t *ctx, void *md, ptls_hash_final_mode_t mode); -* struct st_ptls_hash_context_t *(*clone_)(struct st_ptls_hash_context_t *src); -* -*/ + * In Picotls, these are described by the stucture + * ptls_hash_algorithm_t, which include the function + * pointer for creation of the hash context. + * + * The structure contains a function pointer to the + * "create" function that creates a hash operation, + * which itself contains three function pointers: + * + * void (*update)(struct st_ptls_hash_context_t *ctx, const void *src, size_t len); + * void (*final)(struct st_ptls_hash_context_t *ctx, void *md, ptls_hash_final_mode_t mode); + * struct st_ptls_hash_context_t *(*clone_)(struct st_ptls_hash_context_t *src); + * + */ typedef struct st_ptls_mbedtls_hash_ctx_t { ptls_hash_context_t super; @@ -89,22 +89,22 @@ typedef struct st_ptls_mbedtls_hash_ctx_t { psa_hash_operation_t operation; } ptls_mbedtls_hash_ctx_t; -static void ptls_mbedtls_hash_update(struct st_ptls_hash_context_t* _ctx, const void* src, size_t len) +static void ptls_mbedtls_hash_update(struct st_ptls_hash_context_t *_ctx, const void *src, size_t len) { - ptls_mbedtls_hash_ctx_t* ctx = (ptls_mbedtls_hash_ctx_t*)_ctx; + ptls_mbedtls_hash_ctx_t *ctx = (ptls_mbedtls_hash_ctx_t *)_ctx; - (void) psa_hash_update(&ctx->operation, (const uint8_t *) src, len); + (void)psa_hash_update(&ctx->operation, (const uint8_t *)src, len); } -static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode); +static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t *_ctx, void *md, ptls_hash_final_mode_t mode); -static struct st_ptls_hash_context_t* ptls_mbedtls_hash_clone(struct st_ptls_hash_context_t* _src) +static struct st_ptls_hash_context_t *ptls_mbedtls_hash_clone(struct st_ptls_hash_context_t *_src) { - ptls_mbedtls_hash_ctx_t* ctx = (ptls_mbedtls_hash_ctx_t*)malloc(sizeof(ptls_mbedtls_hash_ctx_t)); - const ptls_mbedtls_hash_ctx_t* src = (const ptls_mbedtls_hash_ctx_t*)_src; + ptls_mbedtls_hash_ctx_t *ctx = (ptls_mbedtls_hash_ctx_t *)malloc(sizeof(ptls_mbedtls_hash_ctx_t)); + const ptls_mbedtls_hash_ctx_t *src = (const ptls_mbedtls_hash_ctx_t *)_src; if (ctx != NULL) { - ptls_mbedtls_hash_ctx_t* src = (ptls_mbedtls_hash_ctx_t*)_src; + ptls_mbedtls_hash_ctx_t *src = (ptls_mbedtls_hash_ctx_t *)_src; memset(&ctx->operation, 0, sizeof(mbedtls_sha256_context)); ctx->super.clone_ = ptls_mbedtls_hash_clone; ctx->super.update = ptls_mbedtls_hash_update; @@ -116,15 +116,15 @@ static struct st_ptls_hash_context_t* ptls_mbedtls_hash_clone(struct st_ptls_has ctx = NULL; } } - return (ptls_hash_context_t*)ctx; + return (ptls_hash_context_t *)ctx; } -static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t* _ctx, void* md, ptls_hash_final_mode_t mode) +static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t *_ctx, void *md, ptls_hash_final_mode_t mode) { - ptls_mbedtls_hash_ctx_t* ctx = (ptls_mbedtls_hash_ctx_t*)_ctx; + ptls_mbedtls_hash_ctx_t *ctx = (ptls_mbedtls_hash_ctx_t *)_ctx; if (mode == PTLS_HASH_FINAL_MODE_SNAPSHOT) { - struct st_ptls_hash_context_t* cloned = ptls_mbedtls_hash_clone(_ctx); + struct st_ptls_hash_context_t *cloned = ptls_mbedtls_hash_clone(_ctx); if (cloned != NULL) { ptls_mbedtls_hash_final(cloned, md, PTLS_HASH_FINAL_MODE_FREE); @@ -140,8 +140,7 @@ static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t* _ctx, void* m if (mode == PTLS_HASH_FINAL_MODE_FREE) { (void)psa_hash_abort(&ctx->operation); free(ctx); - } - else { + } else { /* if mode = reset, reset the context */ memset(&ctx->operation, 0, sizeof(ctx->operation)); (void)psa_hash_setup(&ctx->operation, ctx->alg); @@ -149,9 +148,9 @@ static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t* _ctx, void* m } } -ptls_hash_context_t* ptls_mbedtls_hash_create(psa_algorithm_t alg, size_t hash_size) +ptls_hash_context_t *ptls_mbedtls_hash_create(psa_algorithm_t alg, size_t hash_size) { - ptls_mbedtls_hash_ctx_t* ctx = (ptls_mbedtls_hash_ctx_t*)malloc(sizeof(ptls_mbedtls_hash_ctx_t)); + ptls_mbedtls_hash_ctx_t *ctx = (ptls_mbedtls_hash_ctx_t *)malloc(sizeof(ptls_mbedtls_hash_ctx_t)); if (ctx != NULL) { memset(&ctx->operation, 0, sizeof(ctx->operation)); @@ -160,45 +159,43 @@ ptls_hash_context_t* ptls_mbedtls_hash_create(psa_algorithm_t alg, size_t hash_s ctx->super.clone_ = ptls_mbedtls_hash_clone; ctx->super.update = ptls_mbedtls_hash_update; ctx->super.final = ptls_mbedtls_hash_final; - if (psa_hash_setup(&ctx->operation, alg) != 0){ + if (psa_hash_setup(&ctx->operation, alg) != 0) { free(ctx); ctx = NULL; } } - return (ptls_hash_context_t*)ctx; + return (ptls_hash_context_t *)ctx; } -ptls_hash_context_t* ptls_mbedtls_sha256_create(void) +ptls_hash_context_t *ptls_mbedtls_sha256_create(void) { return ptls_mbedtls_hash_create(PSA_ALG_SHA_256, PTLS_SHA256_DIGEST_SIZE); } -ptls_hash_context_t* ptls_mbedtls_sha512_create(void) +ptls_hash_context_t *ptls_mbedtls_sha512_create(void) { return ptls_mbedtls_hash_create(PSA_ALG_SHA_512, PTLS_SHA512_DIGEST_SIZE); } - ptls_hash_algorithm_t ptls_mbedtls_sha256 = {"sha256", PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, ptls_mbedtls_sha256_create, -PTLS_ZERO_DIGEST_SHA256}; + PTLS_ZERO_DIGEST_SHA256}; ptls_hash_algorithm_t ptls_mbedtls_sha512 = {"SHA512", PTLS_SHA512_BLOCK_SIZE, PTLS_SHA512_DIGEST_SIZE, ptls_mbedtls_sha512_create, -PTLS_ZERO_DIGEST_SHA512}; + PTLS_ZERO_DIGEST_SHA512}; #if defined(MBEDTLS_SHA384_C) -ptls_hash_context_t* ptls_mbedtls_sha384_create(void) +ptls_hash_context_t *ptls_mbedtls_sha384_create(void) { return ptls_mbedtls_hash_create(PSA_ALG_SHA_384, PTLS_SHA384_DIGEST_SIZE); } -ptls_hash_algorithm_t ptls_mbedtls_sha384 = {"SHA384", PTLS_SHA384_BLOCK_SIZE, -PTLS_SHA384_DIGEST_SIZE, ptls_mbedtls_sha384_create, -PTLS_ZERO_DIGEST_SHA384}; +ptls_hash_algorithm_t ptls_mbedtls_sha384 = {"SHA384", PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, ptls_mbedtls_sha384_create, + PTLS_ZERO_DIGEST_SHA384}; #endif /* MBEDTLS_SHA384_C */ /* -* Generic implementation of a cipher using the PSA API -*/ + * Generic implementation of a cipher using the PSA API + */ struct st_ptls_mbedtls_cipher_context_t { ptls_cipher_context_t super; psa_algorithm_t alg; @@ -209,7 +206,6 @@ struct st_ptls_mbedtls_cipher_context_t { psa_cipher_operation_t operation; }; - static void ptls_mbedtls_cipher_init(ptls_cipher_context_t *_ctx, const void *iv) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; @@ -222,12 +218,11 @@ static void ptls_mbedtls_cipher_init(ptls_cipher_context_t *_ctx, const void *iv memset(&ctx->operation, 0, sizeof(ctx->operation)); if (ctx->is_enc) { (void)psa_cipher_encrypt_setup(&ctx->operation, ctx->key, ctx->alg); - } - else { + } else { (void)psa_cipher_decrypt_setup(&ctx->operation, ctx->key, ctx->alg); } if (ctx->iv_length > 0) { - (void)psa_cipher_set_iv(&ctx->operation, (const uint8_t*)iv, ctx->iv_length); + (void)psa_cipher_set_iv(&ctx->operation, (const uint8_t *)iv, ctx->iv_length); } ctx->is_op_in_progress = 1; } @@ -237,7 +232,7 @@ static void ptls_mbedtls_cipher_transform(ptls_cipher_context_t *_ctx, void *out struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; size_t outlen = 0; - (void) psa_cipher_update(&ctx->operation, (const uint8_t*)input, len, (uint8_t*)output, len, &outlen); + (void)psa_cipher_update(&ctx->operation, (const uint8_t *)input, len, (uint8_t *)output, len, &outlen); } static void ptls_mbedtls_cipher_dispose(ptls_cipher_context_t *_ctx) @@ -250,28 +245,26 @@ static void ptls_mbedtls_cipher_dispose(ptls_cipher_context_t *_ctx) psa_destroy_key(ctx->key); } -static int ptls_mbedtls_cipher_setup_key(mbedtls_svc_key_id_t* key_id, int is_enc, psa_algorithm_t alg, psa_key_type_t key_type, - size_t key_bits, const uint8_t * key_bytes) +static int ptls_mbedtls_cipher_setup_key(mbedtls_svc_key_id_t *key_id, int is_enc, psa_algorithm_t alg, psa_key_type_t key_type, + size_t key_bits, const uint8_t *key_bytes) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; int ret = 0; - psa_set_key_usage_flags(&attributes, - (is_enc)?PSA_KEY_USAGE_ENCRYPT:PSA_KEY_USAGE_DECRYPT); + psa_set_key_usage_flags(&attributes, (is_enc) ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, key_type); psa_set_key_bits(&attributes, key_bits); /* Import key */ - if (psa_import_key(&attributes, key_bytes, key_bits / 8, - key_id) != PSA_SUCCESS) { + if (psa_import_key(&attributes, key_bytes, key_bits / 8, key_id) != PSA_SUCCESS) { ret = PTLS_ERROR_LIBRARY; } return ret; } -static int ptls_mbedtls_cipher_setup_crypto(ptls_cipher_context_t* _ctx, int is_enc, const void* key_bytes, - psa_algorithm_t alg, size_t iv_length, psa_key_type_t key_type, size_t key_bits) +static int ptls_mbedtls_cipher_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, + size_t iv_length, psa_key_type_t key_type, size_t key_bits) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; int ret = 0; @@ -287,7 +280,6 @@ static int ptls_mbedtls_cipher_setup_crypto(ptls_cipher_context_t* _ctx, int is_ ctx->super.do_init = ptls_mbedtls_cipher_init; ctx->super.do_transform = NULL; - if (ret == 0) { ctx->super.do_transform = ptls_mbedtls_cipher_transform; } @@ -296,75 +288,66 @@ static int ptls_mbedtls_cipher_setup_crypto(ptls_cipher_context_t* _ctx, int is_ } /* -* Implementation of AES128_ECB using the PSA API: -*/ + * Implementation of AES128_ECB using the PSA API: + */ static int ptls_mbedtls_cipher_setup_aes128_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, - PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 128); + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 128); } -ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { - "AES128-ECB", - PTLS_AES128_KEY_SIZE, - PTLS_AES_BLOCK_SIZE, - 0 /* iv size */, - sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_aes128_ecb}; +ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = {"AES128-ECB", + PTLS_AES128_KEY_SIZE, + PTLS_AES_BLOCK_SIZE, + 0 /* iv size */, + sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_aes128_ecb}; /* -* Implementation of AES256_ECB using the PSA API: -*/ + * Implementation of AES256_ECB using the PSA API: + */ static int ptls_mbedtls_cipher_setup_aes256_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, - PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 256); + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 256); } -ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { - "AES256-ECB", - PTLS_AES128_KEY_SIZE, - PTLS_AES_BLOCK_SIZE, - 0 /* iv size */, - sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_aes256_ecb}; +ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = {"AES256-ECB", + PTLS_AES128_KEY_SIZE, + PTLS_AES_BLOCK_SIZE, + 0 /* iv size */, + sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_aes256_ecb}; /* -* Implementation of AES128_CTR using the PSA API: -*/ + * Implementation of AES128_CTR using the PSA API: + */ static int ptls_mbedtls_cipher_setup_aes128_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, - PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 128); + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 128); } -ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { - "AES128-CTR", - PTLS_AES128_KEY_SIZE, - PTLS_AES_BLOCK_SIZE, - 16 /* iv size */, - sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_aes128_ctr}; +ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = {"AES128-CTR", + PTLS_AES128_KEY_SIZE, + PTLS_AES_BLOCK_SIZE, + 16 /* iv size */, + sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_aes128_ctr}; /* -* Implementation of AES128_CTR using the PSA API: -*/ + * Implementation of AES128_CTR using the PSA API: + */ static int ptls_mbedtls_cipher_setup_aes256_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, - PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 256); + return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 256); } -ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { - "AES128-CTR", - PTLS_AES256_KEY_SIZE, - PTLS_AES_BLOCK_SIZE, - 16 /* iv size */, - sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_aes256_ctr}; - +ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = {"AES128-CTR", + PTLS_AES256_KEY_SIZE, + PTLS_AES_BLOCK_SIZE, + 16 /* iv size */, + sizeof(struct st_ptls_mbedtls_cipher_context_t), + ptls_mbedtls_cipher_setup_aes256_ctr}; #if 0 /* @@ -383,9 +366,9 @@ ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { ptls_mbedtls_cipher_setup_crypto_chacha20}; #else /* Implementation of ChaCha20 using the low level ChaCha20 API. -* TODO: remove this and the reference to chacha20.h as soon as -* the IV bug in the generic implementation is fixed. -*/ + * TODO: remove this and the reference to chacha20.h as soon as + * the IV bug in the generic implementation is fixed. + */ struct st_ptls_mbedtls_chacha20_context_t { ptls_cipher_context_t super; mbedtls_chacha20_context mctx; @@ -394,18 +377,17 @@ struct st_ptls_mbedtls_chacha20_context_t { static void ptls_mbedtls_chacha20_init(ptls_cipher_context_t *_ctx, const void *v_iv) { struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; - const uint8_t* iv = (const uint8_t*)v_iv; + const uint8_t *iv = (const uint8_t *)v_iv; uint32_t ctr = iv[0] | ((uint32_t)iv[1] << 8) | ((uint32_t)iv[2] << 16) | ((uint32_t)iv[3] << 24); - (void)mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t*)(iv+4), ctr); + (void)mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t *)(iv + 4), ctr); } static void ptls_mbedtls_chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) { struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; - if (mbedtls_chacha20_update(&ctx->mctx, len, - (const uint8_t*)input, (uint8_t*)output) != 0) { + if (mbedtls_chacha20_update(&ctx->mctx, len, (const uint8_t *)input, (uint8_t *)output) != 0) { memset(output, 0, len); } } @@ -422,7 +404,7 @@ static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx int ret = 0; mbedtls_chacha20_init(&ctx->mctx); - ret = mbedtls_chacha20_setkey(&ctx->mctx, (const uint8_t*)key); + ret = mbedtls_chacha20_setkey(&ctx->mctx, (const uint8_t *)key); ctx->super.do_dispose = ptls_mbedtls_chacha20_dispose; ctx->super.do_init = ptls_mbedtls_chacha20_init; @@ -435,44 +417,47 @@ static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx return ret; } -ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { - "CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_chacha20_context_t), - ptls_mbedtls_cipher_setup_crypto_chacha20}; +ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = {"CHACHA20", + PTLS_CHACHA20_KEY_SIZE, + 1 /* block size */, + PTLS_CHACHA20_IV_SIZE, + sizeof(struct st_ptls_mbedtls_chacha20_context_t), + ptls_mbedtls_cipher_setup_crypto_chacha20}; #endif /* Definitions of AEAD algorithms. -* -* For the picotls API, AEAD algorithms are created by calling: -* -* ptls_aead_context_t *ptls_aead_new(ptls_aead_algorithm_t *aead, -* ptls_hash_algorithm_t *hash, int is_enc, const void *secret, -* const char *label_prefix) -* That procedure will allocate memory and create keys, and then call -* a provider specific function: -* -* if (aead->setup_crypto(ctx, is_enc, key, iv) != 0) { -* free(ctx); -* return NULL; -* } -* -* The function will finish completing the aead structure, perform -* initialization, and then document the function pointers: -* -* ctx->super.dispose_crypto: release all resourc -* ctx->super.do_get_iv: return IV -* ctx->super.do_set_iv: set IV value -* ctx->super.do_decrypt: decrypt function -* ctx->super.do_encrypt_init: start encrypting one message -* ctx->super.do_encrypt_update: feed more ciphertext to descriptor -* ctx->super.do_encrypt_final: finalize encryption, including AEAD checksum -* ctx->super.do_encrypt: single shot variant of init/update/final -* ctx->super.do_encrypt_v: scatter gather version of do encrypt -* -* The aead context also documents the underlying "ECB" and "CTR" modes. -* In QUIC, these are used for PN encryption. -* -* TODO: declare other algorithms besides AES128_GCM -*/ + * + * For the picotls API, AEAD algorithms are created by calling: + * + * ptls_aead_context_t *ptls_aead_new(ptls_aead_algorithm_t *aead, + * ptls_hash_algorithm_t *hash, int is_enc, const void *secret, + * const char *label_prefix) + * That procedure will allocate memory and create keys, and then call + * a provider specific function: + * + * if (aead->setup_crypto(ctx, is_enc, key, iv) != 0) { + * free(ctx); + * return NULL; + * } + * + * The function will finish completing the aead structure, perform + * initialization, and then document the function pointers: + * + * ctx->super.dispose_crypto: release all resourc + * ctx->super.do_get_iv: return IV + * ctx->super.do_set_iv: set IV value + * ctx->super.do_decrypt: decrypt function + * ctx->super.do_encrypt_init: start encrypting one message + * ctx->super.do_encrypt_update: feed more ciphertext to descriptor + * ctx->super.do_encrypt_final: finalize encryption, including AEAD checksum + * ctx->super.do_encrypt: single shot variant of init/update/final + * ctx->super.do_encrypt_v: scatter gather version of do encrypt + * + * The aead context also documents the underlying "ECB" and "CTR" modes. + * In QUIC, these are used for PN encryption. + * + * TODO: declare other algorithms besides AES128_GCM + */ struct ptls_mbedtls_aead_param_t { uint8_t static_iv[PTLS_MAX_IV_SIZE]; @@ -488,10 +473,9 @@ struct ptls_mbedtls_aead_context_t { struct ptls_mbedtls_aead_param_t mctx; }; -void ptls_mbedtls_aead_dispose_crypto(struct st_ptls_aead_context_t* _ctx) +void ptls_mbedtls_aead_dispose_crypto(struct st_ptls_aead_context_t *_ctx) { - struct ptls_mbedtls_aead_context_t* ctx = - (struct ptls_mbedtls_aead_context_t*)_ctx; + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; if (ctx->mctx.is_op_in_progress) { psa_aead_abort(&ctx->mctx.op); ctx->mctx.is_op_in_progress = 0; @@ -499,31 +483,27 @@ void ptls_mbedtls_aead_dispose_crypto(struct st_ptls_aead_context_t* _ctx) psa_destroy_key(ctx->mctx.key); } - static void ptls_mbedtls_aead_get_iv(ptls_aead_context_t *_ctx, void *iv) { - struct ptls_mbedtls_aead_context_t* ctx = - (struct ptls_mbedtls_aead_context_t*)_ctx; + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; memcpy(iv, ctx->mctx.static_iv, ctx->super.algo->iv_size); } static void ptls_mbedtls_aead_set_iv(ptls_aead_context_t *_ctx, const void *iv) { - struct ptls_mbedtls_aead_context_t* ctx = - (struct ptls_mbedtls_aead_context_t*)_ctx; + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; memcpy(ctx->mctx.static_iv, iv, ctx->super.algo->iv_size); } -void ptls_mbedtls_aead_do_encrypt_init(struct st_ptls_aead_context_t* _ctx, uint64_t seq, const void* aad, size_t aadlen) +void ptls_mbedtls_aead_do_encrypt_init(struct st_ptls_aead_context_t *_ctx, uint64_t seq, const void *aad, size_t aadlen) { - struct ptls_mbedtls_aead_context_t* ctx = - (struct ptls_mbedtls_aead_context_t*)_ctx; + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; psa_status_t status; if (ctx->mctx.is_op_in_progress) { - psa_aead_abort(&ctx->mctx.op); /* required on errors, harmless on success */ + psa_aead_abort(&ctx->mctx.op); /* required on errors, harmless on success */ ctx->mctx.is_op_in_progress = 0; } @@ -544,31 +524,29 @@ void ptls_mbedtls_aead_do_encrypt_init(struct st_ptls_aead_context_t* _ctx, uint } if (status != PSA_SUCCESS) { - psa_aead_abort(&ctx->mctx.op); /* required on errors, harmless on success */ + psa_aead_abort(&ctx->mctx.op); /* required on errors, harmless on success */ ctx->mctx.is_op_in_progress = 0; } } -size_t ptls_mbedtls_aead_do_encrypt_update(struct st_ptls_aead_context_t* _ctx, void* output, const void* input, size_t inlen) +size_t ptls_mbedtls_aead_do_encrypt_update(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen) { size_t olen = 0; - struct ptls_mbedtls_aead_context_t* ctx = - (struct ptls_mbedtls_aead_context_t*)_ctx; + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; if (ctx->mctx.is_op_in_progress) { size_t available = inlen + ctx->mctx.extra_bytes; - psa_status_t status = psa_aead_update(&ctx->mctx.op, input, inlen, (uint8_t *)output, available + ctx->super.algo->tag_size, &olen); + psa_status_t status = + psa_aead_update(&ctx->mctx.op, input, inlen, (uint8_t *)output, available + ctx->super.algo->tag_size, &olen); if (status == PSA_SUCCESS) { if (olen < available) { ctx->mctx.extra_bytes = available - olen; - } - else { + } else { ctx->mctx.extra_bytes = 0; } - } - else { - psa_aead_abort(&ctx->mctx.op); /* required on errors */ + } else { + psa_aead_abort(&ctx->mctx.op); /* required on errors */ ctx->mctx.is_op_in_progress = 0; } } @@ -576,38 +554,36 @@ size_t ptls_mbedtls_aead_do_encrypt_update(struct st_ptls_aead_context_t* _ctx, return olen; } -size_t ptls_mbedtls_aead_do_encrypt_final(struct st_ptls_aead_context_t* _ctx, void* output) +size_t ptls_mbedtls_aead_do_encrypt_final(struct st_ptls_aead_context_t *_ctx, void *output) { size_t olen = 0; - struct ptls_mbedtls_aead_context_t* ctx = - (struct ptls_mbedtls_aead_context_t*)_ctx; + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; if (ctx->mctx.is_op_in_progress) { unsigned char tag[PSA_AEAD_TAG_MAX_SIZE]; size_t olen_tag = 0; size_t available = ctx->mctx.extra_bytes; - uint8_t* p = (uint8_t*)output; - psa_status_t status = psa_aead_finish(&ctx->mctx.op, p, available + ctx->super.algo->tag_size, &olen, - tag, sizeof(tag), &olen_tag); + uint8_t *p = (uint8_t *)output; + psa_status_t status = + psa_aead_finish(&ctx->mctx.op, p, available + ctx->super.algo->tag_size, &olen, tag, sizeof(tag), &olen_tag); if (status == PSA_SUCCESS) { p += olen; memcpy(p, tag, ctx->super.algo->tag_size); olen += ctx->super.algo->tag_size; - } - else { - psa_aead_abort(&ctx->mctx.op); /* required on errors */ + } else { + psa_aead_abort(&ctx->mctx.op); /* required on errors */ } ctx->mctx.is_op_in_progress = 0; } - return(olen); + return (olen); } -void ptls_mbedtls_aead_do_encrypt_v(struct st_ptls_aead_context_t* _ctx, void* output, ptls_iovec_t* input, size_t incnt, uint64_t seq, - const void* aad, size_t aadlen) +void ptls_mbedtls_aead_do_encrypt_v(struct st_ptls_aead_context_t *_ctx, void *output, ptls_iovec_t *input, size_t incnt, + uint64_t seq, const void *aad, size_t aadlen) { - unsigned char* p = (uint8_t*)output; + unsigned char *p = (uint8_t *)output; ptls_mbedtls_aead_do_encrypt_init(_ctx, seq, aad, aadlen); @@ -618,29 +594,28 @@ void ptls_mbedtls_aead_do_encrypt_v(struct st_ptls_aead_context_t* _ctx, void* o (void)ptls_mbedtls_aead_do_encrypt_final(_ctx, p); } -void ptls_mbedtls_aead_do_encrypt(struct st_ptls_aead_context_t* _ctx, void* output, const void* input, size_t inlen, uint64_t seq, - const void* aad, size_t aadlen, ptls_aead_supplementary_encryption_t* supp) +void ptls_mbedtls_aead_do_encrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq, + const void *aad, size_t aadlen, ptls_aead_supplementary_encryption_t *supp) { ptls_iovec_t in_v; - in_v.base = (uint8_t*)input; + in_v.base = (uint8_t *)input; in_v.len = inlen; ptls_mbedtls_aead_do_encrypt_v(_ctx, output, &in_v, 1, seq, aad, aadlen); } -size_t ptls_mbedtls_aead_do_decrypt(struct st_ptls_aead_context_t* _ctx, void* output, const void* input, size_t inlen, uint64_t seq, - const void* aad, size_t aadlen) +size_t ptls_mbedtls_aead_do_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, + uint64_t seq, const void *aad, size_t aadlen) { size_t o_len = 0; uint8_t iv[PTLS_MAX_IV_SIZE]; - struct ptls_mbedtls_aead_context_t* ctx = - (struct ptls_mbedtls_aead_context_t*)_ctx; + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; psa_status_t status; /* set the nonce. */ ptls_aead__build_iv(ctx->super.algo, iv, ctx->mctx.static_iv, seq); - status = psa_aead_decrypt(ctx->mctx.key, ctx->mctx.alg, iv, ctx->super.algo->iv_size, (uint8_t*)aad, aadlen, - (uint8_t*)input, inlen, (uint8_t*)output, inlen, &o_len); + status = psa_aead_decrypt(ctx->mctx.key, ctx->mctx.alg, iv, ctx->super.algo->iv_size, (uint8_t *)aad, aadlen, (uint8_t *)input, + inlen, (uint8_t *)output, inlen, &o_len); if (status != PSA_SUCCESS) { o_len = inlen + 1; } @@ -648,12 +623,10 @@ size_t ptls_mbedtls_aead_do_decrypt(struct st_ptls_aead_context_t* _ctx, void* o } static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv, - psa_algorithm_t psa_alg, size_t key_bits, psa_key_type_t key_type) + psa_algorithm_t psa_alg, size_t key_bits, psa_key_type_t key_type) { int ret = 0; - struct ptls_mbedtls_aead_context_t* ctx = - (struct ptls_mbedtls_aead_context_t*)_ctx; - + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; /* set mbed specific context to NULL, just to be sure */ memset(&ctx->mctx, 0, sizeof(struct ptls_mbedtls_aead_param_t)); @@ -662,14 +635,12 @@ static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, /* Initialize the key attributes */ if (ret == 0) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_set_key_usage_flags(&attributes, - (is_enc)?PSA_KEY_USAGE_ENCRYPT:PSA_KEY_USAGE_DECRYPT); + psa_set_key_usage_flags(&attributes, (is_enc) ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, ctx->mctx.alg); psa_set_key_type(&attributes, key_type); psa_set_key_bits(&attributes, key_bits); /* Import key */ - if (psa_import_key(&attributes, key_bytes, key_bits / 8, - &ctx->mctx.key) != PSA_SUCCESS) { + if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->mctx.key) != PSA_SUCCESS) { ret = PTLS_ERROR_LIBRARY; } } @@ -678,8 +649,7 @@ static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, /* Store the static IV */ if (ctx->super.algo->iv_size > PTLS_MAX_IV_SIZE) { ret = PTLS_ERROR_LIBRARY; - } - else { + } else { memcpy(ctx->mctx.static_iv, iv, ctx->super.algo->iv_size); ctx->mctx.is_op_in_progress = 0; } @@ -693,8 +663,7 @@ static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, ctx->super.do_encrypt_final = ptls_mbedtls_aead_do_encrypt_final; ctx->super.do_encrypt = ptls_mbedtls_aead_do_encrypt; ctx->super.do_encrypt_v = ptls_mbedtls_aead_do_encrypt_v; - } - else { + } else { ctx->super.do_decrypt = ptls_mbedtls_aead_do_decrypt; } ctx->super.dispose_crypto = ptls_mbedtls_aead_dispose_crypto; @@ -705,112 +674,105 @@ static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, return ret; } -static int ptls_mbedtls_aead_setup_aes128gcm(ptls_aead_context_t* _ctx, int is_enc, const void* key_bytes, const void* iv) +static int ptls_mbedtls_aead_setup_aes128gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) { return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 128, PSA_KEY_TYPE_AES); } -ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = { - "AES128-GCM", - PTLS_AESGCM_CONFIDENTIALITY_LIMIT, - PTLS_AESGCM_INTEGRITY_LIMIT, - &ptls_mbedtls_aes128ctr, - &ptls_mbedtls_aes128ecb, - PTLS_AES128_KEY_SIZE, - PTLS_AESGCM_IV_SIZE, - PTLS_AESGCM_TAG_SIZE, - {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE}, - 0, - 0, - sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_aes128gcm -}; +ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = {"AES128-GCM", + PTLS_AESGCM_CONFIDENTIALITY_LIMIT, + PTLS_AESGCM_INTEGRITY_LIMIT, + &ptls_mbedtls_aes128ctr, + &ptls_mbedtls_aes128ecb, + PTLS_AES128_KEY_SIZE, + PTLS_AESGCM_IV_SIZE, + PTLS_AESGCM_TAG_SIZE, + {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + ptls_mbedtls_aead_setup_aes128gcm}; ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256 = {.id = PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, -.name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256, -.aead = &ptls_mbedtls_aes128gcm, -.hash = &ptls_mbedtls_sha256}; + .name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256, + .aead = &ptls_mbedtls_aes128gcm, + .hash = &ptls_mbedtls_sha256}; -static int ptls_mbedtls_aead_setup_aes256gcm(ptls_aead_context_t* _ctx, int is_enc, const void* key_bytes, const void* iv) +static int ptls_mbedtls_aead_setup_aes256gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) { return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 256, PSA_KEY_TYPE_AES); } -ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = { - "AES256-GCM", - PTLS_AESGCM_CONFIDENTIALITY_LIMIT, - PTLS_AESGCM_INTEGRITY_LIMIT, - &ptls_mbedtls_aes256ctr, - &ptls_mbedtls_aes256ecb, - PTLS_AES256_KEY_SIZE, - PTLS_AESGCM_IV_SIZE, - PTLS_AESGCM_TAG_SIZE, - {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE}, - 0, - 0, - sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_aes256gcm -}; +ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = {"AES256-GCM", + PTLS_AESGCM_CONFIDENTIALITY_LIMIT, + PTLS_AESGCM_INTEGRITY_LIMIT, + &ptls_mbedtls_aes256ctr, + &ptls_mbedtls_aes256ecb, + PTLS_AES256_KEY_SIZE, + PTLS_AESGCM_IV_SIZE, + PTLS_AESGCM_TAG_SIZE, + {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + ptls_mbedtls_aead_setup_aes256gcm}; -ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = { - .id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, - .name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384, - .aead = &ptls_mbedtls_aes256gcm, - .hash = &ptls_mbedtls_sha384}; +ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = {.id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, + .name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384, + .aead = &ptls_mbedtls_aes256gcm, + .hash = &ptls_mbedtls_sha384}; -static int ptls_mbedtls_aead_setup_chacha20poly1305(ptls_aead_context_t* _ctx, int is_enc, const void* key_bytes, const void* iv) +static int ptls_mbedtls_aead_setup_chacha20poly1305(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) { return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_CHACHA20_POLY1305, 256, PSA_KEY_TYPE_CHACHA20); } -ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = { - "CHACHA20-POLY1305", - PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT, - PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT, - &ptls_mbedtls_chacha20, - NULL, - PTLS_CHACHA20_KEY_SIZE, - PTLS_CHACHA20POLY1305_IV_SIZE, - PTLS_CHACHA20POLY1305_TAG_SIZE, - {PTLS_TLS12_CHACHAPOLY_FIXED_IV_SIZE, PTLS_TLS12_CHACHAPOLY_RECORD_IV_SIZE}, - 0, - 0, - sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_chacha20poly1305 -}; +ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = {"CHACHA20-POLY1305", + PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT, + PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT, + &ptls_mbedtls_chacha20, + NULL, + PTLS_CHACHA20_KEY_SIZE, + PTLS_CHACHA20POLY1305_IV_SIZE, + PTLS_CHACHA20POLY1305_TAG_SIZE, + {PTLS_TLS12_CHACHAPOLY_FIXED_IV_SIZE, PTLS_TLS12_CHACHAPOLY_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + ptls_mbedtls_aead_setup_chacha20poly1305}; ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256, -.name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256, -.aead = &ptls_mbedtls_chacha20poly1305, -.hash = &ptls_mbedtls_sha256}; + .name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256, + .aead = &ptls_mbedtls_chacha20poly1305, + .hash = &ptls_mbedtls_sha256}; /* Key exchange algorithms. -* The Picotls framework defines these algorithms as ptls_key_exchange_algorithm_t, -* a structure containing two function pointers: -* -* int (*create)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx); -* int (*exchange)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, -* ptls_iovec_t peerkey); -* The "create" call is used on the client. It documents the ptls_key_exchange_context_t, which contains -* the public key prepared by the client, as an iovec, and a function pointer: -* -* int (*on_exchange)(struct st_ptls_key_exchange_context_t **keyex, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey); -* -* The public key of the client is passed to the server an ends up as "peerkey" argument to the (exchange) function. -* That function documents the server's public key, and the secret computed by combining server and client key. -* -* When the client receives the server hello, the stack calls the "on_exchange" callback, passing the context -* previously created by the client and the public key of the peer, so the client can compute its own -* version of the secret. -* -* The following code uses the MbedTLS PSA API to create the "create", "exchange" and "on_exchange" functions. -*/ - -#define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 + * The Picotls framework defines these algorithms as ptls_key_exchange_algorithm_t, + * a structure containing two function pointers: + * + * int (*create)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx); + * int (*exchange)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, + * ptls_iovec_t peerkey); + * The "create" call is used on the client. It documents the ptls_key_exchange_context_t, which contains + * the public key prepared by the client, as an iovec, and a function pointer: + * + * int (*on_exchange)(struct st_ptls_key_exchange_context_t **keyex, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey); + * + * The public key of the client is passed to the server an ends up as "peerkey" argument to the (exchange) function. + * That function documents the server's public key, and the secret computed by combining server and client key. + * + * When the client receives the server hello, the stack calls the "on_exchange" callback, passing the context + * previously created by the client and the public key of the peer, so the client can compute its own + * version of the secret. + * + * The following code uses the MbedTLS PSA API to create the "create", "exchange" and "on_exchange" functions. + */ + +#define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 struct ptls_mbedtls_key_exchange_context_t { ptls_key_exchange_context_t super; - psa_algorithm_t psa_alg; + psa_algorithm_t psa_alg; psa_ecc_family_t curve; size_t curve_bits; size_t secret_size; @@ -819,17 +781,17 @@ struct ptls_mbedtls_key_exchange_context_t { }; /* Set a private key for key exchange. For now, we only support ECC -*/ + */ -static int ptls_mbedtls_key_exchange_set_private_key(psa_key_id_t * private_key, - psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits) +static int ptls_mbedtls_key_exchange_set_private_key(psa_key_id_t *private_key, psa_algorithm_t psa_alg, psa_ecc_family_t curve, + size_t curve_bits) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; int ret = 0; psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&attributes, psa_alg); - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve) ); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); psa_set_key_bits(&attributes, curve_bits); if (psa_generate_key(&attributes, private_key) != 0) { ret = -1; @@ -848,24 +810,23 @@ size_t output_size, size_t * output_length); */ -int ptls_mbedtls_key_exchange_on_exchange(struct st_ptls_key_exchange_context_t** _pctx, int release, ptls_iovec_t* secret, ptls_iovec_t peerkey) +int ptls_mbedtls_key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_pctx, int release, ptls_iovec_t *secret, + ptls_iovec_t peerkey) { int ret = 0; struct ptls_mbedtls_key_exchange_context_t *keyex = (struct ptls_mbedtls_key_exchange_context_t *)*_pctx; if (secret != NULL) { - uint8_t* secbytes = (uint8_t*)malloc(keyex->secret_size); + uint8_t *secbytes = (uint8_t *)malloc(keyex->secret_size); if (secbytes == NULL) { ret = PTLS_ERROR_NO_MEMORY; - } - else { + } else { size_t olen; - if (psa_raw_key_agreement(keyex->psa_alg, keyex->private_key, (const uint8_t*)peerkey.base, peerkey.len, - secbytes, keyex->secret_size, &olen) == 0) { + if (psa_raw_key_agreement(keyex->psa_alg, keyex->private_key, (const uint8_t *)peerkey.base, peerkey.len, secbytes, + keyex->secret_size, &olen) == 0) { *secret = ptls_iovec_init(secbytes, keyex->secret_size); - } - else { + } else { free(secbytes); ret = PTLS_ERROR_LIBRARY; } @@ -882,8 +843,8 @@ int ptls_mbedtls_key_exchange_on_exchange(struct st_ptls_key_exchange_context_t* return ret; } -int ptls_mbedtls_key_exchange_create(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_key_exchange_context_t** ctx, - psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) +int ptls_mbedtls_key_exchange_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx, + psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) { struct ptls_mbedtls_key_exchange_context_t *keyex; size_t olen = 0; @@ -896,7 +857,7 @@ int ptls_mbedtls_key_exchange_create(const struct st_ptls_key_exchange_algorithm keyex->curve_bits = curve_bits; keyex->secret_size = secret_size; /* Initialize the private key and format the public key */ - if (ptls_mbedtls_key_exchange_set_private_key(&keyex->private_key, psa_alg, curve, curve_bits) != 0){ + if (ptls_mbedtls_key_exchange_set_private_key(&keyex->private_key, psa_alg, curve, curve_bits) != 0) { free(keyex); *ctx = NULL; return PTLS_ERROR_LIBRARY; @@ -908,30 +869,31 @@ int ptls_mbedtls_key_exchange_create(const struct st_ptls_key_exchange_algorithm *ctx = NULL; return PTLS_ERROR_LIBRARY; } - keyex->super.pubkey= ptls_iovec_init(keyex->pub, olen); + keyex->super.pubkey = ptls_iovec_init(keyex->pub, olen); /* Initialize the ptls exchange context */ keyex->super.algo = algo; keyex->super.on_exchange = ptls_mbedtls_key_exchange_on_exchange; - *ctx = (ptls_key_exchange_context_t*)keyex; + *ctx = (ptls_key_exchange_context_t *)keyex; return 0; } -static int ptls_mbedtls_key_exchange_exchange(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_iovec_t* pubkey, ptls_iovec_t* secret, - ptls_iovec_t peerkey, psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) +static int ptls_mbedtls_key_exchange_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, + ptls_iovec_t *secret, ptls_iovec_t peerkey, psa_algorithm_t psa_alg, + psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) { /* generate a local private key for the selected algorithm */ psa_key_id_t private_key; size_t pubkey_len; - uint8_t* pubkey_bytes = NULL; + uint8_t *pubkey_bytes = NULL; size_t secret_len; - uint8_t* secret_bytes = (uint8_t*)malloc(secret_size); + uint8_t *secret_bytes = (uint8_t *)malloc(secret_size); int ret = 0; if (secret_bytes == NULL) { return PTLS_ERROR_NO_MEMORY; } - pubkey_bytes = (uint8_t*)malloc(PTLS_MBEDTLS_ECDH_PUBKEY_MAX); - if (pubkey_bytes == NULL){ + pubkey_bytes = (uint8_t *)malloc(PTLS_MBEDTLS_ECDH_PUBKEY_MAX); + if (pubkey_bytes == NULL) { free(secret_bytes); return PTLS_ERROR_NO_MEMORY; } @@ -944,12 +906,11 @@ static int ptls_mbedtls_key_exchange_exchange(const struct st_ptls_key_exchange_ /* Export public key and call key agrement function */ if (psa_export_public_key(private_key, pubkey_bytes, PTLS_MBEDTLS_ECDH_PUBKEY_MAX, &pubkey_len) == 0 && - psa_raw_key_agreement(psa_alg, private_key, (const uint8_t*)peerkey.base, peerkey.len, - secret_bytes, secret_size, &secret_len) == 0) { + psa_raw_key_agreement(psa_alg, private_key, (const uint8_t *)peerkey.base, peerkey.len, secret_bytes, secret_size, + &secret_len) == 0) { *secret = ptls_iovec_init(secret_bytes, secret_len); *pubkey = ptls_iovec_init(pubkey_bytes, pubkey_len); - } - else { + } else { free(secret_bytes); free(pubkey_bytes); return PTLS_ERROR_LIBRARY; @@ -961,41 +922,37 @@ static int ptls_mbedtls_key_exchange_exchange(const struct st_ptls_key_exchange_ } /* Instantiation of the generic key exchange API with secp256r1 -*/ -static int ptls_mbedtls_secp256r1_create(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_key_exchange_context_t** ctx) + */ +static int ptls_mbedtls_secp256r1_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { - return ptls_mbedtls_key_exchange_create(algo, ctx, - PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); + return ptls_mbedtls_key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); } -static int ptls_mbedtls_secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_iovec_t* pubkey, ptls_iovec_t* secret, - ptls_iovec_t peerkey) +static int ptls_mbedtls_secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, + ptls_iovec_t *secret, ptls_iovec_t peerkey) { - return ptls_mbedtls_key_exchange_exchange(algo, pubkey, secret, peerkey, - PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); + return ptls_mbedtls_key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); } ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = {.id = PTLS_GROUP_SECP256R1, -.name = PTLS_GROUP_NAME_SECP256R1, -.create = ptls_mbedtls_secp256r1_create, -.exchange = ptls_mbedtls_secp256r1_exchange}; + .name = PTLS_GROUP_NAME_SECP256R1, + .create = ptls_mbedtls_secp256r1_create, + .exchange = ptls_mbedtls_secp256r1_exchange}; /* Instantiation of the generic key exchange API with x25519 -*/ -static int ptls_mbedtls_x25519_create(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_key_exchange_context_t** ctx) + */ +static int ptls_mbedtls_x25519_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { - return ptls_mbedtls_key_exchange_create(algo, ctx, - PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); + return ptls_mbedtls_key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); } -static int ptls_mbedtls_x25519_exchange(const struct st_ptls_key_exchange_algorithm_t* algo, ptls_iovec_t* pubkey, ptls_iovec_t* secret, - ptls_iovec_t peerkey) +static int ptls_mbedtls_x25519_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, + ptls_iovec_t *secret, ptls_iovec_t peerkey) { - return ptls_mbedtls_key_exchange_exchange(algo, pubkey, secret, peerkey, - PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); + return ptls_mbedtls_key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); } ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = {.id = PTLS_GROUP_X25519, -.name = PTLS_GROUP_NAME_X25519, -.create = ptls_mbedtls_x25519_create, -.exchange = ptls_mbedtls_x25519_exchange}; + .name = PTLS_GROUP_NAME_X25519, + .create = ptls_mbedtls_x25519_create, + .exchange = ptls_mbedtls_x25519_exchange}; diff --git a/t/ptls_mbedtls.c b/t/ptls_mbedtls.c index 61815b016..7bd44a23b 100644 --- a/t/ptls_mbedtls.c +++ b/t/ptls_mbedtls.c @@ -1,24 +1,24 @@ /* -* Copyright (c) 2023, Christian Huitema -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ + * Copyright (c) 2023, Christian Huitema + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ #ifdef _WINDOWS #include "wincompat.h" @@ -39,14 +39,14 @@ static int random_trial() { - /* The random test is just trying to check that we call the API properly. - * This is done by getting a vector of 1021 bytes, computing the sum of - * all values, and comparing to theoretical min and max, - * computed as average +- 8*standard deviation for sum of 1021 terms. - * 8 random deviations results in an extremely low probability of random - * failure. - * Note that this does not actually test the random generator. - */ + /* The random test is just trying to check that we call the API properly. + * This is done by getting a vector of 1021 bytes, computing the sum of + * all values, and comparing to theoretical min and max, + * computed as average +- 8*standard deviation for sum of 1021 terms. + * 8 random deviations results in an extremely low probability of random + * failure. + * Note that this does not actually test the random generator. + */ uint8_t buf[1021]; uint64_t sum = 0; @@ -74,10 +74,10 @@ static void test_random(void) ok(!!"success"); } -static int hash_trial(ptls_hash_algorithm_t* algo, const uint8_t* input, size_t len1, size_t len2, uint8_t* final_hash) +static int hash_trial(ptls_hash_algorithm_t *algo, const uint8_t *input, size_t len1, size_t len2, uint8_t *final_hash) { int ret = 0; - ptls_hash_context_t* hash_ctx = algo->create(); + ptls_hash_context_t *hash_ctx = algo->create(); hash_ctx->update(hash_ctx, input, len1); if (len2 > 0) { @@ -88,11 +88,11 @@ static int hash_trial(ptls_hash_algorithm_t* algo, const uint8_t* input, size_t return ret; } -static int hash_reset_trial(ptls_hash_algorithm_t* algo, const uint8_t* input, size_t len1, size_t len2, - uint8_t* hash1, uint8_t* hash2) +static int hash_reset_trial(ptls_hash_algorithm_t *algo, const uint8_t *input, size_t len1, size_t len2, uint8_t *hash1, + uint8_t *hash2) { int ret = 0; - ptls_hash_context_t* hash_ctx = algo->create(); + ptls_hash_context_t *hash_ctx = algo->create(); hash_ctx->update(hash_ctx, input, len1); hash_ctx->final(hash_ctx, hash1, PTLS_HASH_FINAL_MODE_RESET); @@ -102,7 +102,7 @@ static int hash_reset_trial(ptls_hash_algorithm_t* algo, const uint8_t* input, s return ret; } -static int test_hash(ptls_hash_algorithm_t* algo, ptls_hash_algorithm_t* ref) +static int test_hash(ptls_hash_algorithm_t *algo, ptls_hash_algorithm_t *ref) { int ret = 0; uint8_t input[1234]; @@ -139,8 +139,7 @@ static int test_hash(ptls_hash_algorithm_t* algo, ptls_hash_algorithm_t* ref) if (ret == 0) { if (memcmp(hash1, href1, ref->digest_size) != 0) { ret = -1; - } - else if (memcmp(hash2, href2, ref->digest_size) != 0) { + } else if (memcmp(hash2, href2, ref->digest_size) != 0) { ret = -1; } } @@ -148,10 +147,11 @@ static int test_hash(ptls_hash_algorithm_t* algo, ptls_hash_algorithm_t* ref) return ret; } -static int cipher_trial(ptls_cipher_algorithm_t * cipher, const uint8_t * key, const uint8_t * iv, int is_enc, const uint8_t * v_in, uint8_t * v_out1, uint8_t * v_out2, size_t len) +static int cipher_trial(ptls_cipher_algorithm_t *cipher, const uint8_t *key, const uint8_t *iv, int is_enc, const uint8_t *v_in, + uint8_t *v_out1, uint8_t *v_out2, size_t len) { int ret = 0; - ptls_cipher_context_t* test_cipher = ptls_cipher_new(cipher, is_enc, key); + ptls_cipher_context_t *test_cipher = ptls_cipher_new(cipher, is_enc, key); if (test_cipher == NULL) { ret = -1; } else { @@ -169,7 +169,7 @@ static int cipher_trial(ptls_cipher_algorithm_t * cipher, const uint8_t * key, c return ret; } -static int test_cipher(ptls_cipher_algorithm_t * cipher, ptls_cipher_algorithm_t * cipher_ref) +static int test_cipher(ptls_cipher_algorithm_t *cipher, ptls_cipher_algorithm_t *cipher_ref) { uint8_t key[32]; uint8_t iv[16]; @@ -190,8 +190,7 @@ static int test_cipher(ptls_cipher_algorithm_t * cipher, ptls_cipher_algorithm_t if (ret == 0) { if (memcmp(v_out_1a, v_out_1b, 16) != 0) { ret = -1; - } - else if (memcmp(v_out_2a, v_out_2b, 16) != 0) { + } else if (memcmp(v_out_2a, v_out_2b, 16) != 0) { ret = -1; } } @@ -202,8 +201,7 @@ static int test_cipher(ptls_cipher_algorithm_t * cipher, ptls_cipher_algorithm_t if (ret == 0) { if (memcmp(v_out_1a, v_out_1d, 16) != 0) { ret = -1; - } - else if (memcmp(v_out_2d, v_in, 16) != 0) { + } else if (memcmp(v_out_2d, v_in, 16) != 0) { ret = -1; } } @@ -211,12 +209,12 @@ static int test_cipher(ptls_cipher_algorithm_t * cipher, ptls_cipher_algorithm_t return ret; } -static int label_test(ptls_hash_algorithm_t * hash, uint8_t * v_out, size_t o_len, const uint8_t * secret, - char const * label, char const * label_prefix) +static int label_test(ptls_hash_algorithm_t *hash, uint8_t *v_out, size_t o_len, const uint8_t *secret, char const *label, + char const *label_prefix) { uint8_t h_val_v[32]; - ptls_iovec_t h_val = { 0 }; - ptls_iovec_t s_vec = { 0 }; + ptls_iovec_t h_val = {0}; + ptls_iovec_t s_vec = {0}; s_vec.base = (uint8_t *)secret; s_vec.len = 32; h_val.base = h_val_v; @@ -227,13 +225,13 @@ static int label_test(ptls_hash_algorithm_t * hash, uint8_t * v_out, size_t o_le return 0; } -static int test_label(ptls_hash_algorithm_t* hash, ptls_hash_algorithm_t* ref) +static int test_label(ptls_hash_algorithm_t *hash, ptls_hash_algorithm_t *ref) { int ret = 0; uint8_t v_out[16], v_ref[16]; uint8_t secret[32]; - char const* label = "label"; - char const* label_prefix = "label_prefix"; + char const *label = "label"; + char const *label_prefix = "label_prefix"; memset(secret, 0x5e, sizeof(secret)); ret = label_test(hash, v_out, 16, secret, label, label_prefix); @@ -249,23 +247,21 @@ static int test_label(ptls_hash_algorithm_t* hash, ptls_hash_algorithm_t* ref) return ret; } -static int aead_trial(ptls_aead_algorithm_t * algo, ptls_hash_algorithm_t * hash, const uint8_t * secret, int is_enc, - const uint8_t * v_in, size_t len, uint8_t * aad, size_t aad_len, uint64_t seq, uint8_t * v_out, size_t * o_len) +static int aead_trial(ptls_aead_algorithm_t *algo, ptls_hash_algorithm_t *hash, const uint8_t *secret, int is_enc, + const uint8_t *v_in, size_t len, uint8_t *aad, size_t aad_len, uint64_t seq, uint8_t *v_out, size_t *o_len) { int ret = 0; - ptls_aead_context_t* aead = ptls_aead_new(algo, hash, is_enc, secret, "test_aead"); + ptls_aead_context_t *aead = ptls_aead_new(algo, hash, is_enc, secret, "test_aead"); if (aead == NULL) { ret = -1; - } - else{ + } else { if (is_enc) { *o_len = ptls_aead_encrypt(aead, v_out, v_in, len, seq, aad, aad_len); if (*o_len != len + algo->tag_size) { ret = -1; } - } - else { + } else { *o_len = ptls_aead_decrypt(aead, v_out, v_in, len, seq, aad, aad_len); if (*o_len != len - algo->tag_size) { ret = -1; @@ -276,7 +272,8 @@ static int aead_trial(ptls_aead_algorithm_t * algo, ptls_hash_algorithm_t * hash return ret; } -static int test_aead(ptls_aead_algorithm_t* algo, ptls_hash_algorithm_t* hash, ptls_aead_algorithm_t* ref, ptls_hash_algorithm_t* hash_ref) +static int test_aead(ptls_aead_algorithm_t *algo, ptls_hash_algorithm_t *hash, ptls_aead_algorithm_t *ref, + ptls_hash_algorithm_t *hash_ref) { uint8_t secret[64]; uint8_t v_in[1234]; @@ -395,7 +392,8 @@ static void test_aes256gcm_sha384(void) static void test_chacha20poly1305_sha256(void) { - if (test_aead(&ptls_mbedtls_chacha20poly1305, &ptls_mbedtls_sha256, &ptls_minicrypto_chacha20poly1305, &ptls_minicrypto_sha256) != 0) { + if (test_aead(&ptls_mbedtls_chacha20poly1305, &ptls_mbedtls_sha256, &ptls_minicrypto_chacha20poly1305, + &ptls_minicrypto_sha256) != 0) { ok(!"fail"); } ok(!!"success"); diff --git a/t/ptlsbench.c b/t/ptlsbench.c index 8fdb6fdb7..9e4bc1efd 100644 --- a/t/ptlsbench.c +++ b/t/ptlsbench.c @@ -281,11 +281,11 @@ static ptls_bench_entry_t aead_list[] = { {"openssl", "aes128gcm", &ptls_openssl_aes128gcm, &ptls_minicrypto_sha256, 1}, {"openssl", "aes256gcm", &ptls_openssl_aes256gcm, &ptls_minicrypto_sha384, 1}, #ifdef PTLS_HAVE_MBEDTLS - {"mbedtls", "aes128gcm",& ptls_mbedtls_aes128gcm,& ptls_mbedtls_sha256, 1}, + {"mbedtls", "aes128gcm", &ptls_mbedtls_aes128gcm, &ptls_mbedtls_sha256, 1}, #if defined(MBEDTLS_SHA384_C) - { "mbedtls", "aes256gcm", &ptls_mbedtls_aes256gcm, &ptls_mbedtls_sha384, 1 }, + {"mbedtls", "aes256gcm", &ptls_mbedtls_aes256gcm, &ptls_mbedtls_sha384, 1}, #endif - { "mbedtls", "chacha20poly1305", &ptls_mbedtls_chacha20poly1305, &ptls_mbedtls_sha256, 1 }, + {"mbedtls", "chacha20poly1305", &ptls_mbedtls_chacha20poly1305, &ptls_mbedtls_sha256, 1}, #endif }; From 08e53195053edaad679cffbf31fd87d60b2c095b Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 3 Nov 2023 18:33:35 +0900 Subject: [PATCH 069/151] rename files following the convention that backends use just the backend name --- include/picotls/{ptls_mbedtls.h => mbedtls.h} | 0 lib/{ptls_mbedtls.c => mbedtls.c} | 0 t/{ptls_mbedtls.c => mbedtls.c} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename include/picotls/{ptls_mbedtls.h => mbedtls.h} (100%) rename lib/{ptls_mbedtls.c => mbedtls.c} (100%) rename t/{ptls_mbedtls.c => mbedtls.c} (100%) diff --git a/include/picotls/ptls_mbedtls.h b/include/picotls/mbedtls.h similarity index 100% rename from include/picotls/ptls_mbedtls.h rename to include/picotls/mbedtls.h diff --git a/lib/ptls_mbedtls.c b/lib/mbedtls.c similarity index 100% rename from lib/ptls_mbedtls.c rename to lib/mbedtls.c diff --git a/t/ptls_mbedtls.c b/t/mbedtls.c similarity index 100% rename from t/ptls_mbedtls.c rename to t/mbedtls.c From 939eb5d7c72695285845e39481c7f50c277a060e Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 3 Nov 2023 18:34:46 +0900 Subject: [PATCH 070/151] `()` in a prototype means any number of args, no zero --- include/picotls/mbedtls.h | 4 ++-- lib/mbedtls.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index ac16ab221..dcc71faef 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -50,8 +50,8 @@ extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; extern ptls_key_exchange_algorithm_t ptls_mbedtls_x25519; -int ptls_mbedtls_init(); -void ptls_mbedtls_free(); +int ptls_mbedtls_init(void); +void ptls_mbedtls_free(void); void ptls_mbedtls_random_bytes(void *buf, size_t len); #ifdef __cplusplus diff --git a/lib/mbedtls.c b/lib/mbedtls.c index ea9ca1b0e..feca0a552 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -42,12 +42,12 @@ * library functions. Free should be used before leaving the program. */ -void ptls_mbedtls_free() +void ptls_mbedtls_free(void) { mbedtls_psa_crypto_free(); } -int ptls_mbedtls_init() +int ptls_mbedtls_init(void) { int ret = 0; psa_status_t status; From c9dcc3e59e28029020d6097434c4aa32b61cd03f Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 3 Nov 2023 18:39:27 +0900 Subject: [PATCH 071/151] ensure that MBEDTLS_SHA384_C is detected regardless of include order --- include/picotls/mbedtls.h | 3 +++ lib/mbedtls.c | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index dcc71faef..5dc8a52d5 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -25,6 +25,9 @@ #ifdef __cplusplus extern "C" { #endif + +#include "mbedtls/mbedtls_config.h" +#include "mbedtls/build_info.h" #include "picotls.h" extern ptls_hash_algorithm_t ptls_mbedtls_sha256; diff --git a/lib/mbedtls.c b/lib/mbedtls.c index feca0a552..11720fd85 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -28,8 +28,6 @@ #include #include #include -#include "mbedtls/mbedtls_config.h" -#include "mbedtls/build_info.h" #include "psa/crypto.h" #include "psa/crypto_struct.h" #include "psa/crypto_values.h" From bcf9f71f2345378c4cd719240cc5d596be4b2dd2 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 3 Nov 2023 18:42:04 +0900 Subject: [PATCH 072/151] API doc goes into .h --- include/picotls/mbedtls.h | 7 +++++++ lib/mbedtls.c | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index 5dc8a52d5..b4435943c 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -28,6 +28,7 @@ extern "C" { #include "mbedtls/mbedtls_config.h" #include "mbedtls/build_info.h" + #include "picotls.h" extern ptls_hash_algorithm_t ptls_mbedtls_sha256; @@ -53,7 +54,13 @@ extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; extern ptls_key_exchange_algorithm_t ptls_mbedtls_x25519; +/** + * Init should be used before starting using library functions. + */ int ptls_mbedtls_init(void); +/** + * Free should be used before leaving the program. + */ void ptls_mbedtls_free(void); void ptls_mbedtls_random_bytes(void *buf, size_t len); diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 11720fd85..dc24922b2 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -36,10 +36,6 @@ #include "mbedtls/ecdh.h" -/* Init and free functions. Init should be used before starting using - * library functions. Free should be used before leaving the program. - */ - void ptls_mbedtls_free(void) { mbedtls_psa_crypto_free(); @@ -56,10 +52,6 @@ int ptls_mbedtls_init(void) return ret; } -/* Random number generator. - * This is a call to the PSA random number generator, which according - * to the documentation meets cryptographic requirements. - */ void ptls_mbedtls_random_bytes(void *buf, size_t len) { psa_generate_random((uint8_t *)buf, len); From cdd6c954ec82db199e5212bf93a59de532f1861e Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Fri, 3 Nov 2023 19:15:56 +0900 Subject: [PATCH 073/151] add capability to define custom clone functions for hash contexts --- include/picotls.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/picotls.h b/include/picotls.h index b701e780b..374543054 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -1763,6 +1763,10 @@ char *ptls_jsonescape(char *buf, const char *s, size_t len); * the default get_time callback */ extern ptls_get_time_t ptls_get_time; +/** + * default hash clone function that calls memcpy + */ +static void ptls_hash_clone_memcpy(void *dst, const void *src, size_t size); #if defined(PICOTLS_USE_DTRACE) && PICOTLS_USE_DTRACE /** * @@ -1919,7 +1923,14 @@ inline size_t ptls_aead_decrypt(ptls_aead_context_t *ctx, void *output, const vo return ctx->do_decrypt(ctx, output, input, inlen, seq, aad, aadlen); } +inline void ptls_hash_clone_memcpy(void *dst, const void *src, size_t size) +{ + memcpy(dst, src, size); +} + #define ptls_define_hash(name, ctx_type, init_func, update_func, final_func) \ + ptls_define_hash6(name, ctx_type, init_func, update_func, final_func, ptls_hash_clone_memcpy) +#define ptls_define_hash6(name, ctx_type, init_func, update_func, final_func, clone_func) \ \ struct name##_context_t { \ ptls_hash_context_t super; \ @@ -1962,7 +1973,8 @@ inline size_t ptls_aead_decrypt(ptls_aead_context_t *ctx, void *output, const vo struct name##_context_t *dst, *src = (struct name##_context_t *)_src; \ if ((dst = malloc(sizeof(*dst))) == NULL) \ return NULL; \ - *dst = *src; \ + dst->super = src->super; \ + clone_func(&dst->ctx, &src->ctx, sizeof(dst->ctx)); \ return &dst->super; \ } \ \ From 86266adce6a4e49453c1dca0d6b8acafd7c16d3e Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 05:38:11 +0100 Subject: [PATCH 074/151] [xcode] add files --- picotls.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj index 6882e1977..67ddebfdd 100644 --- a/picotls.xcodeproj/project.pbxproj +++ b/picotls.xcodeproj/project.pbxproj @@ -205,6 +205,10 @@ 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 = ""; }; + 0883D32A2AF601A700B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = ""; }; + 0883D32B2AF601B900B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = ""; }; + 0883D32C2AF601CB00B711CC /* mbedtls.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mbedtls.h; sourceTree = ""; }; + 0883D32D2AF6020300B711CC /* ptlsbench.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ptlsbench.c; 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; }; @@ -402,7 +406,6 @@ 106530BD1D998624005B2C60 /* lib */, E95EBCC2227E82BA0022C32D /* misc */, E95EBCC0227B71170022C32D /* picotls-probes.d */, - E992F79920E99A080008154D /* src */, 106530C41D9B1A0E005B2C60 /* t */, 106530B31D9985E0005B2C60 /* Products */, E973651D246E37300039AA49 /* Frameworks */, @@ -443,6 +446,7 @@ E97577022212405D00D1EF74 /* ffx.c */, E9B43DBF24619D1700824E51 /* fusion.c */, 08F0FDF52910F67A00EE657D /* hpke.c */, + 0883D32B2AF601B900B711CC /* mbedtls.c */, E949EF272073629300511ECA /* minicrypto-pem.c */, 106530C21D9B004B005B2C60 /* openssl.c */, E99B75DF1F5CDDB500CF503E /* pembase64.c */, @@ -461,9 +465,11 @@ 08B3298229419DFC009D6766 /* ech-live.t */, E9B43DE224619D7E00824E51 /* fusion.c */, 081F00C92918823200534A86 /* hpke.c */, + 0883D32A2AF601A700B711CC /* mbedtls.c */, 1059003D1DC8D4E300FB4085 /* minicrypto.c */, 106530C51D9B1A98005B2C60 /* openssl.c */, 106530E91D9B7C13005B2C60 /* picotls.c */, + 0883D32D2AF6020300B711CC /* ptlsbench.c */, 106530E61D9B7AF6005B2C60 /* test.h */, E9E3849C1F0748DD00D50990 /* util.h */, ); @@ -496,6 +502,7 @@ E9E4B1292180514000514B47 /* certificate_compression.h */, E97577002212405300D1EF74 /* ffx.h */, E9B43DE62461A06800824E51 /* fusion.h */, + 0883D32C2AF601CB00B711CC /* mbedtls.h */, 1059004F1DC8D64E00FB4085 /* minicrypto.h */, 106530ED1D9CEFF7005B2C60 /* openssl.h */, 081F00CD291A358800534A86 /* pembase64.h */, @@ -538,13 +545,6 @@ name = Frameworks; sourceTree = ""; }; - E992F79920E99A080008154D /* src */ = { - isa = PBXGroup; - children = ( - ); - path = src; - sourceTree = ""; - }; E9F20BDF22E34B210018D260 /* cifra */ = { isa = PBXGroup; children = ( From cb3e51c5e88748a44eb094c035530d246f19f3bb Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 05:38:20 +0100 Subject: [PATCH 075/151] rename (amends 08e5319) --- CMakeLists.txt | 4 ++-- t/mbedtls.c | 2 +- t/ptlsbench.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a40ca4ad6..0e816e57f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,11 +208,11 @@ IF (WITH_MBEDTLS) message(STATUS "mbedtls/include: ${MBEDTLS_INCLUDE_DIRS}") message(STATUS "mbedtls libraries: ${MBEDTLS_LIBRARIES}") INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) - ADD_LIBRARY(picotls-mbedtls lib/ptls_mbedtls.c) + ADD_LIBRARY(picotls-mbedtls lib/mbedtls.c) ADD_EXECUTABLE(test-mbedtls.t deps/picotest/picotest.c lib/picotls.c - t/ptls_mbedtls.c) + t/mbedtls.c) TARGET_LINK_LIBRARIES(test-mbedtls.t picotls-minicrypto picotls-mbedtls ${MBEDTLS_LIBRARIES}) diff --git a/t/mbedtls.c b/t/mbedtls.c index 7bd44a23b..faff669e2 100644 --- a/t/mbedtls.c +++ b/t/mbedtls.c @@ -33,7 +33,7 @@ #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "psa/crypto_struct.h" -#include "picotls/ptls_mbedtls.h" +#include "picotls/mbedtls.h" #include "picotls/minicrypto.h" #include "../deps/picotest/picotest.h" diff --git a/t/ptlsbench.c b/t/ptlsbench.c index 9e4bc1efd..9d9b89d8d 100644 --- a/t/ptlsbench.c +++ b/t/ptlsbench.c @@ -62,7 +62,7 @@ #ifdef PTLS_HAVE_MBEDTLS #include "mbedtls/build_info.h" #include "psa/crypto.h" -#include "picotls/ptls_mbedtls.h" +#include "picotls/mbedtls.h" #endif /* Time in microseconds */ From e2a3a82f66126e27f92a7819c34edc0eda55cb06 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 05:39:19 +0100 Subject: [PATCH 076/151] these files are included by `crypto.h` --- lib/mbedtls.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index dc24922b2..046925967 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -29,11 +29,7 @@ #include #include #include "psa/crypto.h" -#include "psa/crypto_struct.h" -#include "psa/crypto_values.h" - #include "mbedtls/chacha20.h" - #include "mbedtls/ecdh.h" void ptls_mbedtls_free(void) From 24bb55602388896dd6d99819d8a6db6d2d85e3d5 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 05:39:43 +0100 Subject: [PATCH 077/151] when building picotls, picotls is not part of the system --- lib/mbedtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 046925967..d18c088f8 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -27,10 +27,10 @@ #include #include #include -#include #include "psa/crypto.h" #include "mbedtls/chacha20.h" #include "mbedtls/ecdh.h" +#include "picotls.h" void ptls_mbedtls_free(void) { From 6d6985aa254a5b37a9081c7e6d96c44703a88d5e Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 05:40:07 +0100 Subject: [PATCH 078/151] when building picotls, picotls is not part of the system, whereas mbedtls is --- lib/mbedtls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index d18c088f8..f7386d397 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -27,9 +27,9 @@ #include #include #include -#include "psa/crypto.h" -#include "mbedtls/chacha20.h" -#include "mbedtls/ecdh.h" +#include +#include +#include #include "picotls.h" void ptls_mbedtls_free(void) From 967e854d32d588d2ab0219aa3900fc15e36b0b44 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 05:57:56 +0100 Subject: [PATCH 079/151] define hash implementations using `ptls_define_hash` --- lib/mbedtls.c | 158 +++++++++++--------------------------------------- 1 file changed, 34 insertions(+), 124 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index f7386d397..8180a8906 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -53,131 +53,41 @@ void ptls_mbedtls_random_bytes(void *buf, size_t len) psa_generate_random((uint8_t *)buf, len); } -/* Definitions for hash algorithms. - * In Picotls, these are described by the stucture - * ptls_hash_algorithm_t, which include the function - * pointer for creation of the hash context. - * - * The structure contains a function pointer to the - * "create" function that creates a hash operation, - * which itself contains three function pointers: - * - * void (*update)(struct st_ptls_hash_context_t *ctx, const void *src, size_t len); - * void (*final)(struct st_ptls_hash_context_t *ctx, void *md, ptls_hash_final_mode_t mode); - * struct st_ptls_hash_context_t *(*clone_)(struct st_ptls_hash_context_t *src); - * - */ - -typedef struct st_ptls_mbedtls_hash_ctx_t { - ptls_hash_context_t super; - psa_algorithm_t alg; - size_t hash_size; - psa_hash_operation_t operation; -} ptls_mbedtls_hash_ctx_t; - -static void ptls_mbedtls_hash_update(struct st_ptls_hash_context_t *_ctx, const void *src, size_t len) -{ - ptls_mbedtls_hash_ctx_t *ctx = (ptls_mbedtls_hash_ctx_t *)_ctx; - - (void)psa_hash_update(&ctx->operation, (const uint8_t *)src, len); -} - -static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t *_ctx, void *md, ptls_hash_final_mode_t mode); - -static struct st_ptls_hash_context_t *ptls_mbedtls_hash_clone(struct st_ptls_hash_context_t *_src) -{ - ptls_mbedtls_hash_ctx_t *ctx = (ptls_mbedtls_hash_ctx_t *)malloc(sizeof(ptls_mbedtls_hash_ctx_t)); - const ptls_mbedtls_hash_ctx_t *src = (const ptls_mbedtls_hash_ctx_t *)_src; - - if (ctx != NULL) { - ptls_mbedtls_hash_ctx_t *src = (ptls_mbedtls_hash_ctx_t *)_src; - memset(&ctx->operation, 0, sizeof(mbedtls_sha256_context)); - ctx->super.clone_ = ptls_mbedtls_hash_clone; - ctx->super.update = ptls_mbedtls_hash_update; - ctx->super.final = ptls_mbedtls_hash_final; - ctx->alg = src->alg; - ctx->hash_size = src->hash_size; - if (psa_hash_clone(&src->operation, &ctx->operation) != 0) { - free(ctx); - ctx = NULL; - } - } - return (ptls_hash_context_t *)ctx; -} - -static void ptls_mbedtls_hash_final(struct st_ptls_hash_context_t *_ctx, void *md, ptls_hash_final_mode_t mode) -{ - ptls_mbedtls_hash_ctx_t *ctx = (ptls_mbedtls_hash_ctx_t *)_ctx; - - if (mode == PTLS_HASH_FINAL_MODE_SNAPSHOT) { - struct st_ptls_hash_context_t *cloned = ptls_mbedtls_hash_clone(_ctx); - - if (cloned != NULL) { - ptls_mbedtls_hash_final(cloned, md, PTLS_HASH_FINAL_MODE_FREE); - } - } else { - if (md != NULL) { - size_t hash_length = 0; - if (psa_hash_finish(&ctx->operation, md, ctx->hash_size, &hash_length) != 0) { - memset(md, 0, ctx->hash_size); - } - } - - if (mode == PTLS_HASH_FINAL_MODE_FREE) { - (void)psa_hash_abort(&ctx->operation); - free(ctx); - } else { - /* if mode = reset, reset the context */ - memset(&ctx->operation, 0, sizeof(ctx->operation)); - (void)psa_hash_setup(&ctx->operation, ctx->alg); - } - } -} - -ptls_hash_context_t *ptls_mbedtls_hash_create(psa_algorithm_t alg, size_t hash_size) -{ - ptls_mbedtls_hash_ctx_t *ctx = (ptls_mbedtls_hash_ctx_t *)malloc(sizeof(ptls_mbedtls_hash_ctx_t)); - - if (ctx != NULL) { - memset(&ctx->operation, 0, sizeof(ctx->operation)); - ctx->alg = alg; - ctx->hash_size = hash_size; - ctx->super.clone_ = ptls_mbedtls_hash_clone; - ctx->super.update = ptls_mbedtls_hash_update; - ctx->super.final = ptls_mbedtls_hash_final; - if (psa_hash_setup(&ctx->operation, alg) != 0) { - free(ctx); - ctx = NULL; - } - } - return (ptls_hash_context_t *)ctx; -} - -ptls_hash_context_t *ptls_mbedtls_sha256_create(void) -{ - return ptls_mbedtls_hash_create(PSA_ALG_SHA_256, PTLS_SHA256_DIGEST_SIZE); -} - -ptls_hash_context_t *ptls_mbedtls_sha512_create(void) -{ - return ptls_mbedtls_hash_create(PSA_ALG_SHA_512, PTLS_SHA512_DIGEST_SIZE); -} - -ptls_hash_algorithm_t ptls_mbedtls_sha256 = {"sha256", PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, ptls_mbedtls_sha256_create, - PTLS_ZERO_DIGEST_SHA256}; - -ptls_hash_algorithm_t ptls_mbedtls_sha512 = {"SHA512", PTLS_SHA512_BLOCK_SIZE, PTLS_SHA512_DIGEST_SIZE, ptls_mbedtls_sha512_create, - PTLS_ZERO_DIGEST_SHA512}; - +#define CALL_WITH_CHECK(fn, ...) \ + do { \ + if (fn(__VA_ARGS__) != PSA_SUCCESS) { \ + fprintf(stderr, PTLS_TO_STR(fn) " failed\n"); \ + abort(); \ + } \ + } while (0) + +#define DEFINE_HASH(name, name_upcase, psa_alg) \ + static void name##_do_init(psa_hash_operation_t *op) \ + { \ + *op = psa_hash_operation_init(); \ + CALL_WITH_CHECK(psa_hash_setup, op, psa_alg); \ + } \ + static void name##_do_update(psa_hash_operation_t *op, const void *src, size_t len) \ + { \ + CALL_WITH_CHECK(psa_hash_update, op, src, len); \ + } \ + static void name##_do_final(psa_hash_operation_t *op, void *md) \ + { \ + size_t unused; \ + CALL_WITH_CHECK(psa_hash_finish, op, md, PTLS_##name_upcase##_DIGEST_SIZE, &unused); \ + } \ + static void name##_do_clone(psa_hash_operation_t *dst, psa_hash_operation_t *src, size_t unused) \ + { \ + CALL_WITH_CHECK(psa_hash_clone, src, dst); \ + } \ + ptls_define_hash6(name, psa_hash_operation_t, name##_do_init, name##_do_update, name##_do_final, name##_do_clone); \ + ptls_hash_algorithm_t ptls_mbedtls_##name = {PTLS_TO_STR(name), PTLS_##name_upcase##_BLOCK_SIZE, \ + PTLS_##name_upcase##_DIGEST_SIZE, name##_create, PTLS_ZERO_DIGEST_##name_upcase}; +DEFINE_HASH(sha256, SHA256, PSA_ALG_SHA_256); +DEFINE_HASH(sha512, SHA512, PSA_ALG_SHA_512); #if defined(MBEDTLS_SHA384_C) -ptls_hash_context_t *ptls_mbedtls_sha384_create(void) -{ - return ptls_mbedtls_hash_create(PSA_ALG_SHA_384, PTLS_SHA384_DIGEST_SIZE); -} - -ptls_hash_algorithm_t ptls_mbedtls_sha384 = {"SHA384", PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, ptls_mbedtls_sha384_create, - PTLS_ZERO_DIGEST_SHA384}; -#endif /* MBEDTLS_SHA384_C */ +DEFINE_HASH(sha384, SHA384, PSA_ALG_SHA_384); +#endif /* * Generic implementation of a cipher using the PSA API From 3e99858601fcd7a8bb5027c88dacbf6d788c17bc Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 05:59:41 +0100 Subject: [PATCH 080/151] mbedtls is dependency --- include/picotls/mbedtls.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index b4435943c..e7fc7a398 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -26,9 +26,8 @@ extern "C" { #endif -#include "mbedtls/mbedtls_config.h" -#include "mbedtls/build_info.h" - +#include +#include #include "picotls.h" extern ptls_hash_algorithm_t ptls_mbedtls_sha256; @@ -67,4 +66,4 @@ void ptls_mbedtls_random_bytes(void *buf, size_t len); #ifdef __cplusplus } #endif -#endif /* picotls_mbedtls_h */ \ No newline at end of file +#endif /* picotls_mbedtls_h */ From 68662dc703b6dd705fa1ad820264e35c41b037ae Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 06:00:42 +0100 Subject: [PATCH 081/151] it is our convention to let the user initialize the crypto backends (see openssl) --- include/picotls/mbedtls.h | 10 ++-------- lib/mbedtls.c | 16 ---------------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index e7fc7a398..3e8904c7d 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -30,6 +30,8 @@ extern "C" { #include #include "picotls.h" +/* before using any of these objects, psa_crypto_init() must be called */ + extern ptls_hash_algorithm_t ptls_mbedtls_sha256; extern ptls_hash_algorithm_t ptls_mbedtls_sha512; #if defined(MBEDTLS_SHA384_C) @@ -53,14 +55,6 @@ extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; extern ptls_key_exchange_algorithm_t ptls_mbedtls_x25519; -/** - * Init should be used before starting using library functions. - */ -int ptls_mbedtls_init(void); -/** - * Free should be used before leaving the program. - */ -void ptls_mbedtls_free(void); void ptls_mbedtls_random_bytes(void *buf, size_t len); #ifdef __cplusplus diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 8180a8906..aa5a31db5 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -32,22 +32,6 @@ #include #include "picotls.h" -void ptls_mbedtls_free(void) -{ - mbedtls_psa_crypto_free(); -} - -int ptls_mbedtls_init(void) -{ - int ret = 0; - psa_status_t status; - if ((status = psa_crypto_init()) != PSA_SUCCESS) { - ret = -1; - } - - return ret; -} - void ptls_mbedtls_random_bytes(void *buf, size_t len) { psa_generate_random((uint8_t *)buf, len); From e2f03c95998e7d6c328b5dd5407a6a864153a131 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 06:01:14 +0100 Subject: [PATCH 082/151] PRNG might fail too --- lib/mbedtls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index aa5a31db5..8dff7012b 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -32,11 +32,6 @@ #include #include "picotls.h" -void ptls_mbedtls_random_bytes(void *buf, size_t len) -{ - psa_generate_random((uint8_t *)buf, len); -} - #define CALL_WITH_CHECK(fn, ...) \ do { \ if (fn(__VA_ARGS__) != PSA_SUCCESS) { \ @@ -45,6 +40,11 @@ void ptls_mbedtls_random_bytes(void *buf, size_t len) } \ } while (0) +void ptls_mbedtls_random_bytes(void *buf, size_t len) +{ + CALL_WITH_CHECK(psa_generate_random, buf, len); +} + #define DEFINE_HASH(name, name_upcase, psa_alg) \ static void name##_do_init(psa_hash_operation_t *op) \ { \ From 21062990588be43d76ca7c5997d8608e9f4dc641 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 07:53:39 +0100 Subject: [PATCH 083/151] reduce state of symmentric ciphers; no need to set key for every IV --- lib/mbedtls.c | 178 ++++++++++++++++++-------------------------------- 1 file changed, 64 insertions(+), 114 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 8dff7012b..629b6c013 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -78,156 +78,109 @@ DEFINE_HASH(sha384, SHA384, PSA_ALG_SHA_384); */ struct st_ptls_mbedtls_cipher_context_t { ptls_cipher_context_t super; - psa_algorithm_t alg; size_t iv_length; - int is_enc; - int is_op_in_progress; - mbedtls_svc_key_id_t key; - psa_cipher_operation_t operation; + psa_cipher_operation_t op; }; -static void ptls_mbedtls_cipher_init(ptls_cipher_context_t *_ctx, const void *iv) +static void cipher_init(ptls_cipher_context_t *_ctx, const void *iv) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; - if (ctx->is_op_in_progress) { - psa_cipher_abort(&ctx->operation); - ctx->is_op_in_progress = 0; - } - - memset(&ctx->operation, 0, sizeof(ctx->operation)); - if (ctx->is_enc) { - (void)psa_cipher_encrypt_setup(&ctx->operation, ctx->key, ctx->alg); - } else { - (void)psa_cipher_decrypt_setup(&ctx->operation, ctx->key, ctx->alg); - } - if (ctx->iv_length > 0) { - (void)psa_cipher_set_iv(&ctx->operation, (const uint8_t *)iv, ctx->iv_length); - } - ctx->is_op_in_progress = 1; + if (ctx->iv_length > 0) + CALL_WITH_CHECK(psa_cipher_set_iv, &ctx->op, iv, ctx->iv_length); } -static void ptls_mbedtls_cipher_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) +static void cipher_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; - size_t outlen = 0; + size_t unused = 0; - (void)psa_cipher_update(&ctx->operation, (const uint8_t *)input, len, (uint8_t *)output, len, &outlen); + CALL_WITH_CHECK(psa_cipher_update, &ctx->op, input, len, output, len, &unused); } -static void ptls_mbedtls_cipher_dispose(ptls_cipher_context_t *_ctx) +static void cipher_dispose(ptls_cipher_context_t *_ctx) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; - if (ctx->is_op_in_progress) { - psa_cipher_abort(&ctx->operation); - ctx->is_op_in_progress = 0; - } - psa_destroy_key(ctx->key); + + psa_cipher_abort(&ctx->op); } -static int ptls_mbedtls_cipher_setup_key(mbedtls_svc_key_id_t *key_id, int is_enc, psa_algorithm_t alg, psa_key_type_t key_type, - size_t key_bits, const uint8_t *key_bytes) +static int setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, size_t iv_length, + psa_key_type_t key_type, size_t key_bits) { + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + mbedtls_svc_key_id_t key; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - int ret = 0; + /* import key or fail immediately */ psa_set_key_usage_flags(&attributes, (is_enc) ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, key_type); psa_set_key_bits(&attributes, key_bits); - /* Import key */ - if (psa_import_key(&attributes, key_bytes, key_bits / 8, key_id) != PSA_SUCCESS) { - ret = PTLS_ERROR_LIBRARY; - } - - return ret; -} - -static int ptls_mbedtls_cipher_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, - size_t iv_length, psa_key_type_t key_type, size_t key_bits) -{ - struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; - int ret = 0; + if (psa_import_key(&attributes, key_bytes, key_bits / 8, &key) != PSA_SUCCESS) + return PTLS_ERROR_LIBRARY; - ctx->alg = alg; - ctx->is_enc = is_enc; + /* init context */ + ctx->super.do_dispose = cipher_dispose; + ctx->super.do_init = cipher_init; + ctx->super.do_transform = cipher_transform; ctx->iv_length = iv_length; - - /* Initialize the key attributes */ - ret = ptls_mbedtls_cipher_setup_key(&ctx->key, is_enc, alg, key_type, key_bits, (const uint8_t *)key_bytes); - /* Finish initializing the context */ - ctx->super.do_dispose = ptls_mbedtls_cipher_dispose; - ctx->super.do_init = ptls_mbedtls_cipher_init; - ctx->super.do_transform = NULL; - - if (ret == 0) { - ctx->super.do_transform = ptls_mbedtls_cipher_transform; + ctx->op = psa_cipher_operation_init(); + if (is_enc) { + CALL_WITH_CHECK(psa_cipher_encrypt_setup, &ctx->op, key, alg); + } else { + CALL_WITH_CHECK(psa_cipher_decrypt_setup, &ctx->op, key, alg); } - return ret; + return 0; } -/* - * Implementation of AES128_ECB using the PSA API: - */ -static int ptls_mbedtls_cipher_setup_aes128_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +static int setup_aes128ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 128); + return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 128); } -ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = {"AES128-ECB", - PTLS_AES128_KEY_SIZE, - PTLS_AES_BLOCK_SIZE, - 0 /* iv size */, - sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_aes128_ecb}; +ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { + "AES128-ECB", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_aes128ecb}; /* * Implementation of AES256_ECB using the PSA API: */ -static int ptls_mbedtls_cipher_setup_aes256_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +static int setup_aes256ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 256); + return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 256); } -ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = {"AES256-ECB", - PTLS_AES128_KEY_SIZE, - PTLS_AES_BLOCK_SIZE, - 0 /* iv size */, - sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_aes256_ecb}; +ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { + "AES256-ECB", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_aes256ecb}; /* * Implementation of AES128_CTR using the PSA API: */ -static int ptls_mbedtls_cipher_setup_aes128_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +static int setup_aes128ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 128); + return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 128); } -ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = {"AES128-CTR", - PTLS_AES128_KEY_SIZE, - PTLS_AES_BLOCK_SIZE, - 16 /* iv size */, - sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_aes128_ctr}; +ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { + "AES128-CTR", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 16 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_aes128ctr}; /* * Implementation of AES128_CTR using the PSA API: */ -static int ptls_mbedtls_cipher_setup_aes256_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +static int setup_aes256ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 256); + return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 256); } -ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = {"AES128-CTR", - PTLS_AES256_KEY_SIZE, - PTLS_AES_BLOCK_SIZE, - 16 /* iv size */, - sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_aes256_ctr}; +ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { + "AES128-CTR", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 16 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_aes256ctr}; #if 0 /* @@ -235,15 +188,14 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = {"AES128-CTR", * This is disabled for now, as there seems to be an issue when * setting the 16 bytes long IV that we need. */ -static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes) +static int setup_crypto_chacha20(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ptls_mbedtls_cipher_setup_crypto(_ctx, is_enc, key_bytes, - PSA_ALG_STREAM_CIPHER, 16, PSA_KEY_TYPE_CHACHA20, 256); + return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_STREAM_CIPHER, 16, PSA_KEY_TYPE_CHACHA20, 256); } ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { "CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_cipher_context_t), - ptls_mbedtls_cipher_setup_crypto_chacha20}; + setup_chacha20}; #else /* Implementation of ChaCha20 using the low level ChaCha20 API. * TODO: remove this and the reference to chacha20.h as soon as @@ -254,7 +206,7 @@ struct st_ptls_mbedtls_chacha20_context_t { mbedtls_chacha20_context mctx; }; -static void ptls_mbedtls_chacha20_init(ptls_cipher_context_t *_ctx, const void *v_iv) +static void chacha20_init(ptls_cipher_context_t *_ctx, const void *v_iv) { struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; const uint8_t *iv = (const uint8_t *)v_iv; @@ -263,38 +215,36 @@ static void ptls_mbedtls_chacha20_init(ptls_cipher_context_t *_ctx, const void * (void)mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t *)(iv + 4), ctr); } -static void ptls_mbedtls_chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) +static void chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) { struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; if (mbedtls_chacha20_update(&ctx->mctx, len, (const uint8_t *)input, (uint8_t *)output) != 0) { - memset(output, 0, len); + fprintf(stderr, "mbedtls_chacha20_update failed\n"); + abort(); } } -static void ptls_mbedtls_chacha20_dispose(ptls_cipher_context_t *_ctx) +static void chacha20_dispose(ptls_cipher_context_t *_ctx) { struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; + mbedtls_chacha20_free(&ctx->mctx); } -static int ptls_mbedtls_cipher_setup_crypto_chacha20(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +static int setup_chacha20(ptls_cipher_context_t *_ctx, int is_enc, const void *key) { struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; - int ret = 0; mbedtls_chacha20_init(&ctx->mctx); - ret = mbedtls_chacha20_setkey(&ctx->mctx, (const uint8_t *)key); + if (mbedtls_chacha20_setkey(&ctx->mctx, key) != 0) + return PTLS_ERROR_LIBRARY; - ctx->super.do_dispose = ptls_mbedtls_chacha20_dispose; - ctx->super.do_init = ptls_mbedtls_chacha20_init; - ctx->super.do_transform = NULL; + ctx->super.do_dispose = chacha20_dispose; + ctx->super.do_init = chacha20_init; + ctx->super.do_transform = chacha20_transform; - if (ret == 0) { - ctx->super.do_transform = ptls_mbedtls_chacha20_transform; - } - - return ret; + return 0; } ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = {"CHACHA20", @@ -302,7 +252,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = {"CHACHA20", 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_chacha20_context_t), - ptls_mbedtls_cipher_setup_crypto_chacha20}; + setup_chacha20}; #endif /* Definitions of AEAD algorithms. From 89c9fa1bcfdea67b580f11dfa9930c7f6547acf7 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 07:56:36 +0100 Subject: [PATCH 084/151] engines can be tested using `test_picotls` --- CMakeLists.txt | 2 +- include/picotls/mbedtls.h | 2 + lib/mbedtls.c | 5 + t/mbedtls.c | 425 +++++--------------------------------- 4 files changed, 56 insertions(+), 378 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e816e57f..f1f2f736f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,7 +211,7 @@ IF (WITH_MBEDTLS) ADD_LIBRARY(picotls-mbedtls lib/mbedtls.c) ADD_EXECUTABLE(test-mbedtls.t deps/picotest/picotest.c - lib/picotls.c + ${CORE_TEST_FILES} t/mbedtls.c) TARGET_LINK_LIBRARIES(test-mbedtls.t picotls-minicrypto picotls-mbedtls diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index 3e8904c7d..538a2508f 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -51,9 +51,11 @@ extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; extern ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256; extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; +extern ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[]; extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; extern ptls_key_exchange_algorithm_t ptls_mbedtls_x25519; +extern ptls_key_exchange_algorithm_t *ptls_mbedtls_key_exchanges[]; void ptls_mbedtls_random_bytes(void *buf, size_t len); diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 629b6c013..f15467931 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -576,6 +576,9 @@ ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUI .aead = &ptls_mbedtls_chacha20poly1305, .hash = &ptls_mbedtls_sha256}; +ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[] = {&ptls_mbedtls_aes256gcmsha384, &ptls_mbedtls_aes128gcmsha256, + &ptls_mbedtls_chacha20poly1305sha256, NULL}; + /* Key exchange algorithms. * The Picotls framework defines these algorithms as ptls_key_exchange_algorithm_t, * a structure containing two function pointers: @@ -786,3 +789,5 @@ ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = {.id = PTLS_GROUP_X25519, .name = PTLS_GROUP_NAME_X25519, .create = ptls_mbedtls_x25519_create, .exchange = ptls_mbedtls_x25519_exchange}; + +ptls_key_exchange_algorithm_t *ptls_mbedtls_key_exchanges[] = {&ptls_mbedtls_secp256r1, NULL}; diff --git a/t/mbedtls.c b/t/mbedtls.c index faff669e2..1a86d9f48 100644 --- a/t/mbedtls.c +++ b/t/mbedtls.c @@ -36,6 +36,7 @@ #include "picotls/mbedtls.h" #include "picotls/minicrypto.h" #include "../deps/picotest/picotest.h" +#include "test.h" static int random_trial() { @@ -74,367 +75,6 @@ static void test_random(void) ok(!!"success"); } -static int hash_trial(ptls_hash_algorithm_t *algo, const uint8_t *input, size_t len1, size_t len2, uint8_t *final_hash) -{ - int ret = 0; - ptls_hash_context_t *hash_ctx = algo->create(); - - hash_ctx->update(hash_ctx, input, len1); - if (len2 > 0) { - hash_ctx->update(hash_ctx, input + len1, len2); - } - hash_ctx->final(hash_ctx, final_hash, PTLS_HASH_FINAL_MODE_FREE); - - return ret; -} - -static int hash_reset_trial(ptls_hash_algorithm_t *algo, const uint8_t *input, size_t len1, size_t len2, uint8_t *hash1, - uint8_t *hash2) -{ - int ret = 0; - ptls_hash_context_t *hash_ctx = algo->create(); - - hash_ctx->update(hash_ctx, input, len1); - hash_ctx->final(hash_ctx, hash1, PTLS_HASH_FINAL_MODE_RESET); - hash_ctx->update(hash_ctx, input + len1, len2); - hash_ctx->final(hash_ctx, hash2, PTLS_HASH_FINAL_MODE_FREE); - - return ret; -} - -static int test_hash(ptls_hash_algorithm_t *algo, ptls_hash_algorithm_t *ref) -{ - int ret = 0; - uint8_t input[1234]; - uint8_t final_hash[64]; - uint8_t final_ref[64]; - uint8_t hash1[64], hash2[64], href1[64], href2[64]; - - memset(input, 0xba, sizeof(input)); - - ret = hash_trial(algo, input, sizeof(input), 0, final_hash); - if (ret == 0) { - ret = hash_trial(ref, input, sizeof(input), 0, final_ref); - } - if (ret == 0) { - if (memcmp(final_hash, final_ref, ref->digest_size) != 0) { - ret = -1; - } - } - if (ret == 0) { - ret = hash_trial(algo, input, sizeof(input) - 17, 17, final_hash); - } - if (ret == 0) { - if (memcmp(final_hash, final_ref, ref->digest_size) != 0) { - ret = -1; - } - } - - if (ret == 0) { - ret = hash_reset_trial(algo, input, sizeof(input) - 126, 126, hash1, hash2); - } - if (ret == 0) { - ret = hash_reset_trial(ref, input, sizeof(input) - 126, 126, href1, href2); - } - if (ret == 0) { - if (memcmp(hash1, href1, ref->digest_size) != 0) { - ret = -1; - } else if (memcmp(hash2, href2, ref->digest_size) != 0) { - ret = -1; - } - } - - return ret; -} - -static int cipher_trial(ptls_cipher_algorithm_t *cipher, const uint8_t *key, const uint8_t *iv, int is_enc, const uint8_t *v_in, - uint8_t *v_out1, uint8_t *v_out2, size_t len) -{ - int ret = 0; - ptls_cipher_context_t *test_cipher = ptls_cipher_new(cipher, is_enc, key); - if (test_cipher == NULL) { - ret = -1; - } else { - if (test_cipher->do_init != NULL) { - ptls_cipher_init(test_cipher, iv); - } - ptls_cipher_encrypt(test_cipher, v_out1, v_in, len); - if (test_cipher->do_init != NULL) { - ptls_cipher_init(test_cipher, iv); - } - ptls_cipher_encrypt(test_cipher, v_out2, v_out1, len); - ptls_cipher_free(test_cipher); - } - - return ret; -} - -static int test_cipher(ptls_cipher_algorithm_t *cipher, ptls_cipher_algorithm_t *cipher_ref) -{ - uint8_t key[32]; - uint8_t iv[16]; - uint8_t v_in[16]; - uint8_t v_out_1a[16], v_out_2a[16], v_out_1b[16], v_out_2b[16], v_out_1d[16], v_out_2d[16]; - int ret = 0; - - /* Set initial values */ - memset(key, 0x55, sizeof(key)); - memset(iv, 0x33, sizeof(iv)); - memset(v_in, 0xaa, sizeof(v_in)); - - /* Encryption test */ - ret = cipher_trial(cipher, key, iv, 1, v_in, v_out_1a, v_out_2a, 16); - if (ret == 0) { - ret = cipher_trial(cipher_ref, key, iv, 1, v_in, v_out_1b, v_out_2b, 16); - } - if (ret == 0) { - if (memcmp(v_out_1a, v_out_1b, 16) != 0) { - ret = -1; - } else if (memcmp(v_out_2a, v_out_2b, 16) != 0) { - ret = -1; - } - } - /* decryption test */ - if (ret == 0) { - ret = cipher_trial(cipher, key, iv, 0, v_out_2a, v_out_1d, v_out_2d, 16); - } - if (ret == 0) { - if (memcmp(v_out_1a, v_out_1d, 16) != 0) { - ret = -1; - } else if (memcmp(v_out_2d, v_in, 16) != 0) { - ret = -1; - } - } - - return ret; -} - -static int label_test(ptls_hash_algorithm_t *hash, uint8_t *v_out, size_t o_len, const uint8_t *secret, char const *label, - char const *label_prefix) -{ - uint8_t h_val_v[32]; - ptls_iovec_t h_val = {0}; - ptls_iovec_t s_vec = {0}; - s_vec.base = (uint8_t *)secret; - s_vec.len = 32; - h_val.base = h_val_v; - h_val.len = 32; - memset(h_val_v, 0, sizeof(h_val_v)); - - ptls_hkdf_expand_label(hash, v_out, o_len, s_vec, label, h_val, label_prefix); - return 0; -} - -static int test_label(ptls_hash_algorithm_t *hash, ptls_hash_algorithm_t *ref) -{ - int ret = 0; - uint8_t v_out[16], v_ref[16]; - uint8_t secret[32]; - char const *label = "label"; - char const *label_prefix = "label_prefix"; - memset(secret, 0x5e, sizeof(secret)); - - ret = label_test(hash, v_out, 16, secret, label, label_prefix); - - if (ret == 0) { - ret = label_test(ref, v_ref, 16, secret, label, label_prefix); - } - - if (ret == 0 && memcmp(v_out, v_ref, 16) != 0) { - ret = -1; - } - - return ret; -} - -static int aead_trial(ptls_aead_algorithm_t *algo, ptls_hash_algorithm_t *hash, const uint8_t *secret, int is_enc, - const uint8_t *v_in, size_t len, uint8_t *aad, size_t aad_len, uint64_t seq, uint8_t *v_out, size_t *o_len) -{ - int ret = 0; - ptls_aead_context_t *aead = ptls_aead_new(algo, hash, is_enc, secret, "test_aead"); - - if (aead == NULL) { - ret = -1; - } else { - if (is_enc) { - *o_len = ptls_aead_encrypt(aead, v_out, v_in, len, seq, aad, aad_len); - if (*o_len != len + algo->tag_size) { - ret = -1; - } - } else { - *o_len = ptls_aead_decrypt(aead, v_out, v_in, len, seq, aad, aad_len); - if (*o_len != len - algo->tag_size) { - ret = -1; - } - } - ptls_aead_free(aead); - } - return ret; -} - -static int test_aead(ptls_aead_algorithm_t *algo, ptls_hash_algorithm_t *hash, ptls_aead_algorithm_t *ref, - ptls_hash_algorithm_t *hash_ref) -{ - uint8_t secret[64]; - uint8_t v_in[1234]; - uint8_t aad[17]; - uint8_t v_out_a[1250], v_out_b[1250], v_out_r[1250]; - size_t olen_a, olen_b, olen_r; - uint64_t seq = 12345; - int ret = 0; - - memset(secret, 0x58, sizeof(secret)); - memset(v_in, 0x12, sizeof(v_in)); - memset(aad, 0xaa, sizeof(aad)); - - ret = aead_trial(algo, hash, secret, 1, v_in, sizeof(v_in), aad, sizeof(aad), seq, v_out_a, &olen_a); - if (ret == 0) { - ret = aead_trial(ref, hash_ref, secret, 1, v_in, sizeof(v_in), aad, sizeof(aad), seq, v_out_b, &olen_b); - } - if (ret == 0 && (olen_a != olen_b || memcmp(v_out_a, v_out_b, olen_a) != 0)) { - ret = -1; - } - if (ret == 0) { - ret = aead_trial(ref, hash_ref, secret, 0, v_out_a, olen_a, aad, sizeof(aad), seq, v_out_r, &olen_r); - } - if (ret == 0 && (olen_r != sizeof(v_in) || memcmp(v_in, v_out_r, sizeof(v_in)) != 0)) { - ret = -1; - } - return ret; -} - -static void test_sha256(void) -{ - if (test_hash(&ptls_mbedtls_sha256, &ptls_minicrypto_sha256) != 0) { - ok(!"fail"); - return; - } - ok(!!"success"); -} - -#if defined(MBEDTLS_SHA384_C) -static void test_sha384(void) -{ - if (test_hash(&ptls_mbedtls_sha384, &ptls_minicrypto_sha384) != 0) { - ok(!"fail"); - return; - } - ok(!!"success"); -} -#endif - -static void test_label_sha256(void) -{ - if (test_label(&ptls_mbedtls_sha256, &ptls_minicrypto_sha256) != 0) { - ok(!"fail"); - return; - } - ok(!!"success"); -} - -static void test_aes128ecb(void) -{ - if (test_cipher(&ptls_mbedtls_aes128ecb, &ptls_minicrypto_aes128ecb) != 0) { - ok(!"fail"); - } - ok(!!"success"); -} - -static void test_aes128ctr(void) -{ - if (test_cipher(&ptls_mbedtls_aes128ctr, &ptls_minicrypto_aes128ctr) != 0) { - ok(!"fail"); - } - ok(!!"success"); -} - -static void test_aes256ecb(void) -{ - if (test_cipher(&ptls_mbedtls_aes256ecb, &ptls_minicrypto_aes256ecb) != 0) { - ok(!"fail"); - } - ok(!!"success"); -} - -static void test_aes256ctr(void) -{ - if (test_cipher(&ptls_mbedtls_aes256ctr, &ptls_minicrypto_aes256ctr) != 0) { - ok(!"fail"); - } - ok(!!"success"); -} - -static void test_chacha20(void) -{ - if (test_cipher(&ptls_mbedtls_chacha20, &ptls_minicrypto_chacha20) != 0) { - ok(!"fail"); - } - ok(!!"success"); -} - -static void test_aes128gcm_sha256(void) -{ - if (test_aead(&ptls_mbedtls_aes128gcm, &ptls_mbedtls_sha256, &ptls_minicrypto_aes128gcm, &ptls_minicrypto_sha256) != 0) { - ok(!"fail"); - } - ok(!!"success"); -} - -#if defined(MBEDTLS_SHA384_C) -static void test_aes256gcm_sha384(void) -{ - if (test_aead(&ptls_mbedtls_aes256gcm, &ptls_mbedtls_sha384, &ptls_minicrypto_aes256gcm, &ptls_minicrypto_sha384) != 0) { - ok(!"fail"); - } - ok(!!"success"); -} -#endif - -static void test_chacha20poly1305_sha256(void) -{ - if (test_aead(&ptls_mbedtls_chacha20poly1305, &ptls_mbedtls_sha256, &ptls_minicrypto_chacha20poly1305, - &ptls_minicrypto_sha256) != 0) { - ok(!"fail"); - } - ok(!!"success"); -} - -/* Test key exchange. This is a cut and paste of the "test_key_exchange" - * defined in test.h and openssl.c, because referring to that common code - * causes a link error. - */ -static void test_key_exchange(ptls_key_exchange_algorithm_t *client, ptls_key_exchange_algorithm_t *server) -{ - ptls_key_exchange_context_t *ctx; - ptls_iovec_t client_secret, server_pubkey, server_secret; - int ret; - - /* fail */ - ret = server->exchange(server, &server_pubkey, &server_secret, (ptls_iovec_t){NULL}); - ok(ret != 0); - - /* perform ecdh */ - ret = client->create(client, &ctx); - ok(ret == 0); - ret = server->exchange(server, &server_pubkey, &server_secret, ctx->pubkey); - ok(ret == 0); - ret = ctx->on_exchange(&ctx, 1, &client_secret, server_pubkey); - ok(ret == 0); - ok(client_secret.len == server_secret.len); - ok(memcmp(client_secret.base, server_secret.base, client_secret.len) == 0); - - free(client_secret.base); - free(server_pubkey.base); - free(server_secret.base); - - /* client abort */ - ret = client->create(client, &ctx); - ok(ret == 0); - ret = ctx->on_exchange(&ctx, 1, NULL, ptls_iovec_init(NULL, 0)); - ok(ret == 0); - ok(ctx == NULL); -} - static void test_secp256r1(void) { test_key_exchange(&ptls_mbedtls_secp256r1, &ptls_minicrypto_secp256r1); @@ -453,6 +93,9 @@ static void test_key_exchanges(void) subtest("x25519", test_x25519); } +DEFINE_FFX_AES128_ALGORITHMS(mbedtls); +DEFINE_FFX_CHACHA20_ALGORITHMS(mbedtls); + int main(int argc, char **argv) { /* Initialize the PSA crypto library. */ @@ -460,25 +103,53 @@ int main(int argc, char **argv) note("psa_crypto_init fails."); return done_testing(); } + /* Test of the port of the mbedtls random generator */ subtest("random", test_random); - /* Series of test to check consistency between wrapped mbedtls and minicrypto */ - subtest("sha256", test_sha256); -#if defined(MBEDTLS_SHA384_C) - subtest("sha384", test_sha384); -#endif - subtest("label_sha256", test_label_sha256); - subtest("aes128ecb", test_aes128ecb); - subtest("aes128ctr", test_aes128ctr); - subtest("aes256ecb", test_aes256ecb); - subtest("aes256ctr", test_aes256ctr); - subtest("chacha20", test_chacha20); - subtest("aes128gcm_sha256", test_aes128gcm_sha256); -#if defined(MBEDTLS_SHA384_C) - subtest("aes256gcm_sha384", test_aes256gcm_sha384); -#endif - subtest("chacha20poly1305_sha256", test_chacha20poly1305_sha256); subtest("key_exchanges", test_key_exchanges); + + ADD_FFX_AES128_ALGORITHMS(mbedtls); + ADD_FFX_CHACHA20_ALGORITHMS(mbedtls); + + /* minicrypto contexts used as peer for valiation */ + ptls_iovec_t secp256r1_certificate = ptls_iovec_init(SECP256R1_CERTIFICATE, sizeof(SECP256R1_CERTIFICATE) - 1); + ptls_minicrypto_secp256r1sha256_sign_certificate_t minicrypto_sign_certificate; + ptls_minicrypto_init_secp256r1sha256_sign_certificate( + &minicrypto_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1)); + ptls_context_t minicrypto_ctx = {ptls_minicrypto_random_bytes, + &ptls_get_time, + ptls_minicrypto_key_exchanges, + ptls_minicrypto_cipher_suites, + {&secp256r1_certificate, 1}, + {{NULL}}, + NULL, + NULL, + &minicrypto_sign_certificate.super}; + + /* context using mbedtls as backend; minicrypto is used for signing certificate as the mbedtls backend does not (yet) have the + * capability */ + ptls_context_t mbedtls_ctx = {ptls_mbedtls_random_bytes, + &ptls_get_time, + ptls_mbedtls_key_exchanges, + ptls_mbedtls_cipher_suites, + {&minicrypto_certificate, 1}, + {{NULL}}, + NULL, + NULL, + &minicrypto_sign_certificate.super}; + + ctx = &mbedtls_ctx; + ctx_peer = &mbedtls_ctx; + subtest("selt-test", test_picotls); + + ctx = &mbedtls_ctx; + ctx_peer = &minicrypto_ctx; + subtest("vs. minicrypto", test_picotls); + + ctx = &minicrypto_ctx; + ctx_peer = &mbedtls_ctx; + subtest("minicrypto vs.", test_picotls); + /* Deinitialize the PSA crypto library. */ mbedtls_psa_crypto_free(); From bdec08f79bf56a144fd9bb54eef6722411c7d527 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 10:28:39 +0100 Subject: [PATCH 085/151] report error in detail --- lib/mbedtls.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index f15467931..64b50c22d 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -34,8 +34,9 @@ #define CALL_WITH_CHECK(fn, ...) \ do { \ - if (fn(__VA_ARGS__) != PSA_SUCCESS) { \ - fprintf(stderr, PTLS_TO_STR(fn) " failed\n"); \ + psa_status_t ret; \ + if ((ret = fn(__VA_ARGS__)) != PSA_SUCCESS) { \ + fprintf(stderr, "in %s at line %d, " PTLS_TO_STR(fn) " failed (%d)\n", __FUNCTION__, __LINE__, (int)ret); \ abort(); \ } \ } while (0) From c4521e8e467410e2c56375aa005d84a0a1ccb4dd Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 10:29:21 +0100 Subject: [PATCH 086/151] have ones own --- t/mbedtls.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/t/mbedtls.c b/t/mbedtls.c index 1a86d9f48..94cf55cd8 100644 --- a/t/mbedtls.c +++ b/t/mbedtls.c @@ -128,15 +128,18 @@ int main(int argc, char **argv) /* context using mbedtls as backend; minicrypto is used for signing certificate as the mbedtls backend does not (yet) have the * capability */ + ptls_minicrypto_secp256r1sha256_sign_certificate_t mbedtls_sign_certificate; + ptls_minicrypto_init_secp256r1sha256_sign_certificate( + &mbedtls_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1)); ptls_context_t mbedtls_ctx = {ptls_mbedtls_random_bytes, &ptls_get_time, ptls_mbedtls_key_exchanges, ptls_mbedtls_cipher_suites, - {&minicrypto_certificate, 1}, + {&secp256r1_certificate, 1}, {{NULL}}, NULL, NULL, - &minicrypto_sign_certificate.super}; + &mbedtls_sign_certificate.super}; ctx = &mbedtls_ctx; ctx_peer = &mbedtls_ctx; From e6ac47f50d15ed66d61df8e1f0588d3850a07cc4 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 10:44:27 +0100 Subject: [PATCH 087/151] amend 2106299 --- lib/mbedtls.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 64b50c22d..54ca9f5f4 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -79,7 +79,11 @@ DEFINE_HASH(sha384, SHA384, PSA_ALG_SHA_384); */ struct st_ptls_mbedtls_cipher_context_t { ptls_cipher_context_t super; + psa_algorithm_t alg; size_t iv_length; + unsigned is_enc : 1; + unsigned is_op_in_progress : 1; + mbedtls_svc_key_id_t key; psa_cipher_operation_t op; }; @@ -87,6 +91,18 @@ static void cipher_init(ptls_cipher_context_t *_ctx, const void *iv) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + if (ctx->is_op_in_progress) { + psa_cipher_abort(&ctx->op); + ctx->is_op_in_progress = 0; + } + + ctx->op = psa_cipher_operation_init(); + if (ctx->is_enc) { + CALL_WITH_CHECK(psa_cipher_encrypt_setup, &ctx->op, ctx->key, ctx->alg); + } else { + CALL_WITH_CHECK(psa_cipher_decrypt_setup, &ctx->op, ctx->key, ctx->alg); + } + ctx->is_op_in_progress = 1; if (ctx->iv_length > 0) CALL_WITH_CHECK(psa_cipher_set_iv, &ctx->op, iv, ctx->iv_length); } @@ -103,14 +119,15 @@ static void cipher_dispose(ptls_cipher_context_t *_ctx) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; - psa_cipher_abort(&ctx->op); + if (ctx->is_op_in_progress) + psa_cipher_abort(&ctx->op); + psa_destroy_key(ctx->key); } static int setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, size_t iv_length, psa_key_type_t key_type, size_t key_bits) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; - mbedtls_svc_key_id_t key; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; /* import key or fail immediately */ @@ -118,20 +135,18 @@ static int setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, key_type); psa_set_key_bits(&attributes, key_bits); - if (psa_import_key(&attributes, key_bytes, key_bits / 8, &key) != PSA_SUCCESS) + if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->key) != PSA_SUCCESS) return PTLS_ERROR_LIBRARY; - /* init context */ + /* init the rest that are guaranteed to succeed */ ctx->super.do_dispose = cipher_dispose; ctx->super.do_init = cipher_init; ctx->super.do_transform = cipher_transform; + ctx->alg = alg; ctx->iv_length = iv_length; + ctx->is_enc = is_enc; + ctx->is_op_in_progress = 0; ctx->op = psa_cipher_operation_init(); - if (is_enc) { - CALL_WITH_CHECK(psa_cipher_encrypt_setup, &ctx->op, key, alg); - } else { - CALL_WITH_CHECK(psa_cipher_decrypt_setup, &ctx->op, key, alg); - } return 0; } From 4d5827ddd46517ec24a31067fedb91e05ea60481 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sat, 4 Nov 2023 10:54:02 +0100 Subject: [PATCH 088/151] `ptls_cipher_init` is not called in ECB mode --- lib/mbedtls.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 54ca9f5f4..f7dd20d56 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -124,7 +124,7 @@ static void cipher_dispose(ptls_cipher_context_t *_ctx) psa_destroy_key(ctx->key); } -static int setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, size_t iv_length, +static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, size_t iv_length, psa_key_type_t key_type, size_t key_bits) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; @@ -151,9 +151,27 @@ static int setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key return 0; } +static int ecb_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, psa_key_type_t key_type, size_t key_bits) +{ + int ret; + + if ((ret = cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, key_type, key_bits)) != 0) + return ret; + /* ECB mode does not necessary call `ptls_cipher_init` */ + cipher_init(ctx, NULL); + + return 0; +} + +static int ctr_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, size_t iv_length, psa_key_type_t key_type, + size_t key_bits) +{ + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, iv_length, key_type, key_bits); +} + static int setup_aes128ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 128); + return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES, 128); } ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { @@ -165,7 +183,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { */ static int setup_aes256ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, PSA_KEY_TYPE_AES, 256); + return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES, 256); } ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { @@ -178,7 +196,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { static int setup_aes128ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 128); + return ctr_setup(ctx, is_enc, key_bytes, 16, PSA_KEY_TYPE_AES, 128); } ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { @@ -191,7 +209,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { static int setup_aes256ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_CTR, 16, PSA_KEY_TYPE_AES, 256); + return ctr_setup(ctx, is_enc, key_bytes, 16, PSA_KEY_TYPE_AES, 256); } ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { @@ -206,7 +224,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { */ static int setup_crypto_chacha20(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return setup_crypto(ctx, is_enc, key_bytes, PSA_ALG_STREAM_CIPHER, 16, PSA_KEY_TYPE_CHACHA20, 256); + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_STREAM_CIPHER, 16, PSA_KEY_TYPE_CHACHA20, 256); } ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { From 9e323048b3f7884331f873e02c4b2286f790e9d8 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 7 Nov 2023 12:55:51 +0100 Subject: [PATCH 089/151] 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; From 046b582a39ea3625cab90c71310a7897c8661e34 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 09:51:33 +0900 Subject: [PATCH 090/151] limit scope of `psa_key_attributes_t` --- lib/mbedtls.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index f7dd20d56..80ed6ce45 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -128,15 +128,16 @@ static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key psa_key_type_t key_type, size_t key_bits) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - /* import key or fail immediately */ - psa_set_key_usage_flags(&attributes, (is_enc) ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&attributes, alg); - psa_set_key_type(&attributes, key_type); - psa_set_key_bits(&attributes, key_bits); - if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->key) != PSA_SUCCESS) - return PTLS_ERROR_LIBRARY; + { /* import key or fail immediately */ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_usage_flags(&attributes, is_enc ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, key_type); + psa_set_key_bits(&attributes, key_bits); + if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->key) != PSA_SUCCESS) + return PTLS_ERROR_LIBRARY; + } /* init the rest that are guaranteed to succeed */ ctx->super.do_dispose = cipher_dispose; From 47411024167a26df38b034f2e4e74deb4f88eaf4 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 10:21:55 +0900 Subject: [PATCH 091/151] move useful comments to `.h`, as they are not specific to the mbedtls backend --- include/picotls.h | 70 +++++++++++++++++++++++++++++++++++++++++------ lib/mbedtls.c | 34 ----------------------- 2 files changed, 62 insertions(+), 42 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index 374543054..49271f77a 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -398,31 +398,81 @@ typedef const struct st_ptls_cipher_algorithm_t { int (*setup_crypto)(ptls_cipher_context_t *ctx, int is_enc, const void *key); } ptls_cipher_algorithm_t; +/** + * This object specifies symmetric cipher to be calculated alongside the AEAD encryption. + * QUIC stacks can use this object to apply QUIC header protection and AEAD encryption in one shot. + */ typedef struct st_ptls_aead_supplementary_encryption_t { + /** + * Cipher context to be used. + */ ptls_cipher_context_t *ctx; + /** + * Input to the cipher. + * This field may point to the output of AEAD encryption, in which case the input will be read after AEAD encryption is + * complete. + */ const void *input; + /** + * Output. + */ uint8_t output[16]; } ptls_aead_supplementary_encryption_t; /** - * AEAD context. AEAD implementations are allowed to stuff data at the end of the struct. The size of the memory allocated for the - * struct is governed by ptls_aead_algorithm_t::context_size. - * Ciphers for TLS over TCP MUST implement `do_encrypt`, `do_encrypt_v`, `do_decrypt`. `do_encrypt_init`, `~update`, `~final` are - * obsolete, and therefore may not be available. + * AEAD context. + * AEAD implementations are allowed to stuff data at the end of the struct; see `ptls_aead_algorithm_t::setup_crypto`. + * Ciphers for TLS over TCP MUST implement `do_encrypt`, `do_encrypt_v`, `do_decrypt`. + * `do_encrypt_init`, `~update`, `~final` are obsolete, and therefore may not be available. */ typedef struct st_ptls_aead_context_t { + /** + * Points to the algorithm. This field is governed by picotls core; backends must not alter. + */ const struct st_ptls_aead_algorithm_t *algo; - /* field above this line must not be altered by the crypto binding */ + /** + * Mandatory callback that disposes of all the backend-specific data. + */ void (*dispose_crypto)(struct st_ptls_aead_context_t *ctx); + /** + * Mandatory callback that returns the static IV. The size of IV is available as `ptls_aead_algorithm_t::iv_size`. + */ void (*do_get_iv)(struct st_ptls_aead_context_t *ctx, void *iv); + /** + * Mandatory callback that sets the static IV. The size of IV is available as `ptls_aead_algorithm_t::iv_size`. + */ void (*do_set_iv)(struct st_ptls_aead_context_t *ctx, const void *iv); + /** + * Deprecated. + */ void (*do_encrypt_init)(struct st_ptls_aead_context_t *ctx, uint64_t seq, const void *aad, size_t aadlen); + /** + * Deprecated. + */ size_t (*do_encrypt_update)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen); + /** + * Deprecated. + */ size_t (*do_encrypt_final)(struct st_ptls_aead_context_t *ctx, void *output); + /** + * Mandatory callback that does "one-shot" encryption of an AEAD block. + * When `supp` is set to non-NULL, the callback must also encrypt the supplementary block. + * Backends may set this field to `ptls_aead__do_encrypt` that calls `do_encrypt_v` and `ptls_cipher_*` functions for handling + * the supplimentary block. + */ void (*do_encrypt)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq, const void *aad, size_t aadlen, ptls_aead_supplementary_encryption_t *supp); + /** + * Variant of `do_encrypt` that gathers input from multiple blocks. Support for this callback is also mandatory. + * Legacy backends may set this field to `ptls_aead__do_encrypt_v` that calls `do_encrypt_init`, `do_encrypt_update`, + * `do_encrypt_final`. + */ void (*do_encrypt_v)(struct st_ptls_aead_context_t *ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq, const void *aad, size_t aadlen); + /** + * Mandatory callback for decrypting an AEAD block. + * If successful, returns the amount of cleartext bytes being written to output. Otherwise, returns SIZE_MAX. + */ size_t (*do_decrypt)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq, const void *aad, size_t aadlen); } ptls_aead_context_t; @@ -479,12 +529,16 @@ typedef const struct st_ptls_aead_algorithm_t { */ uint8_t align_bits; /** - * size of memory allocated for ptls_aead_context_t. AEAD implementations can set this value to something greater than - * sizeof(ptls_aead_context_t) and stuff additional data at the bottom of the struct. + * size of memory allocated for `ptls_aead_context_t` */ size_t context_size; /** - * callback that sets up the crypto + * Backend callback called to setup `ptls_aead_context_t`. + * Backends are allowed to stuff arbitrary data at the end of `ptls_aead_context_t`; actual size of the memory chunk being + * allocated is that specified by `ptls_aead_algorithm_t::context_size`. When the `setup_crypto` callback is called, all the + * fields outside of `ptls_aead_context_t` will be in undefined state; it is the responsibility of the callback to initialize + * them, as well as the callbacks of `ptls_aead_context_t` that the backend supports. + * A non-zero return value indicates failure, in which case the error will propagate as `ptls_aead_new` returning NULL. */ int (*setup_crypto)(ptls_aead_context_t *ctx, int is_enc, const void *key, const void *iv); } ptls_aead_algorithm_t; diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 80ed6ce45..7979802e0 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -290,40 +290,6 @@ ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = {"CHACHA20", setup_chacha20}; #endif -/* Definitions of AEAD algorithms. - * - * For the picotls API, AEAD algorithms are created by calling: - * - * ptls_aead_context_t *ptls_aead_new(ptls_aead_algorithm_t *aead, - * ptls_hash_algorithm_t *hash, int is_enc, const void *secret, - * const char *label_prefix) - * That procedure will allocate memory and create keys, and then call - * a provider specific function: - * - * if (aead->setup_crypto(ctx, is_enc, key, iv) != 0) { - * free(ctx); - * return NULL; - * } - * - * The function will finish completing the aead structure, perform - * initialization, and then document the function pointers: - * - * ctx->super.dispose_crypto: release all resourc - * ctx->super.do_get_iv: return IV - * ctx->super.do_set_iv: set IV value - * ctx->super.do_decrypt: decrypt function - * ctx->super.do_encrypt_init: start encrypting one message - * ctx->super.do_encrypt_update: feed more ciphertext to descriptor - * ctx->super.do_encrypt_final: finalize encryption, including AEAD checksum - * ctx->super.do_encrypt: single shot variant of init/update/final - * ctx->super.do_encrypt_v: scatter gather version of do encrypt - * - * The aead context also documents the underlying "ECB" and "CTR" modes. - * In QUIC, these are used for PN encryption. - * - * TODO: declare other algorithms besides AES128_GCM - */ - struct ptls_mbedtls_aead_param_t { uint8_t static_iv[PTLS_MAX_IV_SIZE]; psa_algorithm_t alg; From 2e4ecad3deb0246327c2c97cea42282b64c13c1f Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 11:04:59 +0900 Subject: [PATCH 092/151] simply AEAD code by only supporting the mandatory operation types --- lib/mbedtls.c | 246 ++++++++++++++------------------------------------ 1 file changed, 70 insertions(+), 176 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 7979802e0..d610b7abc 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -290,224 +290,118 @@ ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = {"CHACHA20", setup_chacha20}; #endif -struct ptls_mbedtls_aead_param_t { +struct ptls_mbedtls_aead_context_t { + struct st_ptls_aead_context_t super; uint8_t static_iv[PTLS_MAX_IV_SIZE]; psa_algorithm_t alg; psa_key_id_t key; - psa_aead_operation_t op; - size_t extra_bytes; - int is_op_in_progress; -}; - -struct ptls_mbedtls_aead_context_t { - struct st_ptls_aead_context_t super; - struct ptls_mbedtls_aead_param_t mctx; }; -void ptls_mbedtls_aead_dispose_crypto(struct st_ptls_aead_context_t *_ctx) -{ - struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; - if (ctx->mctx.is_op_in_progress) { - psa_aead_abort(&ctx->mctx.op); - ctx->mctx.is_op_in_progress = 0; - } - psa_destroy_key(ctx->mctx.key); -} - -static void ptls_mbedtls_aead_get_iv(ptls_aead_context_t *_ctx, void *iv) +static void aead_dispose_crypto(struct st_ptls_aead_context_t *_ctx) { struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; - memcpy(iv, ctx->mctx.static_iv, ctx->super.algo->iv_size); + psa_destroy_key(ctx->key); } -static void ptls_mbedtls_aead_set_iv(ptls_aead_context_t *_ctx, const void *iv) +static void aead_get_iv(ptls_aead_context_t *_ctx, void *iv) { struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; - memcpy(ctx->mctx.static_iv, iv, ctx->super.algo->iv_size); + memcpy(iv, ctx->static_iv, ctx->super.algo->iv_size); } -void ptls_mbedtls_aead_do_encrypt_init(struct st_ptls_aead_context_t *_ctx, uint64_t seq, const void *aad, size_t aadlen) +static void aead_set_iv(ptls_aead_context_t *_ctx, const void *iv) { struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; - psa_status_t status; - - if (ctx->mctx.is_op_in_progress) { - psa_aead_abort(&ctx->mctx.op); /* required on errors, harmless on success */ - ctx->mctx.is_op_in_progress = 0; - } - - ctx->mctx.is_op_in_progress = 1; - memset(&ctx->mctx.op, 0, sizeof(ctx->mctx.op)); - - status = psa_aead_encrypt_setup(&ctx->mctx.op, ctx->mctx.key, ctx->mctx.alg); - if (status == PSA_SUCCESS) { - /* set the nonce. */ - uint8_t iv[PTLS_MAX_IV_SIZE]; - ptls_aead__build_iv(ctx->super.algo, iv, ctx->mctx.static_iv, seq); - status = psa_aead_set_nonce(&ctx->mctx.op, iv, ctx->super.algo->iv_size); - } - - if (status == PSA_SUCCESS) { - status = psa_aead_update_ad(&ctx->mctx.op, aad, aadlen); - } - - if (status != PSA_SUCCESS) { - psa_aead_abort(&ctx->mctx.op); /* required on errors, harmless on success */ - ctx->mctx.is_op_in_progress = 0; - } + memcpy(ctx->static_iv, iv, ctx->super.algo->iv_size); } -size_t ptls_mbedtls_aead_do_encrypt_update(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen) +static void aead_encrypt_v(struct st_ptls_aead_context_t *_ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq, + const void *aad, size_t aadlen) { - size_t olen = 0; struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; + psa_aead_operation_t op = psa_aead_operation_init(); + uint8_t *dst = output, iv[PTLS_MAX_IV_SIZE], tag[PSA_AEAD_TAG_MAX_SIZE]; + size_t outlen, taglen; - if (ctx->mctx.is_op_in_progress) { - size_t available = inlen + ctx->mctx.extra_bytes; - psa_status_t status = - psa_aead_update(&ctx->mctx.op, input, inlen, (uint8_t *)output, available + ctx->super.algo->tag_size, &olen); + /* setup op */ + CALL_WITH_CHECK(psa_aead_encrypt_setup, &op, ctx->key, ctx->alg); + ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); + CALL_WITH_CHECK(psa_aead_set_nonce, &op, iv, ctx->super.algo->iv_size); + CALL_WITH_CHECK(psa_aead_update_ad, &op, aad, aadlen); - if (status == PSA_SUCCESS) { - if (olen < available) { - ctx->mctx.extra_bytes = available - olen; - } else { - ctx->mctx.extra_bytes = 0; - } - } else { - psa_aead_abort(&ctx->mctx.op); /* required on errors */ - ctx->mctx.is_op_in_progress = 0; - } + /* encrypt */ + for (size_t i = 0; i < incnt; i++) { + CALL_WITH_CHECK(psa_aead_update, &op, input[i].base, input[i].len, dst, SIZE_MAX, &outlen); + dst += outlen; } + CALL_WITH_CHECK(psa_aead_finish, &op, dst, SIZE_MAX, &outlen, tag, sizeof(tag), &taglen); + dst += outlen; + memcpy(dst, tag, taglen); - return olen; + /* destroy op */ + psa_aead_abort(&op); } -size_t ptls_mbedtls_aead_do_encrypt_final(struct st_ptls_aead_context_t *_ctx, void *output) +size_t aead_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq, + const void *aad, size_t aadlen) { - size_t olen = 0; struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; + uint8_t iv[PTLS_MAX_IV_SIZE]; + size_t outlen; - if (ctx->mctx.is_op_in_progress) { - unsigned char tag[PSA_AEAD_TAG_MAX_SIZE]; - size_t olen_tag = 0; - size_t available = ctx->mctx.extra_bytes; - uint8_t *p = (uint8_t *)output; - psa_status_t status = - psa_aead_finish(&ctx->mctx.op, p, available + ctx->super.algo->tag_size, &olen, tag, sizeof(tag), &olen_tag); - - if (status == PSA_SUCCESS) { - p += olen; - memcpy(p, tag, ctx->super.algo->tag_size); - olen += ctx->super.algo->tag_size; - } else { - psa_aead_abort(&ctx->mctx.op); /* required on errors */ - } - ctx->mctx.is_op_in_progress = 0; - } - - return (olen); -} - -void ptls_mbedtls_aead_do_encrypt_v(struct st_ptls_aead_context_t *_ctx, void *output, ptls_iovec_t *input, size_t incnt, - uint64_t seq, const void *aad, size_t aadlen) -{ - unsigned char *p = (uint8_t *)output; - - ptls_mbedtls_aead_do_encrypt_init(_ctx, seq, aad, aadlen); + ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); - for (size_t i = 0; i < incnt; i++) { - p += ptls_mbedtls_aead_do_encrypt_update(_ctx, p, input[i].base, input[i].len); + switch (psa_aead_decrypt(ctx->key, ctx->alg, iv, ctx->super.algo->iv_size, aad, aadlen, input, inlen, output, inlen, &outlen)) { + case PSA_SUCCESS: + break; + case PSA_ERROR_INVALID_SIGNATURE: + outlen = SIZE_MAX; + break; + default: + abort(); + break; } - (void)ptls_mbedtls_aead_do_encrypt_final(_ctx, p); -} - -void ptls_mbedtls_aead_do_encrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq, - const void *aad, size_t aadlen, ptls_aead_supplementary_encryption_t *supp) -{ - ptls_iovec_t in_v; - in_v.base = (uint8_t *)input; - in_v.len = inlen; - - ptls_mbedtls_aead_do_encrypt_v(_ctx, output, &in_v, 1, seq, aad, aadlen); -} - -size_t ptls_mbedtls_aead_do_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, - uint64_t seq, const void *aad, size_t aadlen) -{ - size_t o_len = 0; - uint8_t iv[PTLS_MAX_IV_SIZE]; - struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; - psa_status_t status; - /* set the nonce. */ - ptls_aead__build_iv(ctx->super.algo, iv, ctx->mctx.static_iv, seq); - - status = psa_aead_decrypt(ctx->mctx.key, ctx->mctx.alg, iv, ctx->super.algo->iv_size, (uint8_t *)aad, aadlen, (uint8_t *)input, - inlen, (uint8_t *)output, inlen, &o_len); - if (status != PSA_SUCCESS) { - o_len = inlen + 1; - } - return o_len; + return outlen; } -static int ptls_mbedtls_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv, - psa_algorithm_t psa_alg, size_t key_bits, psa_key_type_t key_type) +static int aead_setup(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv, psa_algorithm_t psa_alg, + size_t key_bits, psa_key_type_t key_type) { - int ret = 0; struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; - /* set mbed specific context to NULL, just to be sure */ - memset(&ctx->mctx, 0, sizeof(struct ptls_mbedtls_aead_param_t)); - ctx->mctx.alg = psa_alg; - - /* Initialize the key attributes */ - if (ret == 0) { + { /* setup key */ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_set_key_usage_flags(&attributes, (is_enc) ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&attributes, ctx->mctx.alg); + psa_set_key_usage_flags(&attributes, is_enc ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, psa_alg); psa_set_key_type(&attributes, key_type); psa_set_key_bits(&attributes, key_bits); - /* Import key */ - if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->mctx.key) != PSA_SUCCESS) { - ret = PTLS_ERROR_LIBRARY; - } - } - - if (ret == 0) { - /* Store the static IV */ - if (ctx->super.algo->iv_size > PTLS_MAX_IV_SIZE) { - ret = PTLS_ERROR_LIBRARY; - } else { - memcpy(ctx->mctx.static_iv, iv, ctx->super.algo->iv_size); - ctx->mctx.is_op_in_progress = 0; - } + if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->key) != PSA_SUCCESS) + return PTLS_ERROR_LIBRARY; } - /* set the pointers to the individual functions */ - if (ret == 0) { - if (is_enc) { - ctx->super.do_encrypt_init = ptls_mbedtls_aead_do_encrypt_init; - ctx->super.do_encrypt_update = ptls_mbedtls_aead_do_encrypt_update; - ctx->super.do_encrypt_final = ptls_mbedtls_aead_do_encrypt_final; - ctx->super.do_encrypt = ptls_mbedtls_aead_do_encrypt; - ctx->super.do_encrypt_v = ptls_mbedtls_aead_do_encrypt_v; - } else { - ctx->super.do_decrypt = ptls_mbedtls_aead_do_decrypt; - } - ctx->super.dispose_crypto = ptls_mbedtls_aead_dispose_crypto; - ctx->super.do_get_iv = ptls_mbedtls_aead_get_iv; - ctx->super.do_set_iv = ptls_mbedtls_aead_set_iv; + /* setup the rest */ + ctx->super.dispose_crypto = aead_dispose_crypto; + ctx->super.do_get_iv = aead_get_iv; + ctx->super.do_set_iv = aead_set_iv; + if (is_enc) { + ctx->super.do_encrypt = ptls_aead__do_encrypt; + ctx->super.do_encrypt_v = aead_encrypt_v; + } else { + ctx->super.do_decrypt = aead_decrypt; } + memcpy(ctx->static_iv, iv, ctx->super.algo->iv_size); + ctx->alg = psa_alg; - return ret; + return 0; } -static int ptls_mbedtls_aead_setup_aes128gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) +static int aead_setup_aes128gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) { - return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 128, PSA_KEY_TYPE_AES); + return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 128, PSA_KEY_TYPE_AES); } ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = {"AES128-GCM", @@ -522,16 +416,16 @@ ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = {"AES128-GCM", 0, 0, sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_aes128gcm}; + aead_setup_aes128gcm}; ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256 = {.id = PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, .name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256, .aead = &ptls_mbedtls_aes128gcm, .hash = &ptls_mbedtls_sha256}; -static int ptls_mbedtls_aead_setup_aes256gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) +static int aead_setup_aes256gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) { - return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 256, PSA_KEY_TYPE_AES); + return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 256, PSA_KEY_TYPE_AES); } ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = {"AES256-GCM", @@ -546,16 +440,16 @@ ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = {"AES256-GCM", 0, 0, sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_aes256gcm}; + aead_setup_aes256gcm}; ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = {.id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, .name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384, .aead = &ptls_mbedtls_aes256gcm, .hash = &ptls_mbedtls_sha384}; -static int ptls_mbedtls_aead_setup_chacha20poly1305(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) +static int aead_setup_chacha20poly1305(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) { - return ptls_mbedtls_aead_setup_crypto(_ctx, is_enc, key_bytes, iv, PSA_ALG_CHACHA20_POLY1305, 256, PSA_KEY_TYPE_CHACHA20); + return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_CHACHA20_POLY1305, 256, PSA_KEY_TYPE_CHACHA20); } ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = {"CHACHA20-POLY1305", @@ -570,7 +464,7 @@ ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = {"CHACHA20-POLY1305", 0, 0, sizeof(struct ptls_mbedtls_aead_context_t), - ptls_mbedtls_aead_setup_chacha20poly1305}; + aead_setup_chacha20poly1305}; ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256, .name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256, From 7550f87de350b8a82f288e8768ee23103cf3dc86 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 11:16:29 +0900 Subject: [PATCH 093/151] update test code to not rely on init-update-final cycle that is now optional (see doc-comment of ptls_aead_context_t) --- t/picotls.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/t/picotls.c b/t/picotls.c index ecca51d3c..b61dfce16 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -225,12 +225,8 @@ static void test_ciphersuite(ptls_cipher_suite_t *cs1, ptls_cipher_suite_t *cs2) /* encrypt */ c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL); assert(c != NULL); - ptls_aead_encrypt_init(c, 0, NULL, 0); - enc1len = ptls_aead_encrypt_update(c, enc1, src1, strlen(src1)); - enc1len += ptls_aead_encrypt_final(c, enc1 + enc1len); - ptls_aead_encrypt_init(c, 1, NULL, 0); - enc2len = ptls_aead_encrypt_update(c, enc2, src2, strlen(src2)); - enc2len += ptls_aead_encrypt_final(c, enc2 + enc2len); + enc1len = ptls_aead_encrypt(c, enc1, src1, strlen(src1), 0, NULL, 0); + enc2len = ptls_aead_encrypt(c, enc2, src2, strlen(src2), 1, NULL, 0); ptls_aead_free(c); c = ptls_aead_new(cs2->aead, cs2->hash, 0, traffic_secret, NULL); @@ -275,6 +271,10 @@ static void test_ciphersuite_stream(ptls_cipher_suite_t *cs1, ptls_cipher_suite_ /* encrypt */ c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL); assert(c != NULL); + if (c->do_encrypt_init == NULL) { + note("new ciphers may omit support for init-update-final"); + return; + } ptls_aead_encrypt_init(c, 0, NULL, 0); enclen = 0; for (size_t i = 0; text[i] != NULL; ++i) @@ -311,9 +311,7 @@ static void test_aad_ciphersuite(ptls_cipher_suite_t *cs1, ptls_cipher_suite_t * /* encrypt */ c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL); assert(c != NULL); - ptls_aead_encrypt_init(c, 123, aad, strlen(aad)); - enclen = ptls_aead_encrypt_update(c, enc, src, strlen(src)); - enclen += ptls_aead_encrypt_final(c, enc + enclen); + enclen = ptls_aead_encrypt(c, enc, src, strlen(src), 123, aad, strlen(aad)); ptls_aead_free(c); /* decrypt */ @@ -340,9 +338,7 @@ static void test_aad96_ciphersuite(ptls_cipher_suite_t *cs1, ptls_cipher_suite_t c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL); assert(c != NULL); ptls_aead_xor_iv(c, seq32, sizeof(seq32)); - ptls_aead_encrypt_init(c, 123, aad, strlen(aad)); - enclen = ptls_aead_encrypt_update(c, enc, src, strlen(src)); - enclen += ptls_aead_encrypt_final(c, enc + enclen); + enclen = ptls_aead_encrypt(c, enc, src, strlen(src), 123, aad, strlen(aad)); ptls_aead_free(c); /* decrypt */ From fc2bae6018990116caa1f167f7461165ff7e728e Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 11:26:20 +0900 Subject: [PATCH 094/151] fail the same way --- lib/mbedtls.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index d610b7abc..cf5ca055b 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -32,13 +32,17 @@ #include #include "picotls.h" +#define PSA_FUNC_FAILED(fn, ret) \ + do { \ + fprintf(stderr, "in %s at line %d, " PTLS_TO_STR(fn) " failed (%d)\n", __FUNCTION__, __LINE__, (int)ret); \ + abort(); \ + } while (0) + #define CALL_WITH_CHECK(fn, ...) \ do { \ psa_status_t ret; \ - if ((ret = fn(__VA_ARGS__)) != PSA_SUCCESS) { \ - fprintf(stderr, "in %s at line %d, " PTLS_TO_STR(fn) " failed (%d)\n", __FUNCTION__, __LINE__, (int)ret); \ - abort(); \ - } \ + if ((ret = fn(__VA_ARGS__)) != PSA_SUCCESS) \ + PSA_FUNC_FAILED(fn, ret); \ } while (0) void ptls_mbedtls_random_bytes(void *buf, size_t len) @@ -247,17 +251,18 @@ static void chacha20_init(ptls_cipher_context_t *_ctx, const void *v_iv) const uint8_t *iv = (const uint8_t *)v_iv; uint32_t ctr = iv[0] | ((uint32_t)iv[1] << 8) | ((uint32_t)iv[2] << 16) | ((uint32_t)iv[3] << 24); - (void)mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t *)(iv + 4), ctr); + int ret = mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t *)(iv + 4), ctr); + if (ret != 0) + PSA_FUNC_FAILED(mbedtls_chacha20_starts, ret); } static void chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) { struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; - if (mbedtls_chacha20_update(&ctx->mctx, len, (const uint8_t *)input, (uint8_t *)output) != 0) { - fprintf(stderr, "mbedtls_chacha20_update failed\n"); - abort(); - } + int ret = mbedtls_chacha20_update(&ctx->mctx, len, (const uint8_t *)input, (uint8_t *)output); + if (ret != 0) + PSA_FUNC_FAILED(mbedtls_chacha20_update, ret); } static void chacha20_dispose(ptls_cipher_context_t *_ctx) @@ -354,14 +359,16 @@ size_t aead_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const voi ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); - switch (psa_aead_decrypt(ctx->key, ctx->alg, iv, ctx->super.algo->iv_size, aad, aadlen, input, inlen, output, inlen, &outlen)) { + psa_status_t ret = + psa_aead_decrypt(ctx->key, ctx->alg, iv, ctx->super.algo->iv_size, aad, aadlen, input, inlen, output, inlen, &outlen); + switch (ret) { case PSA_SUCCESS: break; case PSA_ERROR_INVALID_SIGNATURE: outlen = SIZE_MAX; break; default: - abort(); + PSA_FUNC_FAILED(psa_aead_decrypt, ret); break; } From 0635d6e2ef08304cbde7a8978fc2d9b8ab984b0d Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 11:51:36 +0900 Subject: [PATCH 095/151] expand doc-comment in picotls.h instead --- include/picotls.h | 13 +++++++++---- lib/mbedtls.c | 22 ---------------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index 49271f77a..3b7a96dec 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -338,11 +338,14 @@ typedef struct st_ptls_key_exchange_context_t { */ const struct st_ptls_key_exchange_algorithm_t *algo; /** - * the public key + * public key of this context */ ptls_iovec_t pubkey; /** - * If `release` is set, the callee frees resources allocated to the context and set *keyex to NULL + * This function can be used for deriving a shared secret or for destroying the context. + * When `secret` is non-NULL, this callback derives the shared secret using the public key of the context and the peer key being + * given, and sets the value in `secret`. The memory pointed to by `secret->base` must be freed by the caller by calling `free`. + * When `release` is set, the callee frees resources allocated to the context and set *keyex to NULL. */ int (*on_exchange)(struct st_ptls_key_exchange_context_t **keyex, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey); } ptls_key_exchange_context_t; @@ -356,12 +359,14 @@ typedef const struct st_ptls_key_exchange_algorithm_t { */ uint16_t id; /** - * creates a context for asynchronous key exchange. The function is called when ClientHello is generated. The on_exchange + * Creates a context for asynchronous key exchange. The function is called when ClientHello is generated. The on_exchange * callback of the created context is called when the client receives ServerHello. */ int (*create)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx); /** - * implements synchronous key exchange. Called when receiving a ServerHello. + * Implements synchronous key exchange. Called when receiving a ServerHello. + * Given a public key provided by the peer (`peerkey`), this callback returns a empheral public key (`pubkey`) and a secret + * (`secret) `derived from the two public keys. */ int (*exchange)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey); diff --git a/lib/mbedtls.c b/lib/mbedtls.c index cf5ca055b..ffe4d96ab 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -481,28 +481,6 @@ ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUI ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[] = {&ptls_mbedtls_aes256gcmsha384, &ptls_mbedtls_aes128gcmsha256, &ptls_mbedtls_chacha20poly1305sha256, NULL}; -/* Key exchange algorithms. - * The Picotls framework defines these algorithms as ptls_key_exchange_algorithm_t, - * a structure containing two function pointers: - * - * int (*create)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx); - * int (*exchange)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, - * ptls_iovec_t peerkey); - * The "create" call is used on the client. It documents the ptls_key_exchange_context_t, which contains - * the public key prepared by the client, as an iovec, and a function pointer: - * - * int (*on_exchange)(struct st_ptls_key_exchange_context_t **keyex, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey); - * - * The public key of the client is passed to the server an ends up as "peerkey" argument to the (exchange) function. - * That function documents the server's public key, and the secret computed by combining server and client key. - * - * When the client receives the server hello, the stack calls the "on_exchange" callback, passing the context - * previously created by the client and the public key of the peer, so the client can compute its own - * version of the secret. - * - * The following code uses the MbedTLS PSA API to create the "create", "exchange" and "on_exchange" functions. - */ - #define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 struct ptls_mbedtls_key_exchange_context_t { From bf9e1d735df6321089ab3e368d45684a237ece85 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 12:22:04 +0900 Subject: [PATCH 096/151] reduce state, release memory regardless of errors --- lib/mbedtls.c | 187 ++++++++++++++++++++++++-------------------------- 1 file changed, 88 insertions(+), 99 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index ffe4d96ab..6a5a59fe7 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -486,18 +486,15 @@ ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[] = {&ptls_mbedtls_aes256gcmsha3 struct ptls_mbedtls_key_exchange_context_t { ptls_key_exchange_context_t super; psa_algorithm_t psa_alg; - psa_ecc_family_t curve; - size_t curve_bits; size_t secret_size; psa_key_id_t private_key; - uint8_t pub[PTLS_MBEDTLS_ECDH_PUBKEY_MAX]; + uint8_t pubkeybuf[PTLS_MBEDTLS_ECDH_PUBKEY_MAX]; }; -/* Set a private key for key exchange. For now, we only support ECC +/** + * Generates a private key. For now, we only support ECC. */ - -static int ptls_mbedtls_key_exchange_set_private_key(psa_key_id_t *private_key, psa_algorithm_t psa_alg, psa_ecc_family_t curve, - size_t curve_bits) +static int generate_private_key(psa_key_id_t *private_key, psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; int ret = 0; @@ -512,123 +509,115 @@ static int ptls_mbedtls_key_exchange_set_private_key(psa_key_id_t *private_key, return ret; } -/* -* The key agreement is done by calling psa_raw_key_agreement -psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, -psa_key_id_t private_key, -const uint8_t * peer_key, -size_t peer_key_length, -uint8_t * output, -size_t output_size, -size_t * output_length); -*/ - -int ptls_mbedtls_key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_pctx, int release, ptls_iovec_t *secret, - ptls_iovec_t peerkey) +int key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_keyex, int release, ptls_iovec_t *secret, + ptls_iovec_t peerkey) { + struct ptls_mbedtls_key_exchange_context_t *keyex = (struct ptls_mbedtls_key_exchange_context_t *)*_keyex; int ret = 0; - struct ptls_mbedtls_key_exchange_context_t *keyex = (struct ptls_mbedtls_key_exchange_context_t *)*_pctx; - - if (secret != NULL) { - uint8_t *secbytes = (uint8_t *)malloc(keyex->secret_size); - - if (secbytes == NULL) { - ret = PTLS_ERROR_NO_MEMORY; - } else { - size_t olen; - if (psa_raw_key_agreement(keyex->psa_alg, keyex->private_key, (const uint8_t *)peerkey.base, peerkey.len, secbytes, - keyex->secret_size, &olen) == 0) { - *secret = ptls_iovec_init(secbytes, keyex->secret_size); - } else { - free(secbytes); - ret = PTLS_ERROR_LIBRARY; - } - } + + if (secret == NULL) + goto Exit; + + /* derive shared secret */ + if ((secret->base = malloc(keyex->secret_size)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; + } + if (psa_raw_key_agreement(keyex->psa_alg, keyex->private_key, peerkey.base, peerkey.len, secret->base, keyex->secret_size, + &secret->len) != 0) { + ret = PTLS_ERROR_LIBRARY; + goto Exit; + } + assert(keyex->secret_size == secret->len); + ret = 0; + +Exit: + if (ret != 0 && secret != NULL) { + free(secret->base); + *secret = ptls_iovec_init(NULL, 0); } if (release) { - /* Clear the private key */ psa_destroy_key(keyex->private_key); - /* Set context to NULL */ - *_pctx = NULL; - /* TODO: check whether allocated memory should be freed */ + free(keyex); + *_keyex = NULL; } - return ret; } -int ptls_mbedtls_key_exchange_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx, - psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) +static int key_exchange_create(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx, psa_algorithm_t psa_alg, + psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) { struct ptls_mbedtls_key_exchange_context_t *keyex; - size_t olen = 0; - if ((keyex = (struct ptls_mbedtls_key_exchange_context_t *)malloc(sizeof(struct ptls_mbedtls_key_exchange_context_t))) == NULL) + *ctx = NULL; + + /* setup context */ + if ((keyex = malloc(sizeof(*keyex))) == NULL) return PTLS_ERROR_NO_MEMORY; - /* Initialize the exchange context based on the algorithm definition */ - keyex->psa_alg = psa_alg; - keyex->curve = curve; - keyex->curve_bits = curve_bits; - keyex->secret_size = secret_size; - /* Initialize the private key and format the public key */ - if (ptls_mbedtls_key_exchange_set_private_key(&keyex->private_key, psa_alg, curve, curve_bits) != 0) { + *keyex = (struct ptls_mbedtls_key_exchange_context_t){ + .super.algo = algo, + .super.pubkey.base = keyex->pubkeybuf, + .super.on_exchange = key_exchange_on_exchange, + .psa_alg = psa_alg, + .secret_size = secret_size, + }; + + /* generate private key */ + if (generate_private_key(&keyex->private_key, psa_alg, curve, curve_bits) != 0) { free(keyex); - *ctx = NULL; return PTLS_ERROR_LIBRARY; } - /* According to the doc, format of public key is same as picotls */ - if (psa_export_public_key(keyex->private_key, keyex->pub, sizeof(keyex->pub), &olen) != 0) { - psa_destroy_key(keyex->private_key); - free(keyex); - *ctx = NULL; - return PTLS_ERROR_LIBRARY; + { /* export public key */ + psa_status_t ret = + psa_export_public_key(keyex->private_key, keyex->pubkeybuf, sizeof(keyex->pubkeybuf), &keyex->super.pubkey.len); + if (ret != 0) + PSA_FUNC_FAILED(psa_export_public_key, ret); } - keyex->super.pubkey = ptls_iovec_init(keyex->pub, olen); - /* Initialize the ptls exchange context */ - keyex->super.algo = algo; - keyex->super.on_exchange = ptls_mbedtls_key_exchange_on_exchange; - *ctx = (ptls_key_exchange_context_t *)keyex; + + *ctx = &keyex->super; return 0; } -static int ptls_mbedtls_key_exchange_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, - ptls_iovec_t *secret, ptls_iovec_t peerkey, psa_algorithm_t psa_alg, - psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) +static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, + ptls_iovec_t peerkey, psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits, + size_t secret_size) { - /* generate a local private key for the selected algorithm */ psa_key_id_t private_key; - size_t pubkey_len; - uint8_t *pubkey_bytes = NULL; - size_t secret_len; - uint8_t *secret_bytes = (uint8_t *)malloc(secret_size); - int ret = 0; + int ret; - if (secret_bytes == NULL) { - return PTLS_ERROR_NO_MEMORY; - } - pubkey_bytes = (uint8_t *)malloc(PTLS_MBEDTLS_ECDH_PUBKEY_MAX); - if (pubkey_bytes == NULL) { - free(secret_bytes); - return PTLS_ERROR_NO_MEMORY; - } + *pubkey = ptls_iovec_init(NULL, 0); + *secret = ptls_iovec_init(NULL, 0); - if (ptls_mbedtls_key_exchange_set_private_key(&private_key, psa_alg, curve, curve_bits) != 0) { - free(secret_bytes); - free(pubkey_bytes); + /* generate private key (and return immediately upon failure) */ + if (generate_private_key(&private_key, psa_alg, curve, curve_bits) != 0) return PTLS_ERROR_LIBRARY; + + /* allocate buffers */ + if ((secret->base = malloc(secret_size)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; + } + if ((pubkey->base = malloc(PTLS_MBEDTLS_ECDH_PUBKEY_MAX)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; } - /* Export public key and call key agrement function */ - if (psa_export_public_key(private_key, pubkey_bytes, PTLS_MBEDTLS_ECDH_PUBKEY_MAX, &pubkey_len) == 0 && - psa_raw_key_agreement(psa_alg, private_key, (const uint8_t *)peerkey.base, peerkey.len, secret_bytes, secret_size, - &secret_len) == 0) { - *secret = ptls_iovec_init(secret_bytes, secret_len); - *pubkey = ptls_iovec_init(pubkey_bytes, pubkey_len); - } else { - free(secret_bytes); - free(pubkey_bytes); - return PTLS_ERROR_LIBRARY; + /* export public key and call key agrement function */ + if (psa_export_public_key(private_key, pubkey->base, PTLS_MBEDTLS_ECDH_PUBKEY_MAX, &pubkey->len) != 0 || + psa_raw_key_agreement(psa_alg, private_key, peerkey.base, peerkey.len, secret->base, secret_size, &secret->len) != 0) { + ret = PTLS_ERROR_LIBRARY; + goto Exit; } + ret = 0; + +Exit: + if (ret != 0) { + free(pubkey->base); + *pubkey = ptls_iovec_init(NULL, 0); + free(secret->base); + *secret = ptls_iovec_init(NULL, 0); + } psa_destroy_key(private_key); return ret; @@ -638,13 +627,13 @@ static int ptls_mbedtls_key_exchange_exchange(const struct st_ptls_key_exchange_ */ static int ptls_mbedtls_secp256r1_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { - return ptls_mbedtls_key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); + return key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); } static int ptls_mbedtls_secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey) { - return ptls_mbedtls_key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); + return key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); } ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = {.id = PTLS_GROUP_SECP256R1, @@ -656,13 +645,13 @@ ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = {.id = PTLS_GROUP_SECP256 */ static int ptls_mbedtls_x25519_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { - return ptls_mbedtls_key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); + return key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); } static int ptls_mbedtls_x25519_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey) { - return ptls_mbedtls_key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); + return key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); } ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = {.id = PTLS_GROUP_X25519, From 60f4749cb8b4473439e23433cd6156ee9d547ff7 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 14:56:38 +0900 Subject: [PATCH 097/151] add missing `static` --- lib/mbedtls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 6a5a59fe7..4e74c4fe6 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -350,8 +350,8 @@ static void aead_encrypt_v(struct st_ptls_aead_context_t *_ctx, void *output, pt psa_aead_abort(&op); } -size_t aead_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq, - const void *aad, size_t aadlen) +static size_t aead_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq, + const void *aad, size_t aadlen) { struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; uint8_t iv[PTLS_MAX_IV_SIZE]; @@ -509,8 +509,8 @@ static int generate_private_key(psa_key_id_t *private_key, psa_algorithm_t psa_a return ret; } -int key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_keyex, int release, ptls_iovec_t *secret, - ptls_iovec_t peerkey) +static int key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_keyex, int release, ptls_iovec_t *secret, + ptls_iovec_t peerkey) { struct ptls_mbedtls_key_exchange_context_t *keyex = (struct ptls_mbedtls_key_exchange_context_t *)*_keyex; int ret = 0; From 8a694b6fb64f896b7f8ee24c0c3682eb06ae51b6 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 14:57:34 +0900 Subject: [PATCH 098/151] no need to have prefix for static functions --- lib/mbedtls.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 4e74c4fe6..610e9fa94 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -625,38 +625,34 @@ static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec /* Instantiation of the generic key exchange API with secp256r1 */ -static int ptls_mbedtls_secp256r1_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) +static int secp256r1_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { return key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); } -static int ptls_mbedtls_secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, - ptls_iovec_t *secret, ptls_iovec_t peerkey) +static int secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, + ptls_iovec_t peerkey) { return key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); } -ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = {.id = PTLS_GROUP_SECP256R1, - .name = PTLS_GROUP_NAME_SECP256R1, - .create = ptls_mbedtls_secp256r1_create, - .exchange = ptls_mbedtls_secp256r1_exchange}; +ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = { + .id = PTLS_GROUP_SECP256R1, .name = PTLS_GROUP_NAME_SECP256R1, .create = secp256r1_create, .exchange = secp256r1_exchange}; /* Instantiation of the generic key exchange API with x25519 */ -static int ptls_mbedtls_x25519_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) +static int x25519_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { return key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); } -static int ptls_mbedtls_x25519_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, - ptls_iovec_t *secret, ptls_iovec_t peerkey) +static int x25519_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, + ptls_iovec_t peerkey) { return key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); } -ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = {.id = PTLS_GROUP_X25519, - .name = PTLS_GROUP_NAME_X25519, - .create = ptls_mbedtls_x25519_create, - .exchange = ptls_mbedtls_x25519_exchange}; +ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = { + .id = PTLS_GROUP_X25519, .name = PTLS_GROUP_NAME_X25519, .create = x25519_create, .exchange = x25519_exchange}; ptls_key_exchange_algorithm_t *ptls_mbedtls_key_exchanges[] = {&ptls_mbedtls_secp256r1, NULL}; From 25e0ab8bde0dd54136b2f0ae8b2e22f9bb418164 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 15:08:48 +0900 Subject: [PATCH 099/151] consolidate duplicated constants into `const struct` --- lib/mbedtls.c | 54 ++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 610e9fa94..256dfca53 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -483,10 +483,17 @@ ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[] = {&ptls_mbedtls_aes256gcmsha3 #define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 +static const struct ptls_mbedtls_key_exchange_params_t { + psa_algorithm_t alg; + psa_ecc_family_t curve; + size_t curve_bits; + size_t secret_size; +} secp256r1_params = {PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32}, + x25519_params = {PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32}; + struct ptls_mbedtls_key_exchange_context_t { ptls_key_exchange_context_t super; - psa_algorithm_t psa_alg; - size_t secret_size; + const struct ptls_mbedtls_key_exchange_params_t *params; psa_key_id_t private_key; uint8_t pubkeybuf[PTLS_MBEDTLS_ECDH_PUBKEY_MAX]; }; @@ -494,15 +501,15 @@ struct ptls_mbedtls_key_exchange_context_t { /** * Generates a private key. For now, we only support ECC. */ -static int generate_private_key(psa_key_id_t *private_key, psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits) +static int generate_private_key(psa_key_id_t *private_key, const struct ptls_mbedtls_key_exchange_params_t *params) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; int ret = 0; psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); - psa_set_key_algorithm(&attributes, psa_alg); - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); - psa_set_key_bits(&attributes, curve_bits); + psa_set_key_algorithm(&attributes, params->alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(params->curve)); + psa_set_key_bits(&attributes, params->curve_bits); if (psa_generate_key(&attributes, private_key) != 0) { ret = -1; } @@ -519,16 +526,16 @@ static int key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_key goto Exit; /* derive shared secret */ - if ((secret->base = malloc(keyex->secret_size)) == NULL) { + if ((secret->base = malloc(keyex->params->secret_size)) == NULL) { ret = PTLS_ERROR_NO_MEMORY; goto Exit; } - if (psa_raw_key_agreement(keyex->psa_alg, keyex->private_key, peerkey.base, peerkey.len, secret->base, keyex->secret_size, - &secret->len) != 0) { + if (psa_raw_key_agreement(keyex->params->alg, keyex->private_key, peerkey.base, peerkey.len, secret->base, + keyex->params->secret_size, &secret->len) != 0) { ret = PTLS_ERROR_LIBRARY; goto Exit; } - assert(keyex->secret_size == secret->len); + assert(keyex->params->secret_size == secret->len); ret = 0; Exit: @@ -544,8 +551,8 @@ static int key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_key return ret; } -static int key_exchange_create(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx, psa_algorithm_t psa_alg, - psa_ecc_family_t curve, size_t curve_bits, size_t secret_size) +static int key_exchange_create(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx, + const struct ptls_mbedtls_key_exchange_params_t *params) { struct ptls_mbedtls_key_exchange_context_t *keyex; @@ -558,12 +565,11 @@ static int key_exchange_create(ptls_key_exchange_algorithm_t *algo, ptls_key_exc .super.algo = algo, .super.pubkey.base = keyex->pubkeybuf, .super.on_exchange = key_exchange_on_exchange, - .psa_alg = psa_alg, - .secret_size = secret_size, + .params = params, }; /* generate private key */ - if (generate_private_key(&keyex->private_key, psa_alg, curve, curve_bits) != 0) { + if (generate_private_key(&keyex->private_key, keyex->params) != 0) { free(keyex); return PTLS_ERROR_LIBRARY; } @@ -579,8 +585,7 @@ static int key_exchange_create(ptls_key_exchange_algorithm_t *algo, ptls_key_exc } static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, - ptls_iovec_t peerkey, psa_algorithm_t psa_alg, psa_ecc_family_t curve, size_t curve_bits, - size_t secret_size) + ptls_iovec_t peerkey, const struct ptls_mbedtls_key_exchange_params_t *params) { psa_key_id_t private_key; int ret; @@ -589,11 +594,11 @@ static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec *secret = ptls_iovec_init(NULL, 0); /* generate private key (and return immediately upon failure) */ - if (generate_private_key(&private_key, psa_alg, curve, curve_bits) != 0) + if (generate_private_key(&private_key, params) != 0) return PTLS_ERROR_LIBRARY; /* allocate buffers */ - if ((secret->base = malloc(secret_size)) == NULL) { + if ((secret->base = malloc(params->secret_size)) == NULL) { ret = PTLS_ERROR_NO_MEMORY; goto Exit; } @@ -604,7 +609,8 @@ static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec /* export public key and call key agrement function */ if (psa_export_public_key(private_key, pubkey->base, PTLS_MBEDTLS_ECDH_PUBKEY_MAX, &pubkey->len) != 0 || - psa_raw_key_agreement(psa_alg, private_key, peerkey.base, peerkey.len, secret->base, secret_size, &secret->len) != 0) { + psa_raw_key_agreement(params->alg, private_key, peerkey.base, peerkey.len, secret->base, params->secret_size, + &secret->len) != 0) { ret = PTLS_ERROR_LIBRARY; goto Exit; } @@ -627,13 +633,13 @@ static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec */ static int secp256r1_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { - return key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); + return key_exchange_create(algo, ctx, &secp256r1_params); } static int secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey) { - return key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32); + return key_exchange_exchange(algo, pubkey, secret, peerkey, &secp256r1_params); } ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = { @@ -643,13 +649,13 @@ ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = { */ static int x25519_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { - return key_exchange_create(algo, ctx, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); + return key_exchange_create(algo, ctx, &x25519_params); } static int x25519_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey) { - return key_exchange_exchange(algo, pubkey, secret, peerkey, PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32); + return key_exchange_exchange(algo, pubkey, secret, peerkey, &x25519_params); } ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = { From 0069e3c2fdf6855c57532d48ee16ed18b1b6936f Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 15:13:58 +0900 Subject: [PATCH 100/151] reduce state --- lib/mbedtls.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 256dfca53..a2136e3cf 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -84,7 +84,6 @@ DEFINE_HASH(sha384, SHA384, PSA_ALG_SHA_384); struct st_ptls_mbedtls_cipher_context_t { ptls_cipher_context_t super; psa_algorithm_t alg; - size_t iv_length; unsigned is_enc : 1; unsigned is_op_in_progress : 1; mbedtls_svc_key_id_t key; @@ -107,8 +106,8 @@ static void cipher_init(ptls_cipher_context_t *_ctx, const void *iv) CALL_WITH_CHECK(psa_cipher_decrypt_setup, &ctx->op, ctx->key, ctx->alg); } ctx->is_op_in_progress = 1; - if (ctx->iv_length > 0) - CALL_WITH_CHECK(psa_cipher_set_iv, &ctx->op, iv, ctx->iv_length); + if (ctx->super.algo->iv_size > 0) + CALL_WITH_CHECK(psa_cipher_set_iv, &ctx->op, iv, ctx->super.algo->iv_size); } static void cipher_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) @@ -128,8 +127,8 @@ static void cipher_dispose(ptls_cipher_context_t *_ctx) psa_destroy_key(ctx->key); } -static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, size_t iv_length, - psa_key_type_t key_type, size_t key_bits) +static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, + psa_key_type_t key_type) { struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; @@ -138,8 +137,8 @@ static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key psa_set_key_usage_flags(&attributes, is_enc ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, key_type); - psa_set_key_bits(&attributes, key_bits); - if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->key) != PSA_SUCCESS) + psa_set_key_bits(&attributes, ctx->super.algo->key_size * 8); + if (psa_import_key(&attributes, key_bytes, ctx->super.algo->key_size, &ctx->key) != PSA_SUCCESS) return PTLS_ERROR_LIBRARY; } @@ -148,7 +147,6 @@ static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key ctx->super.do_init = cipher_init; ctx->super.do_transform = cipher_transform; ctx->alg = alg; - ctx->iv_length = iv_length; ctx->is_enc = is_enc; ctx->is_op_in_progress = 0; ctx->op = psa_cipher_operation_init(); @@ -156,11 +154,11 @@ static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key return 0; } -static int ecb_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, psa_key_type_t key_type, size_t key_bits) +static int ecb_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, psa_key_type_t key_type) { int ret; - if ((ret = cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, 0, key_type, key_bits)) != 0) + if ((ret = cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, key_type)) != 0) return ret; /* ECB mode does not necessary call `ptls_cipher_init` */ cipher_init(ctx, NULL); @@ -168,15 +166,14 @@ static int ecb_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_byt return 0; } -static int ctr_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, size_t iv_length, psa_key_type_t key_type, - size_t key_bits) +static int ctr_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, psa_key_type_t key_type) { - return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, iv_length, key_type, key_bits); + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, key_type); } static int setup_aes128ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES, 128); + return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); } ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { @@ -188,7 +185,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { */ static int setup_aes256ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES, 256); + return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); } ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { @@ -201,7 +198,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { static int setup_aes128ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ctr_setup(ctx, is_enc, key_bytes, 16, PSA_KEY_TYPE_AES, 128); + return ctr_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); } ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { @@ -214,7 +211,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { static int setup_aes256ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ctr_setup(ctx, is_enc, key_bytes, 16, PSA_KEY_TYPE_AES, 256); + return ctr_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); } ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { @@ -229,7 +226,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { */ static int setup_crypto_chacha20(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_STREAM_CIPHER, 16, PSA_KEY_TYPE_CHACHA20, 256); + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_STREAM_CIPHER, 16, PSA_KEY_TYPE_CHACHA20); } ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { From 177c1564e46fd3195729a8007d4873f00d51c29f Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 15:17:03 +0900 Subject: [PATCH 101/151] ... and we find a bug --- lib/mbedtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index a2136e3cf..ed9374d5a 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -189,7 +189,7 @@ static int setup_aes256ecb(ptls_cipher_context_t *ctx, int is_enc, const void *k } ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { - "AES256-ECB", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + "AES256-ECB", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), setup_aes256ecb}; /* From e6a01a86e6569485a151a2ab72ffd205955bb8f2 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 15:19:26 +0900 Subject: [PATCH 102/151] update the hidden chacha20 backend --- lib/mbedtls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index ed9374d5a..7344d8f16 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -224,9 +224,9 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { * This is disabled for now, as there seems to be an issue when * setting the 16 bytes long IV that we need. */ -static int setup_crypto_chacha20(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) +static int setup_chacha20(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_STREAM_CIPHER, 16, PSA_KEY_TYPE_CHACHA20); + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_CHACHA20); } ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { From 7ccec73a90881ae8974140726fee53bdcc47cc5b Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 15:22:11 +0900 Subject: [PATCH 103/151] no need to have a wrapper for CTR mode --- lib/mbedtls.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 7344d8f16..f9fe42f70 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -166,11 +166,6 @@ static int ecb_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_byt return 0; } -static int ctr_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, psa_key_type_t key_type) -{ - return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, key_type); -} - static int setup_aes128ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); @@ -198,7 +193,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { static int setup_aes128ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ctr_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_AES); } ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { @@ -211,7 +206,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { static int setup_aes256ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { - return ctr_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_AES); } ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { From f481e291dca5bc8e6eef2db5f016aee628184229 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 15:26:09 +0900 Subject: [PATCH 104/151] remove verbose doc comments --- lib/mbedtls.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/lib/mbedtls.c b/lib/mbedtls.c index f9fe42f70..2186d17c5 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -78,7 +78,7 @@ DEFINE_HASH(sha512, SHA512, PSA_ALG_SHA_512); DEFINE_HASH(sha384, SHA384, PSA_ALG_SHA_384); #endif -/* +/** * Generic implementation of a cipher using the PSA API */ struct st_ptls_mbedtls_cipher_context_t { @@ -175,9 +175,6 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { "AES128-ECB", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), setup_aes128ecb}; -/* - * Implementation of AES256_ECB using the PSA API: - */ static int setup_aes256ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); @@ -187,10 +184,6 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { "AES256-ECB", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), setup_aes256ecb}; -/* - * Implementation of AES128_CTR using the PSA API: - */ - static int setup_aes128ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_AES); @@ -200,10 +193,6 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { "AES128-CTR", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 16 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), setup_aes128ctr}; -/* - * Implementation of AES128_CTR using the PSA API: - */ - static int setup_aes256ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_AES); @@ -214,11 +203,8 @@ ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { setup_aes256ctr}; #if 0 -/* -* Implementation of CHACHA20 using the PSA API. -* This is disabled for now, as there seems to be an issue when -* setting the 16 bytes long IV that we need. -*/ +/* CHACHA20 backend using PSA API is disabled for now, as there seems to be an issue when setting the 16 bytes long IV that we + * need. */ static int setup_chacha20(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) { return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_CHACHA20); @@ -229,9 +215,7 @@ ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { setup_chacha20}; #else /* Implementation of ChaCha20 using the low level ChaCha20 API. - * TODO: remove this and the reference to chacha20.h as soon as - * the IV bug in the generic implementation is fixed. - */ + * TODO: remove this and the reference to chacha20.h as soon as the IV bug in the generic implementation is fixed. */ struct st_ptls_mbedtls_chacha20_context_t { ptls_cipher_context_t super; mbedtls_chacha20_context mctx; @@ -621,8 +605,6 @@ static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec return ret; } -/* Instantiation of the generic key exchange API with secp256r1 - */ static int secp256r1_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { return key_exchange_create(algo, ctx, &secp256r1_params); @@ -637,8 +619,6 @@ static int secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t *alg ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = { .id = PTLS_GROUP_SECP256R1, .name = PTLS_GROUP_NAME_SECP256R1, .create = secp256r1_create, .exchange = secp256r1_exchange}; -/* Instantiation of the generic key exchange API with x25519 - */ static int x25519_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) { return key_exchange_create(algo, ctx, &x25519_params); From 72da59db136370a7c73bbf0543c34ae7dbbfe4ef Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 16:04:29 +0900 Subject: [PATCH 105/151] [xcode] add files --- picotls.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj index 67ddebfdd..0174a7b1c 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 = ""; }; + 087F1A732B034AEB00E81AC1 /* FindMbedTLS.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = FindMbedTLS.cmake; sourceTree = ""; }; 0883D32A2AF601A700B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = ""; }; 0883D32B2AF601B900B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = ""; }; 0883D32C2AF601CB00B711CC /* mbedtls.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mbedtls.h; sourceTree = ""; }; @@ -532,6 +533,7 @@ E95EBCC9227E9FF30022C32D /* cmake */ = { isa = PBXGroup; children = ( + 087F1A732B034AEB00E81AC1 /* FindMbedTLS.cmake */, 08A835EB2996971300D872CE /* boringssl-adjust.cmake */, E95EBCCA227EA0180022C32D /* dtrace-utils.cmake */, ); From 7e7d39ba516ec081e6386391faada730a9776b17 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 16:06:02 +0900 Subject: [PATCH 106/151] use standard names (e.g., _ROOT_DIR), and UNIX-style search paths (/usr/local, lib) --- CMakeLists.txt | 29 +++++++++---------- cmake/FindMbedTLS.cmake | 64 +++++++++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f1f2f736f..86331a851 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ ENDIF () FIND_PACKAGE(PkgConfig REQUIRED) INCLUDE(cmake/dtrace-utils.cmake) INCLUDE(cmake/boringssl-adjust.cmake) -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") CHECK_DTRACE(${PROJECT_SOURCE_DIR}/picotls-probes.d) IF ((CMAKE_SIZEOF_VOID_P EQUAL 8) AND @@ -204,23 +204,22 @@ ENDIF () IF (WITH_MBEDTLS) FIND_PACKAGE(MbedTLS) - # IF (MbedTLS_FOUND) - message(STATUS "mbedtls/include: ${MBEDTLS_INCLUDE_DIRS}") - message(STATUS "mbedtls libraries: ${MBEDTLS_LIBRARIES}") - INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) - ADD_LIBRARY(picotls-mbedtls lib/mbedtls.c) - ADD_EXECUTABLE(test-mbedtls.t + IF (NOT MbedTLS_FOUND) + MESSAGE(FATAL_ERROR "-DWITH_MBEDTLS set but mbedtls not found") + ENDIF () + message(STATUS "mbedtls/include: ${MBEDTLS_INCLUDE_DIRS}") + message(STATUS "mbedtls libraries: ${MBEDTLS_LIBRARIES}") + INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) + ADD_LIBRARY(picotls-mbedtls lib/mbedtls.c) + ADD_EXECUTABLE(test-mbedtls.t deps/picotest/picotest.c ${CORE_TEST_FILES} t/mbedtls.c) - TARGET_LINK_LIBRARIES(test-mbedtls.t - picotls-minicrypto picotls-mbedtls - ${MBEDTLS_LIBRARIES}) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPTLS_HAVE_MBEDTLS=1") - LIST(APPEND PTLSBENCH_LIBS picotls-mbedtls ${MBEDTLS_LIBRARIES}) - #ELSE () - # MESSAGE (FATAL_ERROR "MbedTLS not found") - #ENDIF() + TARGET_LINK_LIBRARIES(test-mbedtls.t + picotls-minicrypto picotls-mbedtls + ${MBEDTLS_LIBRARIES}) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPTLS_HAVE_MBEDTLS=1") + LIST(APPEND PTLSBENCH_LIBS picotls-mbedtls ${MBEDTLS_LIBRARIES}) ENDIF () ADD_EXECUTABLE(ptlsbench t/ptlsbench.c) diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake index e71403ea0..48185f12a 100644 --- a/cmake/FindMbedTLS.cmake +++ b/cmake/FindMbedTLS.cmake @@ -1,32 +1,48 @@ -# - Try to find MbedTLS -# set(MBEDTLS_LIBRARY mbedtls) -# set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_SOURCE_DIR}/include) -find_path(MBEDTLS_INCLUDE_DIRS - NAMES mbedtls/build_info.h psa/crypto.h - HINTS ${MBEDTLS_PREFIX}/include/ - ${CMAKE_SOURCE_DIR}/../mbedtls/include/ - ${CMAKE_BINARY_DIR}/../mbedtls/include/ - ../mbedtls/include/ ) +# Try to find MbedTLS; recognized hints are: +# * MBEDTLS_ROOT_DIR +# * MBEDTLS_LIBDIR +# Upon return, +# * MBEDTLS_INCLUDE_DIRS +# * MBEDTLS_LIBRARIES +# will be set. +# Users may supply MBEDTLS_INCLUDE_DIRS or MBEDTLS_LIBRARIES directly. +INCLUDE(FindPackageHandleStandardArgs) +# setup default vars for the hints +IF (NOT DEFINED MBEDTLS_ROOT_DIR) + SET(MBEDTLS_ROOT_DIR "/usr/local" "/usr") +ENDIF () +IF (NOT DEFINED MBEDTLS_LIBDIR) + SET(MBEDTLS_LIBDIR) + FOREACH (item IN LISTS MBEDTLS_ROOT_DIR) + LIST(APPEND MBEDTLS_LIBDIR "${item}/lib" "${item}/build/library") + ENDFOREACH () +ENDIF () -set(MBEDTLS_HINTS ${MBEDTLS_PREFIX}/build/library - ${CMAKE_BINARY_DIR}/../mbedtls/build/library - ../mbedtls/build/library ../mbedtls/library) +# find include directory +IF (NOT DEFINED MBEDTLS_INCLUDE_DIRS) + SET(HINTS) + FOREACH (item IN LISTS MBEDTLS_ROOT_DIR) + LIST(APPEND HINTS "${item}/include") + ENDFOREACH () + FIND_PATH(MBEDTLS_INCLUDE_DIRS + NAMES mbedtls/build_info.h psa/crypto.h + HINTS $HINTS) +ENDIF () -find_library(MBEDTLS_LIBRARY mbedtls HINTS ${MBEDTLS_HINTS}) -find_library(MBEDTLS_CRYPTO mbedcrypto HINTS ${MBEDTLS_HINTS}) -find_library(MBEDTLS_X509 mbedx509 HINTS ${MBEDTLS_HINTS}) -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set PTLS_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args(MbedTLS REQUIRED_VARS +# find libraries +FIND_LIBRARY(MBEDTLS_LIBRARY mbedtls HINTS $MBEDTLS_LIBDIR) +FIND_LIBRARY(MBEDTLS_CRYPTO mbedcrypto HINTS $MBEDTLS_LIBDIR) +FIND_LIBRARY(MBEDTLS_X509 mbedx509 HINTS $MBEDTLS_LIBDIR) + +# setup +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MbedTLS REQUIRED_VARS MBEDTLS_LIBRARY MBEDTLS_CRYPTO MBEDTLS_X509 MBEDTLS_INCLUDE_DIRS) - -if (MbedTLS_FOUND) - set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDTLS_CRYPTO} ${MBEDTLS_X509}) - mark_as_advanced(MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) -endif () \ No newline at end of file +IF (MbedTLS_FOUND) + SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDTLS_CRYPTO} ${MBEDTLS_X509}) + MARK_AS_ADVANCED(MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) +ENDIF () From cdc446219ab9fbe98c9b613bede1028d9a1f7366 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 16:13:49 +0900 Subject: [PATCH 107/151] sha384 might not be available --- include/picotls/mbedtls.h | 2 ++ lib/mbedtls.c | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index 538a2508f..feef4951e 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -49,7 +49,9 @@ extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; extern ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256; +#if defined(MBEDTLS_SHA384_C) extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; +#endif extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; extern ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[]; diff --git a/lib/mbedtls.c b/lib/mbedtls.c index 2186d17c5..86fa7b017 100644 --- a/lib/mbedtls.c +++ b/lib/mbedtls.c @@ -425,10 +425,12 @@ ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = {"AES256-GCM", sizeof(struct ptls_mbedtls_aead_context_t), aead_setup_aes256gcm}; +#if defined(MBEDTLS_SHA384_C) ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = {.id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, .name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384, .aead = &ptls_mbedtls_aes256gcm, .hash = &ptls_mbedtls_sha384}; +#endif static int aead_setup_chacha20poly1305(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) { @@ -454,8 +456,11 @@ ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUI .aead = &ptls_mbedtls_chacha20poly1305, .hash = &ptls_mbedtls_sha256}; -ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[] = {&ptls_mbedtls_aes256gcmsha384, &ptls_mbedtls_aes128gcmsha256, - &ptls_mbedtls_chacha20poly1305sha256, NULL}; +ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[] = { +#if defined(MBEDTLS_SHA384_C) + &ptls_mbedtls_aes256gcmsha384, +#endif + &ptls_mbedtls_aes128gcmsha256, &ptls_mbedtls_chacha20poly1305sha256, NULL}; #define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 From 62236db4d4a7457b1ada377220f45d8d56015a21 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 14 Nov 2023 16:31:12 +0900 Subject: [PATCH 108/151] mbedtls of ubuntu2204 does not have these files, we can remove them and still refer to `MBEDTLS_SHA384_C` at least on homebrew --- include/picotls/mbedtls.h | 3 +-- t/mbedtls.c | 4 ---- t/ptlsbench.c | 2 -- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index feef4951e..b64924694 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -26,8 +26,7 @@ extern "C" { #endif -#include -#include +#include #include "picotls.h" /* before using any of these objects, psa_crypto_init() must be called */ diff --git a/t/mbedtls.c b/t/mbedtls.c index 94cf55cd8..d3651de14 100644 --- a/t/mbedtls.c +++ b/t/mbedtls.c @@ -29,10 +29,6 @@ #include #include #include -#include "mbedtls/mbedtls_config.h" -#include "mbedtls/build_info.h" -#include "psa/crypto.h" -#include "psa/crypto_struct.h" #include "picotls/mbedtls.h" #include "picotls/minicrypto.h" #include "../deps/picotest/picotest.h" diff --git a/t/ptlsbench.c b/t/ptlsbench.c index 9d9b89d8d..b0f525b8f 100644 --- a/t/ptlsbench.c +++ b/t/ptlsbench.c @@ -60,8 +60,6 @@ #endif #ifdef PTLS_HAVE_MBEDTLS -#include "mbedtls/build_info.h" -#include "psa/crypto.h" #include "picotls/mbedtls.h" #endif From cce8446b0b1c39689eedc9c165c7cbe45e3a7513 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 15 Nov 2023 14:46:59 +0900 Subject: [PATCH 109/151] run mbedtls test as part of the main CI (builds on top of https://github.com/h2o/h2o/pull/3311) --- .github/workflows/ci.yml | 4 ++-- .github/workflows/mbedtls.yml | 44 ----------------------------------- 2 files changed, 2 insertions(+), 46 deletions(-) delete mode 100644 .github/workflows/mbedtls.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80b5401a4..12938762e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,8 +19,8 @@ jobs: command: make -f misc/docker-ci.mk CMAKE_ARGS='-DOPENSSL_ROOT_DIR=-DOPENSSL_ROOT_DIR=/opt/openssl-1.1.0 -DWITH_FUSION=OFF' CONTAINER_NAME='h2oserver/h2o-ci:ubuntu1604' - name: "Linux / OpenSSL 1.1.1" command: make -f misc/docker-ci.mk CMAKE_ARGS='-DWITH_AEGIS=1 -DAEGIS_INCLUDE_DIR=/usr/local/include' - - name: "Linux / OpenSSL 3.0" - command: make -f misc/docker-ci.mk CONTAINER_NAME=h2oserver/h2o-ci:ubuntu2204 + - name: "Linux / OpenSSL 3.0 + mbedtls" + command: make -f misc/docker-ci.mk CONTAINER_NAME=h2oserver/h2o-ci:ubuntu2204 CMAKE_ARGS='-DWITH_MBEDTLS=1' - name: "Linux / OpenSSL 1.1.1 + ASan & UBSan" command: make -f misc/docker-ci.mk CMAKE_ARGS='-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS=-fsanitize=address,undefined -DCMAKE_CXX_FLAGS=-fsanitize=address,undefined' CHECK_ENVS='ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1' - name: "Linux / boringssl" diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml deleted file mode 100644 index 93d14de85..000000000 --- a/.github/workflows/mbedtls.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -name: "MbedTLS-test" - -on: [push, pull_request] - -jobs: - mbedtls: - name: MbedTLS-test - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 - submodules: 'recursive' - - - name: Installing MbedTLS - run: | - cd .. - git clone https://github.com/Mbed-TLS/mbedtls - cd mbedtls - echo "cloned mbedtls" - mkdir build - cd build - cmake -S .. . - echo "cmake done" - make - echo "compiled MbedTLS" - pwd - cd ../../picotls - - - name: Compile picotls - run: | - echo "building picotls with MbedTLS" - pwd - cmake "-DWITH_MBEDTLS=ON" . - make - - - name: Run test - run: | - ./test-mbedtls.t \ No newline at end of file From 3c2af6de8c976958ff40e09dc578f37b46451c7f Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 16 Nov 2023 11:55:00 +0900 Subject: [PATCH 110/151] remove non-standard directory --- cmake/FindMbedTLS.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake index 48185f12a..048a1e9b4 100644 --- a/cmake/FindMbedTLS.cmake +++ b/cmake/FindMbedTLS.cmake @@ -16,7 +16,7 @@ ENDIF () IF (NOT DEFINED MBEDTLS_LIBDIR) SET(MBEDTLS_LIBDIR) FOREACH (item IN LISTS MBEDTLS_ROOT_DIR) - LIST(APPEND MBEDTLS_LIBDIR "${item}/lib" "${item}/build/library") + LIST(APPEND MBEDTLS_LIBDIR "${item}/lib") ENDFOREACH () ENDIF () From 6ea08110dc46a1f990879100adb73cc50e6b4ea2 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Sun, 3 Dec 2023 00:26:18 +0100 Subject: [PATCH 111/151] Replace the TLS_AEGIS_256_SHA384 ciphersuite with TLS_AEGIS_256_SHA512 The latest AEGIS draft, as well as the IANA TLS registry [1] have been updated to replace TLS_AEGIS_256_SHA384 with TLS_AEGIS_256_SHA512. This follows the recommendations from [2] for new cipher suites. [1] https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 [2] https://eprint.iacr.org/2023/913.pdf --- include/picotls.h | 4 ++-- include/picotls/minicrypto.h | 4 ++-- include/picotls/openssl.h | 2 +- lib/cifra.c | 6 +++--- lib/cifra/aes256.c | 5 +++++ lib/cifra/libaegis.c | 8 ++++---- lib/openssl.c | 8 ++++---- t/openssl.c | 3 ++- t/picotls.c | 4 ++-- 9 files changed, 25 insertions(+), 19 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index 3b7a96dec..e0c390811 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -130,8 +130,8 @@ extern "C" { #define PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" #define PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256 0x1303 #define PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" -#define PTLS_CIPHER_SUITE_AEGIS256_SHA384 0x1306 -#define PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384 "TLS_AEGIS_256_SHA384" +#define PTLS_CIPHER_SUITE_AEGIS256_SHA512 0x1306 +#define PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512 "TLS_AEGIS_256_SHA512" #define PTLS_CIPHER_SUITE_AEGIS128L_SHA256 0x1307 #define PTLS_CIPHER_SUITE_NAME_AEGIS128L_SHA256 "TLS_AEGIS_128L_SHA256" diff --git a/include/picotls/minicrypto.h b/include/picotls/minicrypto.h index ca3a31d9d..9e6db1ade 100644 --- a/include/picotls/minicrypto.h +++ b/include/picotls/minicrypto.h @@ -51,11 +51,11 @@ extern ptls_aead_algorithm_t ptls_minicrypto_aes128gcm, ptls_minicrypto_aes256gc extern ptls_aead_algorithm_t ptls_minicrypto_aegis128l; extern ptls_aead_algorithm_t ptls_minicrypto_aegis256; #endif -extern ptls_hash_algorithm_t ptls_minicrypto_sha256, ptls_minicrypto_sha384; +extern ptls_hash_algorithm_t ptls_minicrypto_sha256, ptls_minicrypto_sha384, pts_minicrypto_sha512; extern ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256, ptls_minicrypto_aes256gcmsha384, ptls_minicrypto_chacha20poly1305sha256; #ifdef PTLS_HAVE_AEGIS extern ptls_cipher_suite_t ptls_minicrypto_aegis128lsha256; -extern ptls_cipher_suite_t ptls_minicrypto_aegis256sha384; +extern ptls_cipher_suite_t ptls_minicrypto_aegis256sha512; #endif extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[]; extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[]; diff --git a/include/picotls/openssl.h b/include/picotls/openssl.h index 987b9b1f2..de777c8dc 100644 --- a/include/picotls/openssl.h +++ b/include/picotls/openssl.h @@ -98,7 +98,7 @@ extern ptls_cipher_suite_t ptls_openssl_chacha20poly1305sha256; extern ptls_aead_algorithm_t ptls_openssl_aegis128l; extern ptls_aead_algorithm_t ptls_openssl_aegis256; extern ptls_cipher_suite_t ptls_openssl_aegis128lsha256; -extern ptls_cipher_suite_t ptls_openssl_aegis256sha384; +extern ptls_cipher_suite_t ptls_openssl_aegis256sha512; #endif extern ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_rsa_aes128gcmsha256; diff --git a/lib/cifra.c b/lib/cifra.c index d51f2b703..5fe9febab 100644 --- a/lib/cifra.c +++ b/lib/cifra.c @@ -23,7 +23,7 @@ #include "picotls.h" #include "picotls/minicrypto.h" -ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha384 (must be first) +ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha512 and sha384 (must be first) &ptls_minicrypto_aes256gcmsha384, // ciphers used with sha256 @@ -31,9 +31,9 @@ ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha &ptls_minicrypto_chacha20poly1305sha256, NULL}; -ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = {// ciphers used with sha384 (must be first) +ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = {// ciphers used with sha512 and sha384 (must be first) #ifdef PTLS_HAVE_AEGIS - &ptls_minicrypto_aegis256sha384, + &ptls_minicrypto_aegis256sha512, #endif &ptls_minicrypto_aes256gcmsha384, diff --git a/lib/cifra/aes256.c b/lib/cifra/aes256.c index d4cefa9e9..e074dea8f 100644 --- a/lib/cifra/aes256.c +++ b/lib/cifra/aes256.c @@ -41,6 +41,11 @@ ptls_define_hash(sha384, cf_sha512_context, cf_sha384_init, cf_sha384_update, cf ptls_hash_algorithm_t ptls_minicrypto_sha384 = {"sha384", PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, sha384_create, PTLS_ZERO_DIGEST_SHA384}; +ptls_define_hash(sha512, cf_sha512_context, cf_sha512_init, cf_sha512_update, cf_sha512_digest_final); + +ptls_hash_algorithm_t ptls_minicrypto_sha512 = {"sha512", PTLS_SHA512_BLOCK_SIZE, PTLS_SHA512_DIGEST_SIZE, sha512_create, + PTLS_ZERO_DIGEST_SHA512}; + ptls_cipher_algorithm_t ptls_minicrypto_aes256ecb = { "AES256-ECB", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct aesecb_context_t), aes256ecb_setup_crypto}; diff --git a/lib/cifra/libaegis.c b/lib/cifra/libaegis.c index 0b4af9349..5771d7915 100644 --- a/lib/cifra/libaegis.c +++ b/lib/cifra/libaegis.c @@ -23,7 +23,7 @@ #include "../libaegis.h" extern ptls_hash_algorithm_t ptls_minicrypto_sha256; -extern ptls_hash_algorithm_t ptls_minicrypto_sha384; +extern ptls_hash_algorithm_t ptls_minicrypto_sha512; ptls_aead_algorithm_t ptls_minicrypto_aegis128l = {"AEGIS-128L", PTLS_AEGIS128L_CONFIDENTIALITY_LIMIT, @@ -56,7 +56,7 @@ ptls_aead_algorithm_t ptls_minicrypto_aegis256 = {"AEGIS-256", 0, sizeof(struct aegis256_context_t), aegis256_setup_crypto}; -ptls_cipher_suite_t ptls_minicrypto_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384, - .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384, +ptls_cipher_suite_t ptls_minicrypto_aegis256sha512 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA512, + .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512, .aead = &ptls_minicrypto_aegis256, - .hash = &ptls_minicrypto_sha384}; + .hash = &ptls_minicrypto_sha512}; diff --git a/lib/openssl.c b/lib/openssl.c index a6abafe51..70a3e7e9a 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -2220,10 +2220,10 @@ ptls_aead_algorithm_t ptls_openssl_aegis256 = { .context_size = sizeof(struct aegis256_context_t), .setup_crypto = aegis256_setup_crypto, }; -ptls_cipher_suite_t ptls_openssl_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384, - .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384, +ptls_cipher_suite_t ptls_openssl_aegis256sha512 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA512, + .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512, .aead = &ptls_openssl_aegis256, - .hash = &ptls_openssl_sha384}; + .hash = &ptls_openssl_sha512}; #endif @@ -2240,7 +2240,7 @@ ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = {// ciphers used with sha384 ptls_cipher_suite_t *ptls_openssl_cipher_suites_all[] = {// ciphers used with sha384 (must be first) #if PTLS_HAVE_AEGIS - &ptls_openssl_aegis256sha384, + &ptls_openssl_aegis256sha512, #endif &ptls_openssl_aes256gcmsha384, diff --git a/t/openssl.c b/t/openssl.c index b3188ff0a..d48744522 100644 --- a/t/openssl.c +++ b/t/openssl.c @@ -564,7 +564,8 @@ int main(int argc, char **argv) .sign_certificate = &openssl_sign_certificate.super}; ptls_context_t openssl_ctx_sha256only = openssl_ctx; while (openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size != 32) { - assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */ + assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 64 || /* sha512 */ + openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */ ++openssl_ctx_sha256only.cipher_suites; } assert(openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size == 32); /* sha256 */ diff --git a/t/picotls.c b/t/picotls.c index 80c8543f5..c82cc414a 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -506,8 +506,8 @@ static void test_aegis128l(void) static void test_aegis256(void) { - ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AEGIS256_SHA384), - *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AEGIS256_SHA384); + ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AEGIS256_SHA512), + *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AEGIS256_SHA512); if (cs != NULL && cs_peer != NULL) { test_ciphersuite(cs, cs_peer); From 816653bd13f7cd5060e8b8c1e3b5c44cf5511f51 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Sun, 3 Dec 2023 12:42:13 -0800 Subject: [PATCH 112/151] Align 2023-12-03 (#11) * Incorporate mbedtls in cmake * include find mbedtls * Add cmake module path * Add find package * Update MbedTLS find * Add missing endif * Check mbedtls found condition * Struggling with Found condition. * Remove error condition for debug * update mbedtls test * fix typo * Add github action for mbedtls * Debugging github action. * Decomposing the build steps * More debugging of github action * Build mbedtls parallel to picotls * Add sha512 and sha384 * Update sha384 definitions and test * Add aes256gcm * Add chachapoly * Add test definition. * Fix copy paste errors * Another typo to fix * Fix declarations * use chacha20 test * Fix chacha20 declaration * One last typo, hopefully * That's for coding when half asleep * Fix initialization of chacha20-ctr * Add mbedtls to ptlsbench * Fix debug message * Condition fusion to PTLS_HAVE_FUSION * Declare cipher suites * Add support for MbedTLS random * [minicrypto] x25519 key derivation must fail when output is all-zero * use high level PSA API * msvc compatibility * here also * Fix test random * Fix typo * Add code of sec256r1 * [boringssl] check x25519 bad key * clear secret * use macro to avoid compile errors * Simplify aead setup * Add x25519 * Add test of mbedtls key exchanges * Fix reference to test_key_exchange * [evp_keyex_init] keep refcount unchanged when the function fails * add the failing case * extensions block is optional in TLS/1.2 also * even though we do not test what is recorded, clear it otherwise tests that follow fail * [fusion] unify detection scheme to the best one that we have (which we have had in h2o) * maybe `_mm_insert_epi64` is unavailable on i386? * clang-format * rename files following the convention that backends use just the backend name * `()` in a prototype means any number of args, no zero * ensure that MBEDTLS_SHA384_C is detected regardless of include order * API doc goes into .h * add capability to define custom clone functions for hash contexts * [xcode] add files * rename (amends 08e5319) * these files are included by `crypto.h` * when building picotls, picotls is not part of the system * when building picotls, picotls is not part of the system, whereas mbedtls is * define hash implementations using `ptls_define_hash` * mbedtls is dependency * it is our convention to let the user initialize the crypto backends (see openssl) * PRNG might fail too * reduce state of symmentric ciphers; no need to set key for every IV * engines can be tested using `test_picotls` * report error in detail * have ones own * amend 2106299 * `ptls_cipher_init` is not called in ECB mode * key_schedule_new might fail due to malloc failing * limit scope of `psa_key_attributes_t` * move useful comments to `.h`, as they are not specific to the mbedtls backend * simply AEAD code by only supporting the mandatory operation types * update test code to not rely on init-update-final cycle that is now optional (see doc-comment of ptls_aead_context_t) * fail the same way * expand doc-comment in picotls.h instead * reduce state, release memory regardless of errors * add missing `static` * no need to have prefix for static functions * consolidate duplicated constants into `const struct` * reduce state * ... and we find a bug * update the hidden chacha20 backend * no need to have a wrapper for CTR mode * remove verbose doc comments * [xcode] add files * use standard names (e.g., _ROOT_DIR), and UNIX-style search paths (/usr/local, lib) * sha384 might not be available * mbedtls of ubuntu2204 does not have these files, we can remove them and still refer to `MBEDTLS_SHA384_C` at least on homebrew * run mbedtls test as part of the main CI (builds on top of https://github.com/h2o/h2o/pull/3311) * remove non-standard directory --------- Co-authored-by: Christian Huitema Co-authored-by: Kazuho Oku --- .github/workflows/ci.yml | 4 +- CMakeLists.txt | 35 +- cmake/FindMbedTLS.cmake | 48 +++ cmake/fusion.cmake | 30 ++ include/picotls.h | 97 ++++- include/picotls/mbedtls.h | 66 +++ lib/cifra/x25519.c | 11 +- lib/mbedtls.c | 641 ++++++++++++++++++++++++++++++ lib/openssl.c | 26 +- lib/picotls.c | 18 +- picotls.xcodeproj/project.pbxproj | 20 +- t/mbedtls.c | 156 ++++++++ t/picotls.c | 41 +- t/ptlsbench.c | 30 +- 14 files changed, 1167 insertions(+), 56 deletions(-) create mode 100644 cmake/FindMbedTLS.cmake create mode 100644 cmake/fusion.cmake create mode 100644 include/picotls/mbedtls.h create mode 100644 lib/mbedtls.c create mode 100644 t/mbedtls.c diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80b5401a4..12938762e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,8 +19,8 @@ jobs: command: make -f misc/docker-ci.mk CMAKE_ARGS='-DOPENSSL_ROOT_DIR=-DOPENSSL_ROOT_DIR=/opt/openssl-1.1.0 -DWITH_FUSION=OFF' CONTAINER_NAME='h2oserver/h2o-ci:ubuntu1604' - name: "Linux / OpenSSL 1.1.1" command: make -f misc/docker-ci.mk CMAKE_ARGS='-DWITH_AEGIS=1 -DAEGIS_INCLUDE_DIR=/usr/local/include' - - name: "Linux / OpenSSL 3.0" - command: make -f misc/docker-ci.mk CONTAINER_NAME=h2oserver/h2o-ci:ubuntu2204 + - name: "Linux / OpenSSL 3.0 + mbedtls" + command: make -f misc/docker-ci.mk CONTAINER_NAME=h2oserver/h2o-ci:ubuntu2204 CMAKE_ARGS='-DWITH_MBEDTLS=1' - name: "Linux / OpenSSL 1.1.1 + ASan & UBSan" command: make -f misc/docker-ci.mk CMAKE_ARGS='-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS=-fsanitize=address,undefined -DCMAKE_CXX_FLAGS=-fsanitize=address,undefined' CHECK_ENVS='ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1' - name: "Linux / boringssl" diff --git a/CMakeLists.txt b/CMakeLists.txt index 42692a520..dc146a8f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,18 +10,13 @@ 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) +SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/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}) @@ -32,6 +27,7 @@ IF (WITH_FUSION) MESSAGE(STATUS "Enabling 'fusion' AES-GCM engine") ENDIF () OPTION(WITH_AEGIS "enable AEGIS (requires libaegis)" ${WITH_AEGIS}) +OPTION(WITH_MBEDTLS "enable MBEDTLS" ${WITH_MBEDTLS}) SET(CMAKE_C_FLAGS "-std=c99 -Wall -O2 -g ${CC_WARNING_FLAGS} ${CMAKE_C_FLAGS}") INCLUDE_DIRECTORIES( @@ -196,9 +192,30 @@ IF (WITH_FUSION) ENDIF () SET(TEST_EXES ${TEST_EXES} test-fusion.t) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPTLS_HAVE_FUSION=1") LIST(APPEND PTLSBENCH_LIBS picotls-fusion) ENDIF () +IF (WITH_MBEDTLS) + FIND_PACKAGE(MbedTLS) + IF (NOT MbedTLS_FOUND) + MESSAGE(FATAL_ERROR "-DWITH_MBEDTLS set but mbedtls not found") + ENDIF () + message(STATUS "mbedtls/include: ${MBEDTLS_INCLUDE_DIRS}") + message(STATUS "mbedtls libraries: ${MBEDTLS_LIBRARIES}") + INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) + ADD_LIBRARY(picotls-mbedtls lib/mbedtls.c) + ADD_EXECUTABLE(test-mbedtls.t + deps/picotest/picotest.c + ${CORE_TEST_FILES} + t/mbedtls.c) + TARGET_LINK_LIBRARIES(test-mbedtls.t + picotls-minicrypto picotls-mbedtls + ${MBEDTLS_LIBRARIES}) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPTLS_HAVE_MBEDTLS=1") + LIST(APPEND PTLSBENCH_LIBS picotls-mbedtls ${MBEDTLS_LIBRARIES}) +ENDIF () + ADD_EXECUTABLE(ptlsbench t/ptlsbench.c) SET_TARGET_PROPERTIES(ptlsbench PROPERTIES COMPILE_FLAGS "-DPTLS_MEMORY_DEBUG=1") TARGET_LINK_LIBRARIES(ptlsbench ${PTLSBENCH_LIBS}) diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake new file mode 100644 index 000000000..048a1e9b4 --- /dev/null +++ b/cmake/FindMbedTLS.cmake @@ -0,0 +1,48 @@ +# Try to find MbedTLS; recognized hints are: +# * MBEDTLS_ROOT_DIR +# * MBEDTLS_LIBDIR +# Upon return, +# * MBEDTLS_INCLUDE_DIRS +# * MBEDTLS_LIBRARIES +# will be set. +# Users may supply MBEDTLS_INCLUDE_DIRS or MBEDTLS_LIBRARIES directly. + +INCLUDE(FindPackageHandleStandardArgs) + +# setup default vars for the hints +IF (NOT DEFINED MBEDTLS_ROOT_DIR) + SET(MBEDTLS_ROOT_DIR "/usr/local" "/usr") +ENDIF () +IF (NOT DEFINED MBEDTLS_LIBDIR) + SET(MBEDTLS_LIBDIR) + FOREACH (item IN LISTS MBEDTLS_ROOT_DIR) + LIST(APPEND MBEDTLS_LIBDIR "${item}/lib") + ENDFOREACH () +ENDIF () + +# find include directory +IF (NOT DEFINED MBEDTLS_INCLUDE_DIRS) + SET(HINTS) + FOREACH (item IN LISTS MBEDTLS_ROOT_DIR) + LIST(APPEND HINTS "${item}/include") + ENDFOREACH () + FIND_PATH(MBEDTLS_INCLUDE_DIRS + NAMES mbedtls/build_info.h psa/crypto.h + HINTS $HINTS) +ENDIF () + +# find libraries +FIND_LIBRARY(MBEDTLS_LIBRARY mbedtls HINTS $MBEDTLS_LIBDIR) +FIND_LIBRARY(MBEDTLS_CRYPTO mbedcrypto HINTS $MBEDTLS_LIBDIR) +FIND_LIBRARY(MBEDTLS_X509 mbedx509 HINTS $MBEDTLS_LIBDIR) + +# setup +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MbedTLS REQUIRED_VARS + MBEDTLS_LIBRARY + MBEDTLS_CRYPTO + MBEDTLS_X509 + MBEDTLS_INCLUDE_DIRS) +IF (MbedTLS_FOUND) + SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDTLS_CRYPTO} ${MBEDTLS_X509}) + MARK_AS_ADVANCED(MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) +ENDIF () diff --git a/cmake/fusion.cmake b/cmake/fusion.cmake new file mode 100644 index 000000000..2b7ef1c9c --- /dev/null +++ b/cmake/fusion.cmake @@ -0,0 +1,30 @@ +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); + _mm_insert_epi64(_mm_setr_epi32(0, 1, 2, 3), 0, 0); + 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/include/picotls.h b/include/picotls.h index b701e780b..3b7a96dec 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -338,11 +338,14 @@ typedef struct st_ptls_key_exchange_context_t { */ const struct st_ptls_key_exchange_algorithm_t *algo; /** - * the public key + * public key of this context */ ptls_iovec_t pubkey; /** - * If `release` is set, the callee frees resources allocated to the context and set *keyex to NULL + * This function can be used for deriving a shared secret or for destroying the context. + * When `secret` is non-NULL, this callback derives the shared secret using the public key of the context and the peer key being + * given, and sets the value in `secret`. The memory pointed to by `secret->base` must be freed by the caller by calling `free`. + * When `release` is set, the callee frees resources allocated to the context and set *keyex to NULL. */ int (*on_exchange)(struct st_ptls_key_exchange_context_t **keyex, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey); } ptls_key_exchange_context_t; @@ -356,12 +359,14 @@ typedef const struct st_ptls_key_exchange_algorithm_t { */ uint16_t id; /** - * creates a context for asynchronous key exchange. The function is called when ClientHello is generated. The on_exchange + * Creates a context for asynchronous key exchange. The function is called when ClientHello is generated. The on_exchange * callback of the created context is called when the client receives ServerHello. */ int (*create)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx); /** - * implements synchronous key exchange. Called when receiving a ServerHello. + * Implements synchronous key exchange. Called when receiving a ServerHello. + * Given a public key provided by the peer (`peerkey`), this callback returns a empheral public key (`pubkey`) and a secret + * (`secret) `derived from the two public keys. */ int (*exchange)(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey); @@ -398,31 +403,81 @@ typedef const struct st_ptls_cipher_algorithm_t { int (*setup_crypto)(ptls_cipher_context_t *ctx, int is_enc, const void *key); } ptls_cipher_algorithm_t; +/** + * This object specifies symmetric cipher to be calculated alongside the AEAD encryption. + * QUIC stacks can use this object to apply QUIC header protection and AEAD encryption in one shot. + */ typedef struct st_ptls_aead_supplementary_encryption_t { + /** + * Cipher context to be used. + */ ptls_cipher_context_t *ctx; + /** + * Input to the cipher. + * This field may point to the output of AEAD encryption, in which case the input will be read after AEAD encryption is + * complete. + */ const void *input; + /** + * Output. + */ uint8_t output[16]; } ptls_aead_supplementary_encryption_t; /** - * AEAD context. AEAD implementations are allowed to stuff data at the end of the struct. The size of the memory allocated for the - * struct is governed by ptls_aead_algorithm_t::context_size. - * Ciphers for TLS over TCP MUST implement `do_encrypt`, `do_encrypt_v`, `do_decrypt`. `do_encrypt_init`, `~update`, `~final` are - * obsolete, and therefore may not be available. + * AEAD context. + * AEAD implementations are allowed to stuff data at the end of the struct; see `ptls_aead_algorithm_t::setup_crypto`. + * Ciphers for TLS over TCP MUST implement `do_encrypt`, `do_encrypt_v`, `do_decrypt`. + * `do_encrypt_init`, `~update`, `~final` are obsolete, and therefore may not be available. */ typedef struct st_ptls_aead_context_t { + /** + * Points to the algorithm. This field is governed by picotls core; backends must not alter. + */ const struct st_ptls_aead_algorithm_t *algo; - /* field above this line must not be altered by the crypto binding */ + /** + * Mandatory callback that disposes of all the backend-specific data. + */ void (*dispose_crypto)(struct st_ptls_aead_context_t *ctx); + /** + * Mandatory callback that returns the static IV. The size of IV is available as `ptls_aead_algorithm_t::iv_size`. + */ void (*do_get_iv)(struct st_ptls_aead_context_t *ctx, void *iv); + /** + * Mandatory callback that sets the static IV. The size of IV is available as `ptls_aead_algorithm_t::iv_size`. + */ void (*do_set_iv)(struct st_ptls_aead_context_t *ctx, const void *iv); + /** + * Deprecated. + */ void (*do_encrypt_init)(struct st_ptls_aead_context_t *ctx, uint64_t seq, const void *aad, size_t aadlen); + /** + * Deprecated. + */ size_t (*do_encrypt_update)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen); + /** + * Deprecated. + */ size_t (*do_encrypt_final)(struct st_ptls_aead_context_t *ctx, void *output); + /** + * Mandatory callback that does "one-shot" encryption of an AEAD block. + * When `supp` is set to non-NULL, the callback must also encrypt the supplementary block. + * Backends may set this field to `ptls_aead__do_encrypt` that calls `do_encrypt_v` and `ptls_cipher_*` functions for handling + * the supplimentary block. + */ void (*do_encrypt)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq, const void *aad, size_t aadlen, ptls_aead_supplementary_encryption_t *supp); + /** + * Variant of `do_encrypt` that gathers input from multiple blocks. Support for this callback is also mandatory. + * Legacy backends may set this field to `ptls_aead__do_encrypt_v` that calls `do_encrypt_init`, `do_encrypt_update`, + * `do_encrypt_final`. + */ void (*do_encrypt_v)(struct st_ptls_aead_context_t *ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq, const void *aad, size_t aadlen); + /** + * Mandatory callback for decrypting an AEAD block. + * If successful, returns the amount of cleartext bytes being written to output. Otherwise, returns SIZE_MAX. + */ size_t (*do_decrypt)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq, const void *aad, size_t aadlen); } ptls_aead_context_t; @@ -479,12 +534,16 @@ typedef const struct st_ptls_aead_algorithm_t { */ uint8_t align_bits; /** - * size of memory allocated for ptls_aead_context_t. AEAD implementations can set this value to something greater than - * sizeof(ptls_aead_context_t) and stuff additional data at the bottom of the struct. + * size of memory allocated for `ptls_aead_context_t` */ size_t context_size; /** - * callback that sets up the crypto + * Backend callback called to setup `ptls_aead_context_t`. + * Backends are allowed to stuff arbitrary data at the end of `ptls_aead_context_t`; actual size of the memory chunk being + * allocated is that specified by `ptls_aead_algorithm_t::context_size`. When the `setup_crypto` callback is called, all the + * fields outside of `ptls_aead_context_t` will be in undefined state; it is the responsibility of the callback to initialize + * them, as well as the callbacks of `ptls_aead_context_t` that the backend supports. + * A non-zero return value indicates failure, in which case the error will propagate as `ptls_aead_new` returning NULL. */ int (*setup_crypto)(ptls_aead_context_t *ctx, int is_enc, const void *key, const void *iv); } ptls_aead_algorithm_t; @@ -1763,6 +1822,10 @@ char *ptls_jsonescape(char *buf, const char *s, size_t len); * the default get_time callback */ extern ptls_get_time_t ptls_get_time; +/** + * default hash clone function that calls memcpy + */ +static void ptls_hash_clone_memcpy(void *dst, const void *src, size_t size); #if defined(PICOTLS_USE_DTRACE) && PICOTLS_USE_DTRACE /** * @@ -1919,7 +1982,14 @@ inline size_t ptls_aead_decrypt(ptls_aead_context_t *ctx, void *output, const vo return ctx->do_decrypt(ctx, output, input, inlen, seq, aad, aadlen); } +inline void ptls_hash_clone_memcpy(void *dst, const void *src, size_t size) +{ + memcpy(dst, src, size); +} + #define ptls_define_hash(name, ctx_type, init_func, update_func, final_func) \ + ptls_define_hash6(name, ctx_type, init_func, update_func, final_func, ptls_hash_clone_memcpy) +#define ptls_define_hash6(name, ctx_type, init_func, update_func, final_func, clone_func) \ \ struct name##_context_t { \ ptls_hash_context_t super; \ @@ -1962,7 +2032,8 @@ inline size_t ptls_aead_decrypt(ptls_aead_context_t *ctx, void *output, const vo struct name##_context_t *dst, *src = (struct name##_context_t *)_src; \ if ((dst = malloc(sizeof(*dst))) == NULL) \ return NULL; \ - *dst = *src; \ + dst->super = src->super; \ + clone_func(&dst->ctx, &src->ctx, sizeof(dst->ctx)); \ return &dst->super; \ } \ \ diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h new file mode 100644 index 000000000..b64924694 --- /dev/null +++ b/include/picotls/mbedtls.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023, Christian Huitema + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#ifndef picotls_mbedtls_h +#define picotls_mbedtls_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "picotls.h" + +/* before using any of these objects, psa_crypto_init() must be called */ + +extern ptls_hash_algorithm_t ptls_mbedtls_sha256; +extern ptls_hash_algorithm_t ptls_mbedtls_sha512; +#if defined(MBEDTLS_SHA384_C) +extern ptls_hash_algorithm_t ptls_mbedtls_sha384; +#endif + +extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr; +extern ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr; +extern ptls_cipher_algorithm_t ptls_mbedtls_chacha20; + +extern ptls_aead_algorithm_t ptls_mbedtls_aes128gcm; +extern ptls_aead_algorithm_t ptls_mbedtls_aes256gcm; +extern ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305; + +extern ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256; +#if defined(MBEDTLS_SHA384_C) +extern ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384; +#endif +extern ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256; +extern ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[]; + +extern ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1; +extern ptls_key_exchange_algorithm_t ptls_mbedtls_x25519; +extern ptls_key_exchange_algorithm_t *ptls_mbedtls_key_exchanges[]; + +void ptls_mbedtls_random_bytes(void *buf, size_t len); + +#ifdef __cplusplus +} +#endif +#endif /* picotls_mbedtls_h */ diff --git a/lib/cifra/x25519.c b/lib/cifra/x25519.c index 58f464f8c..3697d4ddf 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] = {0}; + 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/lib/mbedtls.c b/lib/mbedtls.c new file mode 100644 index 000000000..86fa7b017 --- /dev/null +++ b/lib/mbedtls.c @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2023, Christian Huitema + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef _WINDOWS +#include "wincompat.h" +#endif + +#include +#include +#include +#include +#include +#include +#include "picotls.h" + +#define PSA_FUNC_FAILED(fn, ret) \ + do { \ + fprintf(stderr, "in %s at line %d, " PTLS_TO_STR(fn) " failed (%d)\n", __FUNCTION__, __LINE__, (int)ret); \ + abort(); \ + } while (0) + +#define CALL_WITH_CHECK(fn, ...) \ + do { \ + psa_status_t ret; \ + if ((ret = fn(__VA_ARGS__)) != PSA_SUCCESS) \ + PSA_FUNC_FAILED(fn, ret); \ + } while (0) + +void ptls_mbedtls_random_bytes(void *buf, size_t len) +{ + CALL_WITH_CHECK(psa_generate_random, buf, len); +} + +#define DEFINE_HASH(name, name_upcase, psa_alg) \ + static void name##_do_init(psa_hash_operation_t *op) \ + { \ + *op = psa_hash_operation_init(); \ + CALL_WITH_CHECK(psa_hash_setup, op, psa_alg); \ + } \ + static void name##_do_update(psa_hash_operation_t *op, const void *src, size_t len) \ + { \ + CALL_WITH_CHECK(psa_hash_update, op, src, len); \ + } \ + static void name##_do_final(psa_hash_operation_t *op, void *md) \ + { \ + size_t unused; \ + CALL_WITH_CHECK(psa_hash_finish, op, md, PTLS_##name_upcase##_DIGEST_SIZE, &unused); \ + } \ + static void name##_do_clone(psa_hash_operation_t *dst, psa_hash_operation_t *src, size_t unused) \ + { \ + CALL_WITH_CHECK(psa_hash_clone, src, dst); \ + } \ + ptls_define_hash6(name, psa_hash_operation_t, name##_do_init, name##_do_update, name##_do_final, name##_do_clone); \ + ptls_hash_algorithm_t ptls_mbedtls_##name = {PTLS_TO_STR(name), PTLS_##name_upcase##_BLOCK_SIZE, \ + PTLS_##name_upcase##_DIGEST_SIZE, name##_create, PTLS_ZERO_DIGEST_##name_upcase}; +DEFINE_HASH(sha256, SHA256, PSA_ALG_SHA_256); +DEFINE_HASH(sha512, SHA512, PSA_ALG_SHA_512); +#if defined(MBEDTLS_SHA384_C) +DEFINE_HASH(sha384, SHA384, PSA_ALG_SHA_384); +#endif + +/** + * Generic implementation of a cipher using the PSA API + */ +struct st_ptls_mbedtls_cipher_context_t { + ptls_cipher_context_t super; + psa_algorithm_t alg; + unsigned is_enc : 1; + unsigned is_op_in_progress : 1; + mbedtls_svc_key_id_t key; + psa_cipher_operation_t op; +}; + +static void cipher_init(ptls_cipher_context_t *_ctx, const void *iv) +{ + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + + if (ctx->is_op_in_progress) { + psa_cipher_abort(&ctx->op); + ctx->is_op_in_progress = 0; + } + + ctx->op = psa_cipher_operation_init(); + if (ctx->is_enc) { + CALL_WITH_CHECK(psa_cipher_encrypt_setup, &ctx->op, ctx->key, ctx->alg); + } else { + CALL_WITH_CHECK(psa_cipher_decrypt_setup, &ctx->op, ctx->key, ctx->alg); + } + ctx->is_op_in_progress = 1; + if (ctx->super.algo->iv_size > 0) + CALL_WITH_CHECK(psa_cipher_set_iv, &ctx->op, iv, ctx->super.algo->iv_size); +} + +static void cipher_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) +{ + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + size_t unused = 0; + + CALL_WITH_CHECK(psa_cipher_update, &ctx->op, input, len, output, len, &unused); +} + +static void cipher_dispose(ptls_cipher_context_t *_ctx) +{ + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + + if (ctx->is_op_in_progress) + psa_cipher_abort(&ctx->op); + psa_destroy_key(ctx->key); +} + +static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg, + psa_key_type_t key_type) +{ + struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx; + + { /* import key or fail immediately */ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_usage_flags(&attributes, is_enc ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, key_type); + psa_set_key_bits(&attributes, ctx->super.algo->key_size * 8); + if (psa_import_key(&attributes, key_bytes, ctx->super.algo->key_size, &ctx->key) != PSA_SUCCESS) + return PTLS_ERROR_LIBRARY; + } + + /* init the rest that are guaranteed to succeed */ + ctx->super.do_dispose = cipher_dispose; + ctx->super.do_init = cipher_init; + ctx->super.do_transform = cipher_transform; + ctx->alg = alg; + ctx->is_enc = is_enc; + ctx->is_op_in_progress = 0; + ctx->op = psa_cipher_operation_init(); + + return 0; +} + +static int ecb_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, psa_key_type_t key_type) +{ + int ret; + + if ((ret = cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, key_type)) != 0) + return ret; + /* ECB mode does not necessary call `ptls_cipher_init` */ + cipher_init(ctx, NULL); + + return 0; +} + +static int setup_aes128ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) +{ + return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); +} + +ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = { + "AES128-ECB", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_aes128ecb}; + +static int setup_aes256ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) +{ + return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES); +} + +ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = { + "AES256-ECB", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_aes256ecb}; + +static int setup_aes128ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) +{ + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_AES); +} + +ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = { + "AES128-CTR", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 16 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_aes128ctr}; + +static int setup_aes256ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) +{ + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_AES); +} + +ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = { + "AES128-CTR", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 16 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_aes256ctr}; + +#if 0 +/* CHACHA20 backend using PSA API is disabled for now, as there seems to be an issue when setting the 16 bytes long IV that we + * need. */ +static int setup_chacha20(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes) +{ + return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_CHACHA20); +} + +ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = { + "CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_cipher_context_t), + setup_chacha20}; +#else +/* Implementation of ChaCha20 using the low level ChaCha20 API. + * TODO: remove this and the reference to chacha20.h as soon as the IV bug in the generic implementation is fixed. */ +struct st_ptls_mbedtls_chacha20_context_t { + ptls_cipher_context_t super; + mbedtls_chacha20_context mctx; +}; + +static void chacha20_init(ptls_cipher_context_t *_ctx, const void *v_iv) +{ + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; + const uint8_t *iv = (const uint8_t *)v_iv; + uint32_t ctr = iv[0] | ((uint32_t)iv[1] << 8) | ((uint32_t)iv[2] << 16) | ((uint32_t)iv[3] << 24); + + int ret = mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t *)(iv + 4), ctr); + if (ret != 0) + PSA_FUNC_FAILED(mbedtls_chacha20_starts, ret); +} + +static void chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len) +{ + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; + + int ret = mbedtls_chacha20_update(&ctx->mctx, len, (const uint8_t *)input, (uint8_t *)output); + if (ret != 0) + PSA_FUNC_FAILED(mbedtls_chacha20_update, ret); +} + +static void chacha20_dispose(ptls_cipher_context_t *_ctx) +{ + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; + + mbedtls_chacha20_free(&ctx->mctx); +} + +static int setup_chacha20(ptls_cipher_context_t *_ctx, int is_enc, const void *key) +{ + struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx; + + mbedtls_chacha20_init(&ctx->mctx); + if (mbedtls_chacha20_setkey(&ctx->mctx, key) != 0) + return PTLS_ERROR_LIBRARY; + + ctx->super.do_dispose = chacha20_dispose; + ctx->super.do_init = chacha20_init; + ctx->super.do_transform = chacha20_transform; + + return 0; +} + +ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = {"CHACHA20", + PTLS_CHACHA20_KEY_SIZE, + 1 /* block size */, + PTLS_CHACHA20_IV_SIZE, + sizeof(struct st_ptls_mbedtls_chacha20_context_t), + setup_chacha20}; +#endif + +struct ptls_mbedtls_aead_context_t { + struct st_ptls_aead_context_t super; + uint8_t static_iv[PTLS_MAX_IV_SIZE]; + psa_algorithm_t alg; + psa_key_id_t key; +}; + +static void aead_dispose_crypto(struct st_ptls_aead_context_t *_ctx) +{ + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; + + psa_destroy_key(ctx->key); +} + +static void aead_get_iv(ptls_aead_context_t *_ctx, void *iv) +{ + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; + + memcpy(iv, ctx->static_iv, ctx->super.algo->iv_size); +} + +static void aead_set_iv(ptls_aead_context_t *_ctx, const void *iv) +{ + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; + + memcpy(ctx->static_iv, iv, ctx->super.algo->iv_size); +} + +static void aead_encrypt_v(struct st_ptls_aead_context_t *_ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq, + const void *aad, size_t aadlen) +{ + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; + psa_aead_operation_t op = psa_aead_operation_init(); + uint8_t *dst = output, iv[PTLS_MAX_IV_SIZE], tag[PSA_AEAD_TAG_MAX_SIZE]; + size_t outlen, taglen; + + /* setup op */ + CALL_WITH_CHECK(psa_aead_encrypt_setup, &op, ctx->key, ctx->alg); + ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); + CALL_WITH_CHECK(psa_aead_set_nonce, &op, iv, ctx->super.algo->iv_size); + CALL_WITH_CHECK(psa_aead_update_ad, &op, aad, aadlen); + + /* encrypt */ + for (size_t i = 0; i < incnt; i++) { + CALL_WITH_CHECK(psa_aead_update, &op, input[i].base, input[i].len, dst, SIZE_MAX, &outlen); + dst += outlen; + } + CALL_WITH_CHECK(psa_aead_finish, &op, dst, SIZE_MAX, &outlen, tag, sizeof(tag), &taglen); + dst += outlen; + memcpy(dst, tag, taglen); + + /* destroy op */ + psa_aead_abort(&op); +} + +static size_t aead_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq, + const void *aad, size_t aadlen) +{ + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; + uint8_t iv[PTLS_MAX_IV_SIZE]; + size_t outlen; + + ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq); + + psa_status_t ret = + psa_aead_decrypt(ctx->key, ctx->alg, iv, ctx->super.algo->iv_size, aad, aadlen, input, inlen, output, inlen, &outlen); + switch (ret) { + case PSA_SUCCESS: + break; + case PSA_ERROR_INVALID_SIGNATURE: + outlen = SIZE_MAX; + break; + default: + PSA_FUNC_FAILED(psa_aead_decrypt, ret); + break; + } + + return outlen; +} + +static int aead_setup(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv, psa_algorithm_t psa_alg, + size_t key_bits, psa_key_type_t key_type) +{ + struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx; + + { /* setup key */ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_usage_flags(&attributes, is_enc ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, psa_alg); + psa_set_key_type(&attributes, key_type); + psa_set_key_bits(&attributes, key_bits); + if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->key) != PSA_SUCCESS) + return PTLS_ERROR_LIBRARY; + } + + /* setup the rest */ + ctx->super.dispose_crypto = aead_dispose_crypto; + ctx->super.do_get_iv = aead_get_iv; + ctx->super.do_set_iv = aead_set_iv; + if (is_enc) { + ctx->super.do_encrypt = ptls_aead__do_encrypt; + ctx->super.do_encrypt_v = aead_encrypt_v; + } else { + ctx->super.do_decrypt = aead_decrypt; + } + memcpy(ctx->static_iv, iv, ctx->super.algo->iv_size); + ctx->alg = psa_alg; + + return 0; +} + +static int aead_setup_aes128gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) +{ + return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 128, PSA_KEY_TYPE_AES); +} + +ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = {"AES128-GCM", + PTLS_AESGCM_CONFIDENTIALITY_LIMIT, + PTLS_AESGCM_INTEGRITY_LIMIT, + &ptls_mbedtls_aes128ctr, + &ptls_mbedtls_aes128ecb, + PTLS_AES128_KEY_SIZE, + PTLS_AESGCM_IV_SIZE, + PTLS_AESGCM_TAG_SIZE, + {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + aead_setup_aes128gcm}; + +ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256 = {.id = PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, + .name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256, + .aead = &ptls_mbedtls_aes128gcm, + .hash = &ptls_mbedtls_sha256}; + +static int aead_setup_aes256gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) +{ + return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 256, PSA_KEY_TYPE_AES); +} + +ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = {"AES256-GCM", + PTLS_AESGCM_CONFIDENTIALITY_LIMIT, + PTLS_AESGCM_INTEGRITY_LIMIT, + &ptls_mbedtls_aes256ctr, + &ptls_mbedtls_aes256ecb, + PTLS_AES256_KEY_SIZE, + PTLS_AESGCM_IV_SIZE, + PTLS_AESGCM_TAG_SIZE, + {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + aead_setup_aes256gcm}; + +#if defined(MBEDTLS_SHA384_C) +ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = {.id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, + .name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384, + .aead = &ptls_mbedtls_aes256gcm, + .hash = &ptls_mbedtls_sha384}; +#endif + +static int aead_setup_chacha20poly1305(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv) +{ + return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_CHACHA20_POLY1305, 256, PSA_KEY_TYPE_CHACHA20); +} + +ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = {"CHACHA20-POLY1305", + PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT, + PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT, + &ptls_mbedtls_chacha20, + NULL, + PTLS_CHACHA20_KEY_SIZE, + PTLS_CHACHA20POLY1305_IV_SIZE, + PTLS_CHACHA20POLY1305_TAG_SIZE, + {PTLS_TLS12_CHACHAPOLY_FIXED_IV_SIZE, PTLS_TLS12_CHACHAPOLY_RECORD_IV_SIZE}, + 0, + 0, + sizeof(struct ptls_mbedtls_aead_context_t), + aead_setup_chacha20poly1305}; + +ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256, + .name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256, + .aead = &ptls_mbedtls_chacha20poly1305, + .hash = &ptls_mbedtls_sha256}; + +ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[] = { +#if defined(MBEDTLS_SHA384_C) + &ptls_mbedtls_aes256gcmsha384, +#endif + &ptls_mbedtls_aes128gcmsha256, &ptls_mbedtls_chacha20poly1305sha256, NULL}; + +#define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129 + +static const struct ptls_mbedtls_key_exchange_params_t { + psa_algorithm_t alg; + psa_ecc_family_t curve; + size_t curve_bits; + size_t secret_size; +} secp256r1_params = {PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32}, + x25519_params = {PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32}; + +struct ptls_mbedtls_key_exchange_context_t { + ptls_key_exchange_context_t super; + const struct ptls_mbedtls_key_exchange_params_t *params; + psa_key_id_t private_key; + uint8_t pubkeybuf[PTLS_MBEDTLS_ECDH_PUBKEY_MAX]; +}; + +/** + * Generates a private key. For now, we only support ECC. + */ +static int generate_private_key(psa_key_id_t *private_key, const struct ptls_mbedtls_key_exchange_params_t *params) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + int ret = 0; + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&attributes, params->alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(params->curve)); + psa_set_key_bits(&attributes, params->curve_bits); + if (psa_generate_key(&attributes, private_key) != 0) { + ret = -1; + } + return ret; +} + +static int key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_keyex, int release, ptls_iovec_t *secret, + ptls_iovec_t peerkey) +{ + struct ptls_mbedtls_key_exchange_context_t *keyex = (struct ptls_mbedtls_key_exchange_context_t *)*_keyex; + int ret = 0; + + if (secret == NULL) + goto Exit; + + /* derive shared secret */ + if ((secret->base = malloc(keyex->params->secret_size)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; + } + if (psa_raw_key_agreement(keyex->params->alg, keyex->private_key, peerkey.base, peerkey.len, secret->base, + keyex->params->secret_size, &secret->len) != 0) { + ret = PTLS_ERROR_LIBRARY; + goto Exit; + } + assert(keyex->params->secret_size == secret->len); + ret = 0; + +Exit: + if (ret != 0 && secret != NULL) { + free(secret->base); + *secret = ptls_iovec_init(NULL, 0); + } + if (release) { + psa_destroy_key(keyex->private_key); + free(keyex); + *_keyex = NULL; + } + return ret; +} + +static int key_exchange_create(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx, + const struct ptls_mbedtls_key_exchange_params_t *params) +{ + struct ptls_mbedtls_key_exchange_context_t *keyex; + + *ctx = NULL; + + /* setup context */ + if ((keyex = malloc(sizeof(*keyex))) == NULL) + return PTLS_ERROR_NO_MEMORY; + *keyex = (struct ptls_mbedtls_key_exchange_context_t){ + .super.algo = algo, + .super.pubkey.base = keyex->pubkeybuf, + .super.on_exchange = key_exchange_on_exchange, + .params = params, + }; + + /* generate private key */ + if (generate_private_key(&keyex->private_key, keyex->params) != 0) { + free(keyex); + return PTLS_ERROR_LIBRARY; + } + { /* export public key */ + psa_status_t ret = + psa_export_public_key(keyex->private_key, keyex->pubkeybuf, sizeof(keyex->pubkeybuf), &keyex->super.pubkey.len); + if (ret != 0) + PSA_FUNC_FAILED(psa_export_public_key, ret); + } + + *ctx = &keyex->super; + return 0; +} + +static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, + ptls_iovec_t peerkey, const struct ptls_mbedtls_key_exchange_params_t *params) +{ + psa_key_id_t private_key; + int ret; + + *pubkey = ptls_iovec_init(NULL, 0); + *secret = ptls_iovec_init(NULL, 0); + + /* generate private key (and return immediately upon failure) */ + if (generate_private_key(&private_key, params) != 0) + return PTLS_ERROR_LIBRARY; + + /* allocate buffers */ + if ((secret->base = malloc(params->secret_size)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; + } + if ((pubkey->base = malloc(PTLS_MBEDTLS_ECDH_PUBKEY_MAX)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; + } + + /* export public key and call key agrement function */ + if (psa_export_public_key(private_key, pubkey->base, PTLS_MBEDTLS_ECDH_PUBKEY_MAX, &pubkey->len) != 0 || + psa_raw_key_agreement(params->alg, private_key, peerkey.base, peerkey.len, secret->base, params->secret_size, + &secret->len) != 0) { + ret = PTLS_ERROR_LIBRARY; + goto Exit; + } + + ret = 0; + +Exit: + if (ret != 0) { + free(pubkey->base); + *pubkey = ptls_iovec_init(NULL, 0); + free(secret->base); + *secret = ptls_iovec_init(NULL, 0); + } + psa_destroy_key(private_key); + + return ret; +} + +static int secp256r1_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) +{ + return key_exchange_create(algo, ctx, &secp256r1_params); +} + +static int secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, + ptls_iovec_t peerkey) +{ + return key_exchange_exchange(algo, pubkey, secret, peerkey, &secp256r1_params); +} + +ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = { + .id = PTLS_GROUP_SECP256R1, .name = PTLS_GROUP_NAME_SECP256R1, .create = secp256r1_create, .exchange = secp256r1_exchange}; + +static int x25519_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx) +{ + return key_exchange_create(algo, ctx, &x25519_params); +} + +static int x25519_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, + ptls_iovec_t peerkey) +{ + return key_exchange_exchange(algo, pubkey, secret, peerkey, &x25519_params); +} + +ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = { + .id = PTLS_GROUP_X25519, .name = PTLS_GROUP_NAME_X25519, .create = x25519_create, .exchange = x25519_exchange}; + +ptls_key_exchange_algorithm_t *ptls_mbedtls_key_exchanges[] = {&ptls_mbedtls_secp256r1, NULL}; diff --git a/lib/openssl.c b/lib/openssl.c index b03533909..a6abafe51 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -525,22 +525,35 @@ 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) { - secret->len = peerkey.len; - if ((secret->base = malloc(secret->len)) == NULL) { + /* allocate memory to return secret */ + if ((secret->base = malloc(X25519_KEY_SIZE)) == NULL) { ret = PTLS_ERROR_NO_MEMORY; goto Exit; } - uint8_t sk_raw[32]; + secret->len = X25519_KEY_SIZE; + /* fetch raw key and derive the secret */ + 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; goto Exit; } + 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[X25519_KEY_SIZE] = {0}; + if (ptls_mem_equal(secret->base, zeros, X25519_KEY_SIZE)) { + ret = PTLS_ERROR_INCOMPATIBLE_KEY; + goto Exit; + } + /* success */ ret = 0; goto Exit; } +#undef X25519_KEY_SIZE #endif if ((evppeer = EVP_PKEY_new()) == NULL) { @@ -595,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; @@ -617,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; } diff --git a/lib/picotls.c b/lib/picotls.c index d03bf408a..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; } @@ -3570,10 +3573,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; } @@ -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; diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj index 6882e1977..053d89efa 100644 --- a/picotls.xcodeproj/project.pbxproj +++ b/picotls.xcodeproj/project.pbxproj @@ -205,6 +205,12 @@ 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 = ""; }; + 087F1A732B034AEB00E81AC1 /* FindMbedTLS.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = FindMbedTLS.cmake; sourceTree = ""; }; + 0883D3272AEF8F2500B711CC /* fusion.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = fusion.cmake; sourceTree = ""; }; + 0883D32A2AF601A700B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = ""; }; + 0883D32B2AF601B900B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = ""; }; + 0883D32C2AF601CB00B711CC /* mbedtls.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mbedtls.h; sourceTree = ""; }; + 0883D32D2AF6020300B711CC /* ptlsbench.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ptlsbench.c; 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; }; @@ -402,7 +408,6 @@ 106530BD1D998624005B2C60 /* lib */, E95EBCC2227E82BA0022C32D /* misc */, E95EBCC0227B71170022C32D /* picotls-probes.d */, - E992F79920E99A080008154D /* src */, 106530C41D9B1A0E005B2C60 /* t */, 106530B31D9985E0005B2C60 /* Products */, E973651D246E37300039AA49 /* Frameworks */, @@ -443,6 +448,7 @@ E97577022212405D00D1EF74 /* ffx.c */, E9B43DBF24619D1700824E51 /* fusion.c */, 08F0FDF52910F67A00EE657D /* hpke.c */, + 0883D32B2AF601B900B711CC /* mbedtls.c */, E949EF272073629300511ECA /* minicrypto-pem.c */, 106530C21D9B004B005B2C60 /* openssl.c */, E99B75DF1F5CDDB500CF503E /* pembase64.c */, @@ -461,9 +467,11 @@ 08B3298229419DFC009D6766 /* ech-live.t */, E9B43DE224619D7E00824E51 /* fusion.c */, 081F00C92918823200534A86 /* hpke.c */, + 0883D32A2AF601A700B711CC /* mbedtls.c */, 1059003D1DC8D4E300FB4085 /* minicrypto.c */, 106530C51D9B1A98005B2C60 /* openssl.c */, 106530E91D9B7C13005B2C60 /* picotls.c */, + 0883D32D2AF6020300B711CC /* ptlsbench.c */, 106530E61D9B7AF6005B2C60 /* test.h */, E9E3849C1F0748DD00D50990 /* util.h */, ); @@ -496,6 +504,7 @@ E9E4B1292180514000514B47 /* certificate_compression.h */, E97577002212405300D1EF74 /* ffx.h */, E9B43DE62461A06800824E51 /* fusion.h */, + 0883D32C2AF601CB00B711CC /* mbedtls.h */, 1059004F1DC8D64E00FB4085 /* minicrypto.h */, 106530ED1D9CEFF7005B2C60 /* openssl.h */, 081F00CD291A358800534A86 /* pembase64.h */, @@ -527,6 +536,8 @@ children = ( 08A835EB2996971300D872CE /* boringssl-adjust.cmake */, E95EBCCA227EA0180022C32D /* dtrace-utils.cmake */, + 087F1A732B034AEB00E81AC1 /* FindMbedTLS.cmake */, + 0883D3272AEF8F2500B711CC /* fusion.cmake */, ); path = cmake; sourceTree = ""; @@ -538,13 +549,6 @@ name = Frameworks; sourceTree = ""; }; - E992F79920E99A080008154D /* src */ = { - isa = PBXGroup; - children = ( - ); - path = src; - sourceTree = ""; - }; E9F20BDF22E34B210018D260 /* cifra */ = { isa = PBXGroup; children = ( diff --git a/t/mbedtls.c b/t/mbedtls.c new file mode 100644 index 000000000..d3651de14 --- /dev/null +++ b/t/mbedtls.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2023, Christian Huitema + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef _WINDOWS +#include "wincompat.h" +#endif + +#include +#include +#include +#include +#include +#include "picotls/mbedtls.h" +#include "picotls/minicrypto.h" +#include "../deps/picotest/picotest.h" +#include "test.h" + +static int random_trial() +{ + /* The random test is just trying to check that we call the API properly. + * This is done by getting a vector of 1021 bytes, computing the sum of + * all values, and comparing to theoretical min and max, + * computed as average +- 8*standard deviation for sum of 1021 terms. + * 8 random deviations results in an extremely low probability of random + * failure. + * Note that this does not actually test the random generator. + */ + + uint8_t buf[1021]; + uint64_t sum = 0; + const uint64_t max_sum_1021 = 149505; + const uint64_t min_sum_1021 = 110849; + int ret = 0; + + ptls_mbedtls_random_bytes(buf, sizeof(buf)); + for (size_t i = 0; i < sizeof(buf); i++) { + sum += buf[i]; + } + if (sum > max_sum_1021 || sum < min_sum_1021) { + ret = -1; + } + + return ret; +} + +static void test_random(void) +{ + if (random_trial() != 0) { + ok(!"fail"); + return; + } + ok(!!"success"); +} + +static void test_secp256r1(void) +{ + test_key_exchange(&ptls_mbedtls_secp256r1, &ptls_minicrypto_secp256r1); + test_key_exchange(&ptls_minicrypto_secp256r1, &ptls_mbedtls_secp256r1); +} + +static void test_x25519(void) +{ + test_key_exchange(&ptls_mbedtls_x25519, &ptls_minicrypto_x25519); + test_key_exchange(&ptls_minicrypto_x25519, &ptls_mbedtls_x25519); +} + +static void test_key_exchanges(void) +{ + subtest("secp256r1", test_secp256r1); + subtest("x25519", test_x25519); +} + +DEFINE_FFX_AES128_ALGORITHMS(mbedtls); +DEFINE_FFX_CHACHA20_ALGORITHMS(mbedtls); + +int main(int argc, char **argv) +{ + /* Initialize the PSA crypto library. */ + if (psa_crypto_init() != PSA_SUCCESS) { + note("psa_crypto_init fails."); + return done_testing(); + } + + /* Test of the port of the mbedtls random generator */ + subtest("random", test_random); + subtest("key_exchanges", test_key_exchanges); + + ADD_FFX_AES128_ALGORITHMS(mbedtls); + ADD_FFX_CHACHA20_ALGORITHMS(mbedtls); + + /* minicrypto contexts used as peer for valiation */ + ptls_iovec_t secp256r1_certificate = ptls_iovec_init(SECP256R1_CERTIFICATE, sizeof(SECP256R1_CERTIFICATE) - 1); + ptls_minicrypto_secp256r1sha256_sign_certificate_t minicrypto_sign_certificate; + ptls_minicrypto_init_secp256r1sha256_sign_certificate( + &minicrypto_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1)); + ptls_context_t minicrypto_ctx = {ptls_minicrypto_random_bytes, + &ptls_get_time, + ptls_minicrypto_key_exchanges, + ptls_minicrypto_cipher_suites, + {&secp256r1_certificate, 1}, + {{NULL}}, + NULL, + NULL, + &minicrypto_sign_certificate.super}; + + /* context using mbedtls as backend; minicrypto is used for signing certificate as the mbedtls backend does not (yet) have the + * capability */ + ptls_minicrypto_secp256r1sha256_sign_certificate_t mbedtls_sign_certificate; + ptls_minicrypto_init_secp256r1sha256_sign_certificate( + &mbedtls_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1)); + ptls_context_t mbedtls_ctx = {ptls_mbedtls_random_bytes, + &ptls_get_time, + ptls_mbedtls_key_exchanges, + ptls_mbedtls_cipher_suites, + {&secp256r1_certificate, 1}, + {{NULL}}, + NULL, + NULL, + &mbedtls_sign_certificate.super}; + + ctx = &mbedtls_ctx; + ctx_peer = &mbedtls_ctx; + subtest("selt-test", test_picotls); + + ctx = &mbedtls_ctx; + ctx_peer = &minicrypto_ctx; + subtest("vs. minicrypto", test_picotls); + + ctx = &minicrypto_ctx; + ctx_peer = &mbedtls_ctx; + subtest("minicrypto vs.", test_picotls); + + /* Deinitialize the PSA crypto library. */ + mbedtls_psa_crypto_free(); + + return done_testing(); +} diff --git a/t/picotls.c b/t/picotls.c index ecca51d3c..80c8543f5 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -225,12 +225,8 @@ static void test_ciphersuite(ptls_cipher_suite_t *cs1, ptls_cipher_suite_t *cs2) /* encrypt */ c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL); assert(c != NULL); - ptls_aead_encrypt_init(c, 0, NULL, 0); - enc1len = ptls_aead_encrypt_update(c, enc1, src1, strlen(src1)); - enc1len += ptls_aead_encrypt_final(c, enc1 + enc1len); - ptls_aead_encrypt_init(c, 1, NULL, 0); - enc2len = ptls_aead_encrypt_update(c, enc2, src2, strlen(src2)); - enc2len += ptls_aead_encrypt_final(c, enc2 + enc2len); + enc1len = ptls_aead_encrypt(c, enc1, src1, strlen(src1), 0, NULL, 0); + enc2len = ptls_aead_encrypt(c, enc2, src2, strlen(src2), 1, NULL, 0); ptls_aead_free(c); c = ptls_aead_new(cs2->aead, cs2->hash, 0, traffic_secret, NULL); @@ -275,6 +271,10 @@ static void test_ciphersuite_stream(ptls_cipher_suite_t *cs1, ptls_cipher_suite_ /* encrypt */ c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL); assert(c != NULL); + if (c->do_encrypt_init == NULL) { + note("new ciphers may omit support for init-update-final"); + return; + } ptls_aead_encrypt_init(c, 0, NULL, 0); enclen = 0; for (size_t i = 0; text[i] != NULL; ++i) @@ -311,9 +311,7 @@ static void test_aad_ciphersuite(ptls_cipher_suite_t *cs1, ptls_cipher_suite_t * /* encrypt */ c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL); assert(c != NULL); - ptls_aead_encrypt_init(c, 123, aad, strlen(aad)); - enclen = ptls_aead_encrypt_update(c, enc, src, strlen(src)); - enclen += ptls_aead_encrypt_final(c, enc + enclen); + enclen = ptls_aead_encrypt(c, enc, src, strlen(src), 123, aad, strlen(aad)); ptls_aead_free(c); /* decrypt */ @@ -340,9 +338,7 @@ static void test_aad96_ciphersuite(ptls_cipher_suite_t *cs1, ptls_cipher_suite_t c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL); assert(c != NULL); ptls_aead_xor_iv(c, seq32, sizeof(seq32)); - ptls_aead_encrypt_init(c, 123, aad, strlen(aad)); - enclen = ptls_aead_encrypt_update(c, enc, src, strlen(src)); - enclen += ptls_aead_encrypt_final(c, enc + enclen); + enclen = ptls_aead_encrypt(c, enc, src, strlen(src), 123, aad, strlen(aad)); ptls_aead_free(c); /* decrypt */ @@ -2026,6 +2022,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 +2090,14 @@ 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); + free(legacy_params); + legacy_params = NULL; + tls = ptls_new(ctx, 1); len = sizeof(tls10_with_exts); ret = ptls_handshake(tls, &sendbuf, tls10_with_exts, &len, NULL); @@ -2188,4 +2199,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] = {0}; + ret = server->exchange(server, &server_pubkey, &server_secret, ptls_iovec_init(zeros, sizeof(zeros))); + ok(ret != 0); } diff --git a/t/ptlsbench.c b/t/ptlsbench.c index 1b27607eb..b0f525b8f 100644 --- a/t/ptlsbench.c +++ b/t/ptlsbench.c @@ -36,8 +36,10 @@ #include "picotls/minicrypto.h" #include "picotls/openssl.h" #ifndef _WINDOWS +#ifdef PTLS_HAVE_FUSION #include "picotls/fusion.h" #endif +#endif #include #ifdef _WINDOWS @@ -57,6 +59,10 @@ #endif #endif +#ifdef PTLS_HAVE_MBEDTLS +#include "picotls/mbedtls.h" +#endif + /* Time in microseconds */ static uint64_t bench_time() { @@ -262,14 +268,24 @@ static ptls_bench_entry_t aead_list[] = { {"ptlsbcrypt", "aes256gcm", &ptls_bcrypt_aes256gcm, &ptls_bcrypt_sha384, 1}, #endif #if !defined(_WINDOWS) +#ifdef PTLS_HAVE_FUSION {"fusion", "aes128gcm", &ptls_fusion_aes128gcm, &ptls_minicrypto_sha256, 1}, {"fusion", "aes256gcm", &ptls_fusion_aes256gcm, &ptls_minicrypto_sha384, 1}, #endif +#endif #if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 {"openssl", "chacha20poly1305", &ptls_openssl_chacha20poly1305, &ptls_minicrypto_sha256, 1}, #endif {"openssl", "aes128gcm", &ptls_openssl_aes128gcm, &ptls_minicrypto_sha256, 1}, - {"openssl", "aes256gcm", &ptls_openssl_aes256gcm, &ptls_minicrypto_sha384, 1}}; + {"openssl", "aes256gcm", &ptls_openssl_aes256gcm, &ptls_minicrypto_sha384, 1}, +#ifdef PTLS_HAVE_MBEDTLS + {"mbedtls", "aes128gcm", &ptls_mbedtls_aes128gcm, &ptls_mbedtls_sha256, 1}, +#if defined(MBEDTLS_SHA384_C) + {"mbedtls", "aes256gcm", &ptls_mbedtls_aes256gcm, &ptls_mbedtls_sha384, 1}, +#endif + {"mbedtls", "chacha20poly1305", &ptls_mbedtls_chacha20poly1305, &ptls_mbedtls_sha256, 1}, +#endif +}; static size_t nb_aead_list = sizeof(aead_list) / sizeof(ptls_bench_entry_t); @@ -323,6 +339,13 @@ int main(int argc, char **argv) } #endif +#ifdef PTLS_HAVE_MBEDTLS + if (psa_crypto_init() != PSA_SUCCESS) { + fprintf(stderr, "psa_crypto_init fails.\n"); + exit(-1); + } +#endif + if (argc == 2 && strcmp(argv[1], "-f") == 0) { force_all_tests = 1; } else if (argc > 1) { @@ -346,5 +369,10 @@ int main(int argc, char **argv) printf("Unexpected value of test sum s = %llx\n", (unsigned long long)s); } +#ifdef PTLS_HAVE_MBEDTLS + /* Deinitialize the PSA crypto library. */ + mbedtls_psa_crypto_free(); +#endif + return ret; } From 1aa128cc2b2c22527e650078d4bd036775e609cb Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Sun, 3 Dec 2023 16:43:35 -0800 Subject: [PATCH 113/151] mbed sign certificate and tests --- include/picotls/mbedtls.h | 3 + lib/mbedtls_sign.c | 777 ++++++++++++++++++++++++++++++ t/assets/rsa-pkcs8/key.pem | 16 + t/assets/rsa-pkcs8/keypair.pem | 16 + t/assets/secp256r1-pkcs8/cert.pem | 15 + t/assets/secp256r1-pkcs8/key.pem | 5 + t/assets/secp256r1-pkcs8/pub.pem | 4 + t/mbedtls.c | 180 ++++++- 8 files changed, 999 insertions(+), 17 deletions(-) create mode 100644 lib/mbedtls_sign.c create mode 100644 t/assets/rsa-pkcs8/key.pem create mode 100644 t/assets/rsa-pkcs8/keypair.pem create mode 100644 t/assets/secp256r1-pkcs8/cert.pem create mode 100644 t/assets/secp256r1-pkcs8/key.pem create mode 100644 t/assets/secp256r1-pkcs8/pub.pem diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index b64924694..581c41655 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -60,6 +60,9 @@ extern ptls_key_exchange_algorithm_t *ptls_mbedtls_key_exchanges[]; void ptls_mbedtls_random_bytes(void *buf, size_t len); +int ptls_mbedtls_load_private_key(ptls_context_t* ctx, char const* pem_fname); +void ptls_mbedtls_dispose_sign_certificate(ptls_sign_certificate_t* _self); + #ifdef __cplusplus } #endif diff --git a/lib/mbedtls_sign.c b/lib/mbedtls_sign.c new file mode 100644 index 000000000..1098686f3 --- /dev/null +++ b/lib/mbedtls_sign.c @@ -0,0 +1,777 @@ +/* +* Copyright (c) 2023, Christian Huitema +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifdef _WINDOWS +#include "wincompat.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ptls_mbedtls.h" + +typedef struct st_ptls_mbedtls_signature_scheme_t { + uint16_t scheme_id; + psa_algorithm_t hash_algo; +} ptls_mbedtls_signature_scheme_t; + +typedef struct st_ptls_mbedtls_sign_certificate_t { + ptls_sign_certificate_t super; + mbedtls_svc_key_id_t key_id; + psa_key_attributes_t attributes; + const ptls_mbedtls_signature_scheme_t * schemes; +} ptls_mbedtls_sign_certificate_t; + +static const unsigned char ptls_mbedtls_oid_ec_key[] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 }; +static const unsigned char ptls_mbedtls_oid_rsa_key[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }; +static const unsigned char ptls_mbedtls_oid_ed25519[] = { 0x2b, 0x65, 0x70 }; + +static const ptls_mbedtls_signature_scheme_t rsa_signature_schemes[] = { + {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, PSA_ALG_SHA_256}, + {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, PSA_ALG_SHA_384}, + {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, PSA_ALG_SHA_512}, + {UINT16_MAX, PSA_ALG_NONE}}; +static const ptls_mbedtls_signature_scheme_t secp256r1_signature_schemes[] = { + {PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, PSA_ALG_SHA_256}, {UINT16_MAX, PSA_ALG_NONE}}; +static const ptls_mbedtls_signature_scheme_t secp384r1_signature_schemes[] = { + {PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, PSA_ALG_SHA_384}, {UINT16_MAX, PSA_ALG_NONE}}; +static const ptls_mbedtls_signature_scheme_t secp521r1_signature_schemes[] = { + {PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, PSA_ALG_SHA_512}, {UINT16_MAX, PSA_ALG_NONE}}; +static const ptls_mbedtls_signature_scheme_t ed25519_signature_schemes[] = { + {PTLS_SIGNATURE_ED25519, PSA_ALG_NONE}, {UINT16_MAX, PSA_ALG_NONE}}; + +#if defined(MBEDTLS_PEM_PARSE_C) + +static int ptls_mbedtls_parse_der_length(const unsigned char* pem_buf, size_t pem_len, size_t* px, size_t *pl) +{ + int ret = 0; + size_t x = *px; + size_t l = pem_buf[x++]; + + if (l > 128) { + size_t ll = l & 0x7F; + l = 0; + while (ll > 0 && x + l < pem_len) { + l *= 256; + l += pem_buf[x++]; + ll--; + } + } + + *pl = l; + *px = x; + + return ret; +} + +static int ptls_mbedtls_parse_ecdsa_field(const unsigned char* pem_buf, size_t pem_len, size_t* key_index, size_t* key_length) +{ + int ret = 0; + int param_index_index = -1; + int param_length = 0; + size_t x = 0; + + // const unsigned char head = { 0x30, l-2, 0x02, 0x01, 0x01, 0x04 } + if (pem_len < 16 || + pem_buf[x++] != 0x30 /* type = sequence */) + { + ret = -1; + } + else { + size_t l = 0; + ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l); + + if (x + l != pem_len) { + ret = -1; + } + } + if (ret == 0){ + if (pem_buf[x++] != 0x02 /* type = int */ || + pem_buf[x++] != 0x01 /* length of int = 1 */ || + pem_buf[x++] != 0x01 /* version = 1 */ || + pem_buf[x++] != 0x04 /*octet string */ || + pem_buf[x] + x >= pem_len) { + ret = -1; + } + else { + *key_index = x + 1; + *key_length = pem_buf[x]; + x += 1 + pem_buf[x]; + + if (x < pem_len && pem_buf[x] == 0xa0) { + /* decode the EC parameters, identify the curve */ + x++; + if (x + pem_buf[x] >= pem_len) { + /* EC parameters extend beyond buffer */ + ret = -1; + } + else { + x += pem_buf[x] + 1; + } + } + + if (ret == 0 && x < pem_len) { + /* skip the public key parameter */ + if (pem_buf[x++] != 0xa1 || + x >= pem_len) { + ret = -1; + } + else { + size_t l = 0; + ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l); + x += l; + } + } + + if (x != pem_len) { + ret = -1; + } + } + } + return ret; +} + +/* On input, key_index points at the "key information" in a +* "private key" message. For EDDSA, this contains an +* octet string carrying the key itself. On return, key index +* and key length are updated to point at the key field. +*/ +static int ptls_mbedtls_parse_eddsa_key(const unsigned char* pem_buf, size_t pem_len, + size_t* key_index, size_t* key_length) +{ + int ret = 0; + size_t x = *key_index; + size_t l_key = 0; + + if (*key_length < 2 || pem_buf[x++] != 0x04) { + ret = -1; + } else { + ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_key); + if (x + l_key != *key_index + *key_length) { + ret = -1; + } + else { + *key_index = x; + *key_length = l_key; + } + } + return ret; +} + +/* If using PKCS8 encoding, the "private key" field contains the +* same "ecdsa field" found in PEM "EC PRIVATE KEY" files. We +* use the same parser, but we need to reset indices so they +* reflect the unwrapped key. +*/ +int ptls_mbedtls_parse_ec_private_key(const unsigned char* pem_buf, size_t pem_len, + size_t* key_index, size_t* key_length) +{ + size_t x_offset = 0; + size_t x_len = 0; + int ret = ptls_mbedtls_parse_ecdsa_field(pem_buf + *key_index, *key_length, &x_offset, &x_len); + + if (ret == 0) { + *key_index += x_offset; + *key_length = x_len; + } + return ret; +} + +int test_parse_private_key_field(const unsigned char* pem_buf, size_t pem_len, + size_t* oid_index, size_t *oid_length, + size_t* key_index, size_t* key_length) +{ + int ret = 0; + size_t l_oid = 0; + size_t x_oid = 0; + size_t l_key = 0; + size_t x_key = 0; + + size_t x = 0; + /* const unsigned char head = {0x30, l - 2, 0x02, 0x01, 0x00} */ + if (pem_len < 16 || + pem_buf[x++] != 0x30 /* type = sequence */) + { + ret = -1; + } + else { + size_t l = 0; + ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l); + + if (x + l != pem_len) { + ret = -1; + } + } + if (ret == 0) { + if (pem_buf[x++] != 0x02 /* type = int */ || + pem_buf[x++] != 0x01 /* length of int = 1 */ || + pem_buf[x++] != 0x00 /* version = 0 */ || + pem_buf[x++] != 0x30 /* sequence */){ + ret = -1; + } + else { + /* the sequence contains the OID and optional key attributes, + * which we ignore for now. + */ + size_t l_seq = 0; + size_t x_seq; + ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_seq); + x_seq = x; + if (x + l_seq >= pem_len || + pem_buf[x++] != 0x06) { + ret = -1; + } + else { + l_oid = pem_buf[x++]; + x_oid = x; + if (x + l_oid > x_seq + l_seq) { + ret = -1; + } + else { + x = x_seq + l_seq; + } + } + } + } + if (ret == 0) { + /* At that point the oid has been identified. + * The next parameter is an octet string containing the key info. + */ + size_t l = 0; + if (x + 2 > pem_len || + pem_buf[x++] != 0x04){ + ret = -1; + } + else { + ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_key); + x_key = x; + x += l_key; + if (x > pem_len) { + ret = -1; + } + } + } + *oid_index = x_oid; + *oid_length = l_oid; + *key_index = x_key; + *key_length = l_key; + + return ret; +} + +int ptls_mbedtls_get_der_key(mbedtls_pem_context* pem, + mbedtls_pk_type_t * pk_type, + const unsigned char* key, size_t keylen, + const unsigned char* pwd, size_t pwdlen, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; +#endif + + if (keylen == 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + + mbedtls_pem_init(pem); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } + else { + ret = mbedtls_pem_read_buffer(pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len); + } + + if (ret == 0) { + * pk_type = MBEDTLS_PK_RSA; + return ret; + } + else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { + return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; + } + else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { + return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; + } + else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + return ret; + } +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } + else { + ret = mbedtls_pem_read_buffer(pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len); + } + if (ret == 0) { + * pk_type = MBEDTLS_PK_ECKEY; + return ret; + } + else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { + return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; + } + else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { + return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; + } + else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + return ret; + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } + else { + ret = mbedtls_pem_read_buffer(pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len); + if (ret == 0) { + /* info is unknown */ + return ret; + } + else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + return ret; + } + } + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } + else { + ret = mbedtls_pem_read_buffer(pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len); + } + if (ret == 0) { + /* infor is unknown */ + return ret; + } + else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + return ret; + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; +} +#endif + +const ptls_mbedtls_signature_scheme_t* ptls_mbedtls_select_signature_scheme( + const ptls_mbedtls_signature_scheme_t *available, + const uint16_t *algorithms, size_t num_algorithms) +{ + const ptls_mbedtls_signature_scheme_t* scheme; + /* select the algorithm, driven by server-isde preference of `available` */ + for (scheme = available; scheme->scheme_id != UINT16_MAX; ++scheme) { + for (size_t i = 0; i != num_algorithms; ++i) { + if (algorithms[i] == scheme->scheme_id) { + return scheme; + } + } + } + return NULL; +} + +int ptls_mbedtls_set_available_schemes( + ptls_mbedtls_sign_certificate_t* signer) +{ + int ret = 0; + psa_algorithm_t algo = psa_get_key_algorithm(&signer->attributes); + size_t nb_bits = psa_get_key_bits(&signer->attributes); + + switch (algo) { + case PSA_ALG_RSA_PKCS1V15_SIGN_RAW: + signer->schemes = rsa_signature_schemes; + break; + case PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256): + signer->schemes = secp256r1_signature_schemes; + break; + case PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384): + signer->schemes = secp384r1_signature_schemes; + break; + case PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512): + signer->schemes = secp521r1_signature_schemes; + break; + case PSA_ALG_ECDSA_BASE: + switch (nb_bits) { + case 521: + signer->schemes = secp521r1_signature_schemes; + break; + case 384: + signer->schemes = secp384r1_signature_schemes; + break; + case 256: + signer->schemes = secp256r1_signature_schemes; + break; + default: + signer->schemes = secp256r1_signature_schemes; + ret = -1; + break; + } + break; + case PSA_ALG_ED25519PH: + signer->schemes = ed25519_signature_schemes; + break; + default: + printf("Unknown algo: %x\n", algo); + ret = -1; + } + + return ret; +} + +/* +* Sign a certificate +* - step1, selected a signature algorithm compatible with the public key algorithm +* and with the list specified by the application. +* - step2, compute the hash with the specified algorithm. +* - step3, compute the signature of the hash using psa_sign_hash. +* +* In the case of RSA, we use the algorithm PSA_ALG_RSA_PKCS1V15_SIGN_RAW, which +* pads the hash according to PKCS1V15 before doing the private key operation. +* The implementation of RSA/PKCS1V15 also includes a verification step to protect +* against key attacks through partial faults. +* +* MBEDTLS has a "psa_sign_message" that combines step2 and step3. However, it +* requires specifying an algorithm type that exactly specifies the signature +* algorithm, such as "RSA with SHA384". This is not compatible with the +* "RSA sign raw" algorithm. Instead, we decompose the operation in two steps. +* There is no performance penalty doing so, as "psa_sign_message" is only +* a convenience API. +*/ + +int ptls_mbedtls_sign_certificate(ptls_sign_certificate_t* _self, ptls_t* tls, + ptls_async_job_t** async, uint16_t* selected_algorithm, + ptls_buffer_t* outbuf, ptls_iovec_t input, const uint16_t* algorithms, size_t num_algorithms) +{ + int ret = 0; + ptls_mbedtls_sign_certificate_t* self = (ptls_mbedtls_sign_certificate_t*) + (((unsigned char*)_self) - offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); + /* First, find the set of compatible algorithms */ + const ptls_mbedtls_signature_scheme_t* scheme = + ptls_mbedtls_select_signature_scheme(self->schemes, algorithms, num_algorithms); + + if (scheme == NULL) { + ret = PTLS_ERROR_INCOMPATIBLE_KEY; + } + else { + /* First prepare the hash */ + unsigned char hash_buffer[PTLS_MAX_DIGEST_SIZE]; + unsigned char* hash_value = NULL; + size_t hash_length = 0; + + if (scheme->hash_algo == PSA_ALG_NONE) { + hash_value = input.base; + hash_length = input.len; + } + else { + if (psa_hash_compute(scheme->hash_algo, input.base, input.len, hash_buffer, PTLS_MAX_DIGEST_SIZE, &hash_length) != PSA_SUCCESS) { + ret = PTLS_ERROR_NOT_AVAILABLE; + } + else { + hash_value = hash_buffer; + } + } + if (ret == 0) { + psa_algorithm_t sign_algo = psa_get_key_algorithm(&self->attributes); + size_t nb_bits = psa_get_key_bits(&self->attributes); + size_t nb_bytes = (nb_bits + 7) / 8; + if (nb_bits == 0) { + if (sign_algo == PSA_ALG_RSA_PKCS1V15_SIGN_RAW) { + /* assume at most 4096 bit key */ + nb_bytes = 512; + } + else { + /* Max size assumed, secp521r1 */ + nb_bytes = 124; + } + } else if (sign_algo != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) { + nb_bytes *= 2; + } + if ((ret = ptls_buffer_reserve(outbuf, nb_bytes)) == 0) { + size_t signature_length = 0; + + if (psa_sign_hash(self->key_id, sign_algo, hash_value, hash_length, + outbuf->base + outbuf->off, nb_bytes, &signature_length) != 0) { + ret = PTLS_ERROR_INCOMPATIBLE_KEY; + } + else { + outbuf->off += signature_length; + } + } + } + } + return ret; +} + +void ptls_mbedtls_dispose_sign_certificate(ptls_sign_certificate_t *_self) +{ + if (_self != NULL) { + ptls_mbedtls_sign_certificate_t* self = (ptls_mbedtls_sign_certificate_t*) + (((unsigned char*)_self) - offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); + /* Destroy the key */ + psa_destroy_key(self->key_id); + psa_reset_key_attributes(&self->attributes); + memset(self, 0, sizeof(ptls_mbedtls_sign_certificate_t)); + free(self); + } +} +/* +* An RSa key is encoded in DER as: +* RSAPrivateKey ::= SEQUENCE { +* version INTEGER, -- must be 0 +* modulus INTEGER, -- n +* publicExponent INTEGER, -- e +* privateExponent INTEGER, -- d +* prime1 INTEGER, -- p +* prime2 INTEGER, -- q +* exponent1 INTEGER, -- d mod (p-1) +* exponent2 INTEGER, -- d mod (q-1) +* coefficient INTEGER, -- (inverse of q) mod p +* } +* +* The number of key bits is the size in bits of the integer N. +* We must decode the length in octets of the integer representation, +* then subtract the number of zeros at the beginning of the data. +*/ +int ptls_mbedtls_rsa_get_key_bits(const unsigned char* key_value, size_t key_length, size_t * p_nb_bits) +{ + int ret = 0; + size_t nb_bytes = 0; + size_t nb_bits = 0; + size_t x = 0; + + if (key_length > 16 && key_value[x++] == 0x30) { + /* get the length of the sequence. */ + size_t l = 0; + ret = ptls_mbedtls_parse_der_length(key_value, key_length, &x, &l); + + if (x + l != key_length) { + ret = -1; + } + } + + if (ret == 0 && + key_value[x] == 0x02 && + key_value[x + 1] == 0x01 && + key_value[x + 2] == 0x00 && + key_value[x + 3] == 0x02) { + x += 4; + ret = ptls_mbedtls_parse_der_length(key_value, key_length, &x, &nb_bytes); + } + else { + ret = -1; + } + + if (ret == 0) { + unsigned char v = key_value[x]; + nb_bits = 8 * nb_bytes; + + if (v == 0) { + nb_bits -= 8; + } + else { + while ((v & 0x80) == 0) { + nb_bits--; + v <<= 1; + } + } + } + *p_nb_bits = nb_bits; + return ret; +} + +void ptls_mbedtls_set_rsa_key_attributes(ptls_mbedtls_sign_certificate_t* signer, + const unsigned char * key_value, size_t key_length) +{ + size_t nb_bits = 0; + psa_set_key_usage_flags(&signer->attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&signer->attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW); + psa_set_key_type(&signer->attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + if (ptls_mbedtls_rsa_get_key_bits(key_value, key_length, &nb_bits) == 0) { + psa_set_key_bits(&signer->attributes, nb_bits); + } +} + +int ptls_mbedtls_set_ec_key_attributes(ptls_mbedtls_sign_certificate_t* signer, size_t key_length) +{ + int ret = 0; + + psa_set_key_usage_flags(&signer->attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&signer->attributes, PSA_ALG_ECDSA_BASE); + psa_set_key_type(&signer->attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + if (key_length == 32) { + psa_set_key_algorithm(&signer->attributes, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_bits(&signer->attributes, 256); + } + else if (key_length == 48) { + psa_set_key_algorithm(&signer->attributes, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384)); + psa_set_key_bits(&signer->attributes, 384); + } + else if (key_length == 66) { + psa_set_key_algorithm(&signer->attributes, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512)); + psa_set_key_bits(&signer->attributes, 521); + } + else { + ret = -1; + } + + return ret; +} + + +int ptls_mbedtls_load_private_key(ptls_context_t* ctx, char const* pem_fname) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char* buf; + mbedtls_pem_context pem = { 0 }; + mbedtls_pk_type_t pk_type = 0; + mbedtls_svc_key_id_t key_id = 0; + size_t key_length = 0; + size_t key_index = 0; + ptls_mbedtls_sign_certificate_t* signer = (ptls_mbedtls_sign_certificate_t*)malloc(sizeof(ptls_mbedtls_sign_certificate_t)); + + if (signer == NULL) { + return(PTLS_ERROR_NO_MEMORY); + } + memset(signer, 0, sizeof(ptls_mbedtls_sign_certificate_t)); + signer->attributes = psa_key_attributes_init(); + + if ((ret = mbedtls_pk_load_file(pem_fname, &buf, &n)) != 0) { + if (ret == MBEDTLS_ERR_PK_ALLOC_FAILED) { + return(PTLS_ERROR_NO_MEMORY); + } + else { + return(PTLS_ERROR_NOT_AVAILABLE); + } + } + ret = ptls_mbedtls_get_der_key(&pem, &pk_type, buf, n, NULL, 0, NULL, NULL); + + /* We cannot use the platform API: + mbedtls_zeroize_and_free(buf, n); + so we do our own thing. + */ + memset(buf, 0, n); + free(buf); + + if (ret == 0) { + if (pk_type == MBEDTLS_PK_RSA) { + key_length = pem.private_buflen; + ptls_mbedtls_set_rsa_key_attributes(signer, pem.private_buf, key_length); + } + else if (pk_type == MBEDTLS_PK_ECKEY) { + ret = ptls_mbedtls_parse_ecdsa_field(pem.private_buf, pem.private_buflen, &key_index, &key_length); + if (ret == 0) { + ret = ptls_mbedtls_set_ec_key_attributes(signer, key_length); + } + } + else if (pk_type == MBEDTLS_PK_NONE) { + /* TODO: not clear whether MBDED TLS supports ED25519 yet. Probably not. */ + /* Should have option to encode RSA or ECDSA using PKCS8 */ + size_t oid_index = 0; + size_t oid_length = 0; + + psa_set_key_usage_flags(&signer->attributes, PSA_KEY_USAGE_SIGN_HASH); + ret = test_parse_private_key_field(pem.private_buf, pem.private_buflen, &oid_index, &oid_length, &key_index, &key_length); + if (ret == 0) { + /* need to parse the OID in order to set the parameters */ + + if (oid_length == sizeof(ptls_mbedtls_oid_ec_key) && + memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_ec_key, sizeof(ptls_mbedtls_oid_ec_key)) == 0) { + ret = ptls_mbedtls_parse_ec_private_key(pem.private_buf, pem.private_buflen, &key_index, &key_length); + if (ret == 0) { + ret = ptls_mbedtls_set_ec_key_attributes(signer, key_length); + } + } + else if (oid_length == sizeof(ptls_mbedtls_oid_ed25519) && + memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_ed25519, sizeof(ptls_mbedtls_oid_ed25519)) == 0) { + /* We recognized ED25519 -- PSA_ECC_FAMILY_TWISTED_EDWARDS -- PSA_ALG_ED25519PH */ + psa_set_key_algorithm(&signer->attributes, PSA_ALG_PURE_EDDSA); + psa_set_key_type(&signer->attributes, PSA_ECC_FAMILY_TWISTED_EDWARDS); + ret = ptls_mbedtls_parse_eddsa_key(pem.private_buf, pem.private_buflen, &key_index, &key_length); + psa_set_key_bits(&signer->attributes, 256); + } + else if (oid_length == sizeof(ptls_mbedtls_oid_rsa_key) && + memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_rsa_key, sizeof(ptls_mbedtls_oid_rsa_key)) == 0) { + /* We recognized RSA */ + key_length = pem.private_buflen; + ptls_mbedtls_set_rsa_key_attributes(signer, pem.private_buf, key_length); + } + else { + ret = PTLS_ERROR_NOT_AVAILABLE; + } + } + } + else { + ret = -1; + } + + if (ret == 0) { + /* Now that we have the DER or bytes for the key, try import into PSA */ + psa_status_t status = psa_import_key(&signer->attributes, pem.private_buf + key_index, key_length, &signer->key_id); + + if (status != PSA_SUCCESS) { + ret = -1; + } + else { + ret = ptls_mbedtls_set_available_schemes(signer); + } + } + /* Free the PEM buffer */ + mbedtls_pem_free(&pem); + } + if (ret == 0) { + signer->super.cb = ptls_mbedtls_sign_certificate; + ctx->sign_certificate = &signer->super; + } else { + /* Dispose of what we have allocated. */ + ptls_mbedtls_dispose_sign_certificate(&signer->super); + } + return ret; +} diff --git a/t/assets/rsa-pkcs8/key.pem b/t/assets/rsa-pkcs8/key.pem new file mode 100644 index 000000000..629c2987b --- /dev/null +++ b/t/assets/rsa-pkcs8/key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAL4LUZlRKYdmCqJo +8q8h/Dz8g4pkHRJW1Ll1wB7UgQ4velSSqzFBTgS/yo+vU1L8KkcV4eginJjpf9Wb +1zi7wry0BfpW3t+d6RJx3W8+0wH0ppybbcv07dQMcXI+Rb0yOUFEc9FPDxxkwuPk +P0Md2JNd3e4uM2o2IX5idLtHIXk/AgMBAAECgYEAhTSJzV0GLtFnQs8sy3SWyGh2 +CtqBRgl2sUfHkdSBYOAGbqEfPTb46HtGD9BkJxZ4y7qazYr1GHkSETdac3mn1EaB +5Ga7TX2Tx+sYbsrqju6NHBglbXhCIVqVlrnpC5AIiKxHIP/WZHHW6O+KDpuyA2TI +6HIEMMZwp5eW/LIfQIECQQDt8PwcCeZbbtI/kpsSLl7ycIN23t9/czvcHCX3E6tv +z/XMBP860n6wC4E6EaMrXvcuNp0NWDoVM67Qd4647bE7AkEAzHe63DoQ7cLkRV9I +QHmxOYRqyn2YB7dDlk1a0LF1k5NVV1pTx2weVCx90y25asIykurr3MA+bORH5ocX +o7bXzQJBAMlsoo891jL6qqNEgV+vv5KuqqubWknzC+52KbFyhkNeIa63YDS0cqim +5Jt6yM1zU/5cHzFnyaufF9LEEx77oHcCQQC8bBGM5Q24rYMC0t2YXQyOvpJS7A5v +/diQ59QqwX5icsGQcDMIcYA5fY6uT1KxKSjF7ytQEPD2FCCWNiP4wIR5AkEAvizW +jFdFeuqcpzdfnSW6qXn04Nnf0hYXpnR6bdsvu1PLJ8DjJfN84/XlgkAyOmm85qTd +PoI8/wjI6SA45MkzXg== +-----END PRIVATE KEY----- diff --git a/t/assets/rsa-pkcs8/keypair.pem b/t/assets/rsa-pkcs8/keypair.pem new file mode 100644 index 000000000..629c2987b --- /dev/null +++ b/t/assets/rsa-pkcs8/keypair.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAL4LUZlRKYdmCqJo +8q8h/Dz8g4pkHRJW1Ll1wB7UgQ4velSSqzFBTgS/yo+vU1L8KkcV4eginJjpf9Wb +1zi7wry0BfpW3t+d6RJx3W8+0wH0ppybbcv07dQMcXI+Rb0yOUFEc9FPDxxkwuPk +P0Md2JNd3e4uM2o2IX5idLtHIXk/AgMBAAECgYEAhTSJzV0GLtFnQs8sy3SWyGh2 +CtqBRgl2sUfHkdSBYOAGbqEfPTb46HtGD9BkJxZ4y7qazYr1GHkSETdac3mn1EaB +5Ga7TX2Tx+sYbsrqju6NHBglbXhCIVqVlrnpC5AIiKxHIP/WZHHW6O+KDpuyA2TI +6HIEMMZwp5eW/LIfQIECQQDt8PwcCeZbbtI/kpsSLl7ycIN23t9/czvcHCX3E6tv +z/XMBP860n6wC4E6EaMrXvcuNp0NWDoVM67Qd4647bE7AkEAzHe63DoQ7cLkRV9I +QHmxOYRqyn2YB7dDlk1a0LF1k5NVV1pTx2weVCx90y25asIykurr3MA+bORH5ocX +o7bXzQJBAMlsoo891jL6qqNEgV+vv5KuqqubWknzC+52KbFyhkNeIa63YDS0cqim +5Jt6yM1zU/5cHzFnyaufF9LEEx77oHcCQQC8bBGM5Q24rYMC0t2YXQyOvpJS7A5v +/diQ59QqwX5icsGQcDMIcYA5fY6uT1KxKSjF7ytQEPD2FCCWNiP4wIR5AkEAvizW +jFdFeuqcpzdfnSW6qXn04Nnf0hYXpnR6bdsvu1PLJ8DjJfN84/XlgkAyOmm85qTd +PoI8/wjI6SA45MkzXg== +-----END PRIVATE KEY----- diff --git a/t/assets/secp256r1-pkcs8/cert.pem b/t/assets/secp256r1-pkcs8/cert.pem new file mode 100644 index 000000000..ef2ae2c80 --- /dev/null +++ b/t/assets/secp256r1-pkcs8/cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICYDCCAUigAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9waWNv +dGxzIHRlc3QgY2EwHhcNMTgwMjIzMDUzMTA0WhcNMjgwMjIxMDUzMTA0WjAbMRkw +FwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD +QgAE2silQFS6M9oYqUF/SVPfYOamPbaOUzqf3RkUXqsDz7z7NpgWJI8HKW0V2E8w +6Alk+xT8hnzUBsL9neiZP0iMK6N7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E +HxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFO4whhah +0mmtZOTXd2uy/VxPAaK1MB8GA1UdIwQYMBaAFL95ypeyYHgglqpGV5zfp7Ij9SVj +MA0GCSqGSIb3DQEBCwUAA4IBAQCPrJwBbYGqjK5dtRZ06ujrJluxZtVr1E15DW2H +qba/dC3Bsi5StkvKDQFFOFga0mptIJhaUbBvLD8PEojtfAmldAAhPUvSLVSqU4tk ++R7qpYrnYV5WklI2PqBoWZx9s+hcS3du3ijtGJGpnDnSlsyYBYx03B4SWzi9Vsuj +6OEqWivSMkXBEIUgbGs06maRDi64ZIefB7wjTyOtvonfCphH6WMC00H0LaTO3ePY +QQj+30fA52OOH/BLxa6rwLo4PuOQnAi9dRy5uFRDHZlC4KK3dbsUA3ma9gfYpasr +OnCLd4Vwipg4mzUJ9mJrKUqnp/k73tjIkFfydiojCwFoxpry +-----END CERTIFICATE----- diff --git a/t/assets/secp256r1-pkcs8/key.pem b/t/assets/secp256r1-pkcs8/key.pem new file mode 100644 index 000000000..906aaffa1 --- /dev/null +++ b/t/assets/secp256r1-pkcs8/key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgwXS0+V7+egEOvkro +M7I2E/xl6WWRqDmemoD7q9H/ujqhRANCAATayKVAVLoz2hipQX9JU99g5qY9to5T +Op/dGRReqwPPvPs2mBYkjwcpbRXYTzDoCWT7FPyGfNQGwv2d6Jk/SIwr +-----END PRIVATE KEY----- diff --git a/t/assets/secp256r1-pkcs8/pub.pem b/t/assets/secp256r1-pkcs8/pub.pem new file mode 100644 index 000000000..04029462a --- /dev/null +++ b/t/assets/secp256r1-pkcs8/pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2silQFS6M9oYqUF/SVPfYOamPbaO +Uzqf3RkUXqsDz7z7NpgWJI8HKW0V2E8w6Alk+xT8hnzUBsL9neiZP0iMKw== +-----END PUBLIC KEY----- diff --git a/t/mbedtls.c b/t/mbedtls.c index d3651de14..b9649ff91 100644 --- a/t/mbedtls.c +++ b/t/mbedtls.c @@ -89,6 +89,149 @@ static void test_key_exchanges(void) subtest("x25519", test_x25519); } +/* +Sign certificate has to implement a callback: + +if ((ret = tls->ctx->sign_certificate->cb( +tls->ctx->sign_certificate, tls, tls->is_server ? &tls->server.async_job : NULL, &algo, sendbuf, +ptls_iovec_init(data, datalen), signature_algorithms != NULL ? signature_algorithms->list : NULL, +signature_algorithms != NULL ? signature_algorithms->count : 0)) != 0) { + +or: + +static int sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, ptls_async_job_t **async, uint16_t *selected_algorithm, +ptls_buffer_t *outbuf, ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms) + +The callback "super" type is ptls_sign_certificate_t, defined by the macro: +PTLS_CALLBACK_TYPE(int, sign_certificate, ptls_t *tls, ptls_async_job_t **async, uint16_t *selected_algorithm, +ptls_buffer_t *output, ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms); + +The notation is simple: input buffer and supported algorithms as input, selected algo and output buffer as output. +Output buffer is already partially filled. + +For PSA/MbedTLS, see: +https://mbed-tls.readthedocs.io/en/latest/getting_started/psa/ +Using PSA, Signing a message with RSA provides the following sequence: + +-- Set key attributes -- +psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); +psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW); +psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); +psa_set_key_bits(&attributes, 1024); + +-- Import the key -- +status = psa_import_key(&attributes, key, key_len, &key_id); +if (status != PSA_SUCCESS) { +printf("Failed to import key\n"); +return; +} + +-- Sign message using the key -- +status = psa_sign_hash(key_id, PSA_ALG_RSA_PKCS1V15_SIGN_RAW, +hash, sizeof(hash), +signature, sizeof(signature), +&signature_length); + +TODO: verify that Picotls does compute the hash before calling sign. +TODO: verify that there are "sign raw" implementations for ECDSA, EDDSA + +-- Verify hash: +psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) + +Load a key in memory + +int mbedtls_pk_parse_keyfile(mbedtls_pk_context* ctx, +const char* path, const char* pwd, +int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); + +But before using the psa API, the key must be imported. That means the key has to +be expressed in the proper x509/DER format. + +*/ + +#define ASSET_RSA_KEY "t/assets/rsa/key.pem" +#define ASSET_RSA_PKCS8_KEY "t/assets/rsa-pkcs8/key.pem" +#define ASSET_SECP256R1_KEY "t/assets/secp256r1/key.pem" +#define ASSET_SECP384R1_KEY "t/assets/secp384r1/key.pem" +#define ASSET_SECP521R1_KEY "t/assets/secp521r1/key.pem" +#define ASSET_SECP256R1_PKCS8_KEY "t/assets/secp256r1-pkcs8/key.pem" + +void test_load_one_der_key(char const* path) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char hash[32]; + const unsigned char h0[32] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32 + }; + ptls_context_t ctx = { 0 }; + psa_status_t status = 0; + + ret = ptls_mbedtls_load_private_key(&ctx, path); + if (ret != 0) { + ok(ret == 0, "Cannot create sign_certificate from: %s\n", path); + } + else if (ctx.sign_certificate == NULL) { + printf("Sign_certificate not set in ptls context for: %s\n", path); + ret = -1; + } + else { + /* Try to sign something */ + int ret; + ptls_mbedtls_sign_certificate_t* signer = (ptls_mbedtls_sign_certificate_t*) + (((unsigned char*)ctx.sign_certificate) - offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); + /* get the key algorithm */ + psa_algorithm_t algo = psa_get_key_algorithm(&signer->attributes); + ptls_buffer_t outbuf; + uint8_t outbuf_smallbuf[256]; + ptls_iovec_t input = { hash, sizeof(hash) }; + uint16_t selected_algorithm = 0; + int num_algorithms = 0; + uint16_t algorithms[16]; + memcpy(hash, h0, 32); + while (signer->schemes[num_algorithms].scheme_id != UINT16_MAX && num_algorithms < 16) { + algorithms[num_algorithms++] = signer->schemes[num_algorithms].scheme_id; + } + + ptls_buffer_init(&outbuf, outbuf_smallbuf, sizeof(outbuf_smallbuf)); + + ret = ptls_mbedtls_sign_certificate(ctx.sign_certificate, NULL, NULL, &selected_algorithm, + &outbuf, input, algorithms, num_algorithms); + if (ret == 0) { + printf("Signed a message, key: %s, scheme: %x, signature size: %zu\n", path, selected_algorithm, outbuf.off); + } + else { + printf("Sign failed, key: %s, scheme: %x, signature size: %zu\n", path, selected_algorithm, outbuf.off); + } + ptls_buffer_dispose(&outbuf); + ptls_mbedtls_dispose_sign_certificate(&signer->super); + } + + if (ret != 0) { + ok(!"fail"); + return; + } + ok(!!"success"); +} + +void test_sign_certificate(void) +{ + int ret = 0; + + ok(test_load_one_der_key(ASSET_RSA_KEY)); + ok(test_load_one_der_key(ASSET_SECP256R1_KEY)); + ok(test_load_one_der_key(ASSET_SECP384R1_KEY)); + ok(test_load_one_der_key(ASSET_SECP521R1_KEY)); + ok(test_load_one_der_key(ASSET_SECP256R1_PKCS8_KEY)); + ok(test_load_one_der_key(ASSET_RSA_PKCS8_KEY)); + + /* we do not test EDDSA keys, because they are not yet supported */ + + return ret; +} + DEFINE_FFX_AES128_ALGORITHMS(mbedtls); DEFINE_FFX_CHACHA20_ALGORITHMS(mbedtls); @@ -113,29 +256,29 @@ int main(int argc, char **argv) ptls_minicrypto_init_secp256r1sha256_sign_certificate( &minicrypto_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1)); ptls_context_t minicrypto_ctx = {ptls_minicrypto_random_bytes, - &ptls_get_time, - ptls_minicrypto_key_exchanges, - ptls_minicrypto_cipher_suites, - {&secp256r1_certificate, 1}, - {{NULL}}, - NULL, - NULL, - &minicrypto_sign_certificate.super}; + &ptls_get_time, + ptls_minicrypto_key_exchanges, + ptls_minicrypto_cipher_suites, + {&secp256r1_certificate, 1}, + {{NULL}}, + NULL, + NULL, + &minicrypto_sign_certificate.super}; /* context using mbedtls as backend; minicrypto is used for signing certificate as the mbedtls backend does not (yet) have the - * capability */ + * capability */ ptls_minicrypto_secp256r1sha256_sign_certificate_t mbedtls_sign_certificate; ptls_minicrypto_init_secp256r1sha256_sign_certificate( &mbedtls_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1)); ptls_context_t mbedtls_ctx = {ptls_mbedtls_random_bytes, - &ptls_get_time, - ptls_mbedtls_key_exchanges, - ptls_mbedtls_cipher_suites, - {&secp256r1_certificate, 1}, - {{NULL}}, - NULL, - NULL, - &mbedtls_sign_certificate.super}; + &ptls_get_time, + ptls_mbedtls_key_exchanges, + ptls_mbedtls_cipher_suites, + {&secp256r1_certificate, 1}, + {{NULL}}, + NULL, + NULL, + &mbedtls_sign_certificate.super}; ctx = &mbedtls_ctx; ctx_peer = &mbedtls_ctx; @@ -149,6 +292,9 @@ int main(int argc, char **argv) ctx_peer = &mbedtls_ctx; subtest("minicrypto vs.", test_picotls); + /* test the sign certificate */ + subtest("sign certificate", test_sign_certificate) + /* Deinitialize the PSA crypto library. */ mbedtls_psa_crypto_free(); From a8da331afdcdd278ea998e374d616ac09434e002 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Sun, 3 Dec 2023 16:48:42 -0800 Subject: [PATCH 114/151] Add some comments --- t/mbedtls.c | 40 +--------------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/t/mbedtls.c b/t/mbedtls.c index b9649ff91..5a2dbd0bb 100644 --- a/t/mbedtls.c +++ b/t/mbedtls.c @@ -90,7 +90,7 @@ static void test_key_exchanges(void) } /* -Sign certificate has to implement a callback: +Sign certificate implements a callback: if ((ret = tls->ctx->sign_certificate->cb( tls->ctx->sign_certificate, tls, tls->is_server ? &tls->server.async_job : NULL, &algo, sendbuf, @@ -109,44 +109,6 @@ ptls_buffer_t *output, ptls_iovec_t input, const uint16_t *algorithms, size_t nu The notation is simple: input buffer and supported algorithms as input, selected algo and output buffer as output. Output buffer is already partially filled. -For PSA/MbedTLS, see: -https://mbed-tls.readthedocs.io/en/latest/getting_started/psa/ -Using PSA, Signing a message with RSA provides the following sequence: - --- Set key attributes -- -psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); -psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW); -psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); -psa_set_key_bits(&attributes, 1024); - --- Import the key -- -status = psa_import_key(&attributes, key, key_len, &key_id); -if (status != PSA_SUCCESS) { -printf("Failed to import key\n"); -return; -} - --- Sign message using the key -- -status = psa_sign_hash(key_id, PSA_ALG_RSA_PKCS1V15_SIGN_RAW, -hash, sizeof(hash), -signature, sizeof(signature), -&signature_length); - -TODO: verify that Picotls does compute the hash before calling sign. -TODO: verify that there are "sign raw" implementations for ECDSA, EDDSA - --- Verify hash: -psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) - -Load a key in memory - -int mbedtls_pk_parse_keyfile(mbedtls_pk_context* ctx, -const char* path, const char* pwd, -int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); - -But before using the psa API, the key must be imported. That means the key has to -be expressed in the proper x509/DER format. - */ #define ASSET_RSA_KEY "t/assets/rsa/key.pem" From 5bb478283553a895b9179cfd9cf4b6e650efd8d3 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 4 Dec 2023 10:21:20 +0900 Subject: [PATCH 115/151] core does not depend on any crypto backend --- lib/picotls.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index b00b4292e..ef72b2cf8 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -39,10 +39,6 @@ #include "picotls-probes.h" #endif -#ifdef PTLS_HAVE_AEGIS -#include -#endif - #define PTLS_MAX_PLAINTEXT_RECORD_SIZE 16384 #define PTLS_MAX_ENCRYPTED_RECORD_SIZE (16384 + 256) From de804573a45e75a069a6013840dd114cdf2e8116 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 4 Dec 2023 10:26:45 +0900 Subject: [PATCH 116/151] minicrypto symbols can be found in the header files --- lib/cifra/libaegis.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/cifra/libaegis.c b/lib/cifra/libaegis.c index 0b4af9349..1cb3418c3 100644 --- a/lib/cifra/libaegis.c +++ b/lib/cifra/libaegis.c @@ -20,11 +20,9 @@ * IN THE SOFTWARE. */ +#include "picotls/minicrypto.h" #include "../libaegis.h" -extern ptls_hash_algorithm_t ptls_minicrypto_sha256; -extern ptls_hash_algorithm_t ptls_minicrypto_sha384; - ptls_aead_algorithm_t ptls_minicrypto_aegis128l = {"AEGIS-128L", PTLS_AEGIS128L_CONFIDENTIALITY_LIMIT, PTLS_AEGIS128L_INTEGRITY_LIMIT, From 5035d92aaf881af0122d2db15c96391cb30b34df Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 4 Dec 2023 10:26:53 +0900 Subject: [PATCH 117/151] add aegis files to xcode --- picotls.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj index 053d89efa..338535e88 100644 --- a/picotls.xcodeproj/project.pbxproj +++ b/picotls.xcodeproj/project.pbxproj @@ -205,6 +205,8 @@ 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 = ""; }; + 085BDAE52B1D618E002851EA /* libaegis.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libaegis.c; sourceTree = ""; }; + 085BDAE62B1D6238002851EA /* libaegis.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libaegis.h; sourceTree = ""; }; 087F1A732B034AEB00E81AC1 /* FindMbedTLS.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = FindMbedTLS.cmake; sourceTree = ""; }; 0883D3272AEF8F2500B711CC /* fusion.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = fusion.cmake; sourceTree = ""; }; 0883D32A2AF601A700B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = ""; }; @@ -448,6 +450,7 @@ E97577022212405D00D1EF74 /* ffx.c */, E9B43DBF24619D1700824E51 /* fusion.c */, 08F0FDF52910F67A00EE657D /* hpke.c */, + 085BDAE62B1D6238002851EA /* libaegis.h */, 0883D32B2AF601B900B711CC /* mbedtls.c */, E949EF272073629300511ECA /* minicrypto-pem.c */, 106530C21D9B004B005B2C60 /* openssl.c */, @@ -556,6 +559,7 @@ E9F20BE222E34B340018D260 /* aes128.c */, E9F20BE022E34B340018D260 /* aes256.c */, E9F20BE422E34B340018D260 /* chacha20.c */, + 085BDAE52B1D618E002851EA /* libaegis.c */, E9F20BF922E34C110018D260 /* random.c */, E9F20BE122E34B340018D260 /* x25519.c */, ); From 163effd7afad94f01a0c1ffc944b9af0e33bce95 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 13 Dec 2023 13:20:28 +0900 Subject: [PATCH 118/151] raise error if a TLS struct does not fit --- include/picotls.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/picotls.h b/include/picotls.h index e0c390811..98dbe133a 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -248,6 +248,7 @@ extern "C" { #define PTLS_ERROR_REJECT_EARLY_DATA (PTLS_ERROR_CLASS_INTERNAL + 9) #define PTLS_ERROR_DELEGATE (PTLS_ERROR_CLASS_INTERNAL + 10) #define PTLS_ERROR_ASYNC_OPERATION (PTLS_ERROR_CLASS_INTERNAL + 11) +#define PTLS_ERROR_BLOCK_OVERFLOW (PTLS_ERROR_CLASS_INTERNAL + 12) #define PTLS_ERROR_INCORRECT_BASE64 (PTLS_ERROR_CLASS_INTERNAL + 50) #define PTLS_ERROR_PEM_LABEL_NOT_FOUND (PTLS_ERROR_CLASS_INTERNAL + 51) @@ -1203,6 +1204,10 @@ static uint8_t *ptls_encode_quicint(uint8_t *p, uint64_t v); } while (0); \ size_t body_size = (buf)->off - body_start; \ if (capacity != -1) { \ + if (body_size >= (size_t)1 << (capacity * 8)) { \ + ret = PTLS_ERROR_BLOCK_OVERFLOW; \ + goto Exit; \ + } \ for (; capacity != 0; --capacity) \ (buf)->base[body_start - capacity] = (uint8_t)(body_size >> (8 * (capacity - 1))); \ } else { \ From 55e28f44490967ec6ff73f40ec1750780c89f4c9 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 13 Dec 2023 13:37:35 +0900 Subject: [PATCH 119/151] add test --- t/picotls.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/t/picotls.c b/t/picotls.c index c82cc414a..a5a79dc2c 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -1901,6 +1901,56 @@ static void test_all_handshakes(void) ctx->sign_certificate = second_sc_orig; } +static void do_test_tlsblock(size_t len_encoded, size_t max_bytes) +{ + ptls_buffer_t buf; + const uint8_t *src, *end; + int expect_overflow = 0, ret; + + /* block that fits in */ + ptls_buffer_init(&buf, "", 0); + ptls_buffer_push_block(&buf, len_encoded, { + for (size_t i = 0; i < max_bytes; ++i) + ptls_buffer_push(&buf, (uint8_t)i); + }); + src = buf.base; + end = buf.base + buf.off; + ptls_decode_block(src, end, len_encoded, { + ok(end - src == 255); + for (size_t i = 0; i < max_bytes; ++i) + ok(*src == i); + src = end; + }); + + /* block that does not fit in */ + ptls_buffer_push_block(&buf, len_encoded, { + for (size_t i = 0; i < max_bytes + 1; i++) + ptls_buffer_push(&buf, 1); + expect_overflow = 1; + }); + ok(!"fail"); + +Exit: + if (ret != 0) { + if (expect_overflow) { + ok(ret == PTLS_ERROR_BLOCK_OVERFLOW); + } else { + ok(!"fail"); + } + } + ptls_buffer_dispose(&buf); +} + +static void test_tlsblock8(void) +{ + do_test_tlsblock(1, 255); +} + +static void test_tlsblock16(void) +{ + do_test_tlsblock(2, 65535); +} + static void test_quicint(void) { #define CHECK_PATTERN(output, ...) \ @@ -2161,6 +2211,8 @@ void test_picotls(void) subtest("chacha20", test_chacha20); subtest("ffx", test_ffx); subtest("base64-decode", test_base64_decode); + subtest("tls-block8", test_tlsblock8); + subtest("tls-block16", test_tlsblock16); subtest("ech", test_ech); subtest("fragmented-message", test_fragmented_message); subtest("handshake", test_all_handshakes); From 531d1efc4c789bea95372b5303ce9cbf1a93e920 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Wed, 13 Dec 2023 13:58:10 +0900 Subject: [PATCH 120/151] fix errors in tests --- t/picotls.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/t/picotls.c b/t/picotls.c index a5a79dc2c..8bc5ab444 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -1916,9 +1916,13 @@ static void do_test_tlsblock(size_t len_encoded, size_t max_bytes) src = buf.base; end = buf.base + buf.off; ptls_decode_block(src, end, len_encoded, { - ok(end - src == 255); - for (size_t i = 0; i < max_bytes; ++i) - ok(*src == i); + ok(end - src == max_bytes); + int bytes_eq = 1; + for (size_t i = 0; i < max_bytes; ++i) { + if (src[i] != (uint8_t)i) + bytes_eq = 0; + } + ok(bytes_eq); src = end; }); From 6031b2e7260f1c295f28139e15e4ec8a792c17be Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 9 Jan 2024 09:44:41 +0900 Subject: [PATCH 121/151] cannot test if `capacity` is equal to or greater than size_t --- include/picotls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/picotls.h b/include/picotls.h index 98dbe133a..3542c3a40 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -1204,7 +1204,7 @@ static uint8_t *ptls_encode_quicint(uint8_t *p, uint64_t v); } while (0); \ size_t body_size = (buf)->off - body_start; \ if (capacity != -1) { \ - if (body_size >= (size_t)1 << (capacity * 8)) { \ + if (capacity < sizeof(size_t) && body_size >= (size_t)1 << (capacity * 8)) { \ ret = PTLS_ERROR_BLOCK_OVERFLOW; \ goto Exit; \ } \ From a896a55339c9802c63c0143d325fbe7c0f75cca4 Mon Sep 17 00:00:00 2001 From: ha0li Date: Tue, 9 Jan 2024 09:58:38 +0900 Subject: [PATCH 122/151] add support for CERTIFICATE_AUTHORITIES extension --- include/picotls.h | 7 +++++++ lib/picotls.c | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/picotls.h b/include/picotls.h index e0c390811..43cd62813 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -981,6 +981,13 @@ struct st_ptls_context_t { * (optional) list of supported tls12 cipher-suites terminated by NULL */ ptls_cipher_suite_t **tls12_cipher_suites; + /** + * (optional) used in CR message, must be DNs in DER format. + */ + struct { + const ptls_iovec_t *list; + size_t count; + } client_ca_names; }; typedef struct st_ptls_raw_extension_t { diff --git a/lib/picotls.c b/lib/picotls.c index ef72b2cf8..90e77fb6b 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -67,6 +67,7 @@ #define PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS 43 #define PTLS_EXTENSION_TYPE_COOKIE 44 #define PTLS_EXTENSION_TYPE_PSK_KEY_EXCHANGE_MODES 45 +#define PTLS_EXTENSION_TYPE_CERTIFICATE_AUTHORITIES 47 #define PTLS_EXTENSION_TYPE_KEY_SHARE 51 #define PTLS_EXTENSION_TYPE_ECH_OUTER_EXTENSIONS 0xfd00 #define PTLS_EXTENSION_TYPE_ENCRYPTED_CLIENT_HELLO 0xfe0d @@ -4684,6 +4685,20 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl if ((ret = push_signature_algorithms(tls->ctx->verify_certificate, sendbuf)) != 0) goto Exit; }); + + /* certificate authorities entension */ + if (tls->ctx->client_ca_names.count > 0) { + buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_CERTIFICATE_AUTHORITIES, { + ptls_buffer_push_block(sendbuf, 2, { + for (size_t i = 0; i != tls->ctx->client_ca_names.count; ++i) { + ptls_buffer_push_block(sendbuf, 2, { + ptls_iovec_t name = tls->ctx->client_ca_names.list[i]; + ptls_buffer_pushv(sendbuf, name.base, name.len); + }); + } + }); + }); + } }); }); From bf9d64c9f65b2cff4db67a553f68e663bd379679 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Tue, 9 Jan 2024 10:00:47 +0900 Subject: [PATCH 123/151] adjust comments --- include/picotls.h | 6 +++--- lib/picotls.c | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index 43cd62813..e4584dbb2 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -919,8 +919,7 @@ struct st_ptls_context_t { */ unsigned send_change_cipher_spec : 1; /** - * if set, the server requests client certificates - * to authenticate the client. + * if set, the server requests client certificates to authenticate the client */ unsigned require_client_authentication : 1; /** @@ -982,7 +981,8 @@ struct st_ptls_context_t { */ ptls_cipher_suite_t **tls12_cipher_suites; /** - * (optional) used in CR message, must be DNs in DER format. + * (optional) list of CAs advertised to clients as supported in the CertificateRequest message; each item must be DNs in DER + * format. The values are sent to the client only when `ptls_context_t::require_client_authentication` is set to true. */ struct { const ptls_iovec_t *list; diff --git a/lib/picotls.c b/lib/picotls.c index 90e77fb6b..f37ff969d 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -4674,10 +4674,9 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl /* send certificate request if client authentication is activated */ if (tls->ctx->require_client_authentication) { ptls_push_message(emitter, tls->key_schedule, PTLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST, { - /* certificate_request_context, this field SHALL be zero length, unless the certificate - * request is used for post-handshake authentication. - */ ptls_buffer_t *sendbuf = emitter->buf; + /* certificate_request_context: this field SHALL be zero length, unless the certificate request is used for post- + * handshake authentication. */ ptls_buffer_push(sendbuf, 0); /* extensions */ ptls_buffer_push_block(sendbuf, 2, { @@ -4685,8 +4684,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl if ((ret = push_signature_algorithms(tls->ctx->verify_certificate, sendbuf)) != 0) goto Exit; }); - - /* certificate authorities entension */ + /* certificate authorities entension */ if (tls->ctx->client_ca_names.count > 0) { buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_CERTIFICATE_AUTHORITIES, { ptls_buffer_push_block(sendbuf, 2, { From 7709dd92403af4c80222e43d32dd5bd913035c02 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Mon, 8 Jan 2024 21:37:51 -0800 Subject: [PATCH 124/151] Merge from Picotls Jan 8, 2024 (#12) * Incorporate mbedtls in cmake * include find mbedtls * Add cmake module path * Add find package * Update MbedTLS find * Add missing endif * Check mbedtls found condition * Struggling with Found condition. * Remove error condition for debug * update mbedtls test * fix typo * Add github action for mbedtls * Debugging github action. * Decomposing the build steps * More debugging of github action * Build mbedtls parallel to picotls * Add sha512 and sha384 * Update sha384 definitions and test * Add aes256gcm * Add chachapoly * Add test definition. * Fix copy paste errors * Another typo to fix * Fix declarations * use chacha20 test * Fix chacha20 declaration * One last typo, hopefully * That's for coding when half asleep * Provide capability to segment session resumption using user-supplied value * Fix initialization of chacha20-ctr * Add mbedtls to ptlsbench * Fix debug message * Condition fusion to PTLS_HAVE_FUSION * Declare cipher suites * Add support for MbedTLS random * typo * [minicrypto] x25519 key derivation must fail when output is all-zero * use high level PSA API * msvc compatibility * here also * Fix test random * Fix typo * Add code of sec256r1 * [boringssl] check x25519 bad key * clear secret * use macro to avoid compile errors * Simplify aead setup * Add x25519 * Add test of mbedtls key exchanges * Fix reference to test_key_exchange * [evp_keyex_init] keep refcount unchanged when the function fails * add the failing case * extensions block is optional in TLS/1.2 also * even though we do not test what is recorded, clear it otherwise tests that follow fail * [fusion] unify detection scheme to the best one that we have (which we have had in h2o) * maybe `_mm_insert_epi64` is unavailable on i386? * clang-format * rename files following the convention that backends use just the backend name * `()` in a prototype means any number of args, no zero * ensure that MBEDTLS_SHA384_C is detected regardless of include order * API doc goes into .h * add capability to define custom clone functions for hash contexts * [xcode] add files * rename (amends 08e5319) * these files are included by `crypto.h` * when building picotls, picotls is not part of the system * when building picotls, picotls is not part of the system, whereas mbedtls is * define hash implementations using `ptls_define_hash` * mbedtls is dependency * it is our convention to let the user initialize the crypto backends (see openssl) * PRNG might fail too * reduce state of symmentric ciphers; no need to set key for every IV * engines can be tested using `test_picotls` * report error in detail * have ones own * amend 2106299 * `ptls_cipher_init` is not called in ECB mode * key_schedule_new might fail due to malloc failing * limit scope of `psa_key_attributes_t` * move useful comments to `.h`, as they are not specific to the mbedtls backend * simply AEAD code by only supporting the mandatory operation types * update test code to not rely on init-update-final cycle that is now optional (see doc-comment of ptls_aead_context_t) * fail the same way * expand doc-comment in picotls.h instead * reduce state, release memory regardless of errors * add missing `static` * no need to have prefix for static functions * consolidate duplicated constants into `const struct` * reduce state * ... and we find a bug * update the hidden chacha20 backend * no need to have a wrapper for CTR mode * remove verbose doc comments * [xcode] add files * use standard names (e.g., _ROOT_DIR), and UNIX-style search paths (/usr/local, lib) * sha384 might not be available * mbedtls of ubuntu2204 does not have these files, we can remove them and still refer to `MBEDTLS_SHA384_C` at least on homebrew * run mbedtls test as part of the main CI (builds on top of https://github.com/h2o/h2o/pull/3311) * remove non-standard directory * Replace the TLS_AEGIS_256_SHA384 ciphersuite with TLS_AEGIS_256_SHA512 The latest AEGIS draft, as well as the IANA TLS registry [1] have been updated to replace TLS_AEGIS_256_SHA384 with TLS_AEGIS_256_SHA512. This follows the recommendations from [2] for new cipher suites. [1] https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 [2] https://eprint.iacr.org/2023/913.pdf * core does not depend on any crypto backend * minicrypto symbols can be found in the header files * add aegis files to xcode * raise error if a TLS struct does not fit * add test * fix errors in tests * cannot test if `capacity` is equal to or greater than size_t * add support for CERTIFICATE_AUTHORITIES extension * adjust comments --------- Co-authored-by: Christian Huitema Co-authored-by: Roberto Guimaraes Co-authored-by: Kazuho Oku Co-authored-by: Frank Denis Co-authored-by: ha0li --- include/picotls.h | 27 +++++- include/picotls/mbedtls.h | 3 - include/picotls/minicrypto.h | 4 +- include/picotls/openssl.h | 2 +- lib/cifra.c | 6 +- lib/cifra/aes256.c | 5 ++ lib/cifra/libaegis.c | 10 +-- lib/openssl.c | 8 +- lib/picotls.c | 59 +++++++----- picotls.xcodeproj/project.pbxproj | 4 + t/mbedtls.c | 143 ++++-------------------------- t/openssl.c | 3 +- t/picotls.c | 60 ++++++++++++- 13 files changed, 163 insertions(+), 171 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index 3b7a96dec..70abcf84a 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -130,8 +130,8 @@ extern "C" { #define PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" #define PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256 0x1303 #define PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" -#define PTLS_CIPHER_SUITE_AEGIS256_SHA384 0x1306 -#define PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384 "TLS_AEGIS_256_SHA384" +#define PTLS_CIPHER_SUITE_AEGIS256_SHA512 0x1306 +#define PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512 "TLS_AEGIS_256_SHA512" #define PTLS_CIPHER_SUITE_AEGIS128L_SHA256 0x1307 #define PTLS_CIPHER_SUITE_NAME_AEGIS128L_SHA256 "TLS_AEGIS_128L_SHA256" @@ -248,6 +248,7 @@ extern "C" { #define PTLS_ERROR_REJECT_EARLY_DATA (PTLS_ERROR_CLASS_INTERNAL + 9) #define PTLS_ERROR_DELEGATE (PTLS_ERROR_CLASS_INTERNAL + 10) #define PTLS_ERROR_ASYNC_OPERATION (PTLS_ERROR_CLASS_INTERNAL + 11) +#define PTLS_ERROR_BLOCK_OVERFLOW (PTLS_ERROR_CLASS_INTERNAL + 12) #define PTLS_ERROR_INCORRECT_BASE64 (PTLS_ERROR_CLASS_INTERNAL + 50) #define PTLS_ERROR_PEM_LABEL_NOT_FOUND (PTLS_ERROR_CLASS_INTERNAL + 51) @@ -919,8 +920,7 @@ struct st_ptls_context_t { */ unsigned send_change_cipher_spec : 1; /** - * if set, the server requests client certificates - * to authenticate the client. + * if set, the server requests client certificates to authenticate the client */ unsigned require_client_authentication : 1; /** @@ -981,6 +981,21 @@ struct st_ptls_context_t { * (optional) list of supported tls12 cipher-suites terminated by NULL */ ptls_cipher_suite_t **tls12_cipher_suites; + /** + * (optional) session ID Context to segment resumption + */ + struct { + uint8_t bytes[PTLS_SHA256_DIGEST_SIZE]; + uint8_t is_set : 1; + } ticket_context; + /** + * (optional) list of CAs advertised to clients as supported in the CertificateRequest message; each item must be DNs in DER + * format. The values are sent to the client only when `ptls_context_t::require_client_authentication` is set to true. + */ + struct { + const ptls_iovec_t *list; + size_t count; + } client_ca_names; }; typedef struct st_ptls_raw_extension_t { @@ -1203,6 +1218,10 @@ static uint8_t *ptls_encode_quicint(uint8_t *p, uint64_t v); } while (0); \ size_t body_size = (buf)->off - body_start; \ if (capacity != -1) { \ + if (capacity < sizeof(size_t) && body_size >= (size_t)1 << (capacity * 8)) { \ + ret = PTLS_ERROR_BLOCK_OVERFLOW; \ + goto Exit; \ + } \ for (; capacity != 0; --capacity) \ (buf)->base[body_start - capacity] = (uint8_t)(body_size >> (8 * (capacity - 1))); \ } else { \ diff --git a/include/picotls/mbedtls.h b/include/picotls/mbedtls.h index 581c41655..b64924694 100644 --- a/include/picotls/mbedtls.h +++ b/include/picotls/mbedtls.h @@ -60,9 +60,6 @@ extern ptls_key_exchange_algorithm_t *ptls_mbedtls_key_exchanges[]; void ptls_mbedtls_random_bytes(void *buf, size_t len); -int ptls_mbedtls_load_private_key(ptls_context_t* ctx, char const* pem_fname); -void ptls_mbedtls_dispose_sign_certificate(ptls_sign_certificate_t* _self); - #ifdef __cplusplus } #endif diff --git a/include/picotls/minicrypto.h b/include/picotls/minicrypto.h index ca3a31d9d..a6202d026 100644 --- a/include/picotls/minicrypto.h +++ b/include/picotls/minicrypto.h @@ -51,11 +51,11 @@ extern ptls_aead_algorithm_t ptls_minicrypto_aes128gcm, ptls_minicrypto_aes256gc extern ptls_aead_algorithm_t ptls_minicrypto_aegis128l; extern ptls_aead_algorithm_t ptls_minicrypto_aegis256; #endif -extern ptls_hash_algorithm_t ptls_minicrypto_sha256, ptls_minicrypto_sha384; +extern ptls_hash_algorithm_t ptls_minicrypto_sha256, ptls_minicrypto_sha384, ptls_minicrypto_sha512; extern ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256, ptls_minicrypto_aes256gcmsha384, ptls_minicrypto_chacha20poly1305sha256; #ifdef PTLS_HAVE_AEGIS extern ptls_cipher_suite_t ptls_minicrypto_aegis128lsha256; -extern ptls_cipher_suite_t ptls_minicrypto_aegis256sha384; +extern ptls_cipher_suite_t ptls_minicrypto_aegis256sha512; #endif extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[]; extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[]; diff --git a/include/picotls/openssl.h b/include/picotls/openssl.h index 987b9b1f2..de777c8dc 100644 --- a/include/picotls/openssl.h +++ b/include/picotls/openssl.h @@ -98,7 +98,7 @@ extern ptls_cipher_suite_t ptls_openssl_chacha20poly1305sha256; extern ptls_aead_algorithm_t ptls_openssl_aegis128l; extern ptls_aead_algorithm_t ptls_openssl_aegis256; extern ptls_cipher_suite_t ptls_openssl_aegis128lsha256; -extern ptls_cipher_suite_t ptls_openssl_aegis256sha384; +extern ptls_cipher_suite_t ptls_openssl_aegis256sha512; #endif extern ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_rsa_aes128gcmsha256; diff --git a/lib/cifra.c b/lib/cifra.c index d51f2b703..5fe9febab 100644 --- a/lib/cifra.c +++ b/lib/cifra.c @@ -23,7 +23,7 @@ #include "picotls.h" #include "picotls/minicrypto.h" -ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha384 (must be first) +ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha512 and sha384 (must be first) &ptls_minicrypto_aes256gcmsha384, // ciphers used with sha256 @@ -31,9 +31,9 @@ ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha &ptls_minicrypto_chacha20poly1305sha256, NULL}; -ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = {// ciphers used with sha384 (must be first) +ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = {// ciphers used with sha512 and sha384 (must be first) #ifdef PTLS_HAVE_AEGIS - &ptls_minicrypto_aegis256sha384, + &ptls_minicrypto_aegis256sha512, #endif &ptls_minicrypto_aes256gcmsha384, diff --git a/lib/cifra/aes256.c b/lib/cifra/aes256.c index d4cefa9e9..e074dea8f 100644 --- a/lib/cifra/aes256.c +++ b/lib/cifra/aes256.c @@ -41,6 +41,11 @@ ptls_define_hash(sha384, cf_sha512_context, cf_sha384_init, cf_sha384_update, cf ptls_hash_algorithm_t ptls_minicrypto_sha384 = {"sha384", PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, sha384_create, PTLS_ZERO_DIGEST_SHA384}; +ptls_define_hash(sha512, cf_sha512_context, cf_sha512_init, cf_sha512_update, cf_sha512_digest_final); + +ptls_hash_algorithm_t ptls_minicrypto_sha512 = {"sha512", PTLS_SHA512_BLOCK_SIZE, PTLS_SHA512_DIGEST_SIZE, sha512_create, + PTLS_ZERO_DIGEST_SHA512}; + ptls_cipher_algorithm_t ptls_minicrypto_aes256ecb = { "AES256-ECB", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct aesecb_context_t), aes256ecb_setup_crypto}; diff --git a/lib/cifra/libaegis.c b/lib/cifra/libaegis.c index 0b4af9349..76fc9e42a 100644 --- a/lib/cifra/libaegis.c +++ b/lib/cifra/libaegis.c @@ -20,11 +20,9 @@ * IN THE SOFTWARE. */ +#include "picotls/minicrypto.h" #include "../libaegis.h" -extern ptls_hash_algorithm_t ptls_minicrypto_sha256; -extern ptls_hash_algorithm_t ptls_minicrypto_sha384; - ptls_aead_algorithm_t ptls_minicrypto_aegis128l = {"AEGIS-128L", PTLS_AEGIS128L_CONFIDENTIALITY_LIMIT, PTLS_AEGIS128L_INTEGRITY_LIMIT, @@ -56,7 +54,7 @@ ptls_aead_algorithm_t ptls_minicrypto_aegis256 = {"AEGIS-256", 0, sizeof(struct aegis256_context_t), aegis256_setup_crypto}; -ptls_cipher_suite_t ptls_minicrypto_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384, - .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384, +ptls_cipher_suite_t ptls_minicrypto_aegis256sha512 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA512, + .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512, .aead = &ptls_minicrypto_aegis256, - .hash = &ptls_minicrypto_sha384}; + .hash = &ptls_minicrypto_sha512}; diff --git a/lib/openssl.c b/lib/openssl.c index a6abafe51..70a3e7e9a 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -2220,10 +2220,10 @@ ptls_aead_algorithm_t ptls_openssl_aegis256 = { .context_size = sizeof(struct aegis256_context_t), .setup_crypto = aegis256_setup_crypto, }; -ptls_cipher_suite_t ptls_openssl_aegis256sha384 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA384, - .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA384, +ptls_cipher_suite_t ptls_openssl_aegis256sha512 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA512, + .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512, .aead = &ptls_openssl_aegis256, - .hash = &ptls_openssl_sha384}; + .hash = &ptls_openssl_sha512}; #endif @@ -2240,7 +2240,7 @@ ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = {// ciphers used with sha384 ptls_cipher_suite_t *ptls_openssl_cipher_suites_all[] = {// ciphers used with sha384 (must be first) #if PTLS_HAVE_AEGIS - &ptls_openssl_aegis256sha384, + &ptls_openssl_aegis256sha512, #endif &ptls_openssl_aes256gcmsha384, diff --git a/lib/picotls.c b/lib/picotls.c index b00b4292e..7f8fd9ae3 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -39,10 +39,6 @@ #include "picotls-probes.h" #endif -#ifdef PTLS_HAVE_AEGIS -#include -#endif - #define PTLS_MAX_PLAINTEXT_RECORD_SIZE 16384 #define PTLS_MAX_ENCRYPTED_RECORD_SIZE (16384 + 256) @@ -71,6 +67,7 @@ #define PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS 43 #define PTLS_EXTENSION_TYPE_COOKIE 44 #define PTLS_EXTENSION_TYPE_PSK_KEY_EXCHANGE_MODES 45 +#define PTLS_EXTENSION_TYPE_CERTIFICATE_AUTHORITIES 47 #define PTLS_EXTENSION_TYPE_KEY_SHARE 51 #define PTLS_EXTENSION_TYPE_ECH_OUTER_EXTENSIONS 0xfd00 #define PTLS_EXTENSION_TYPE_ENCRYPTED_CLIENT_HELLO 0xfe0d @@ -1706,10 +1703,13 @@ static int encode_session_identifier(ptls_context_t *ctx, ptls_buffer_t *buf, ui ptls_buffer_push16(buf, csid); /* ticket_age_add */ ptls_buffer_push32(buf, ticket_age_add); - /* server-name */ + /* session ID context */ ptls_buffer_push_block(buf, 2, { - if (server_name != NULL) + if (ctx->ticket_context.is_set) { + ptls_buffer_pushv(buf, ctx->ticket_context.bytes, sizeof(ctx->ticket_context.bytes)); + } else if (server_name != NULL) { ptls_buffer_pushv(buf, server_name, strlen(server_name)); + } }); /* alpn */ ptls_buffer_push_block(buf, 1, { @@ -1722,7 +1722,7 @@ static int encode_session_identifier(ptls_context_t *ctx, ptls_buffer_t *buf, ui return ret; } -int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t *ticket_age_add, ptls_iovec_t *server_name, +int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t *ticket_age_add, ptls_iovec_t *ticket_ctx, uint16_t *key_exchange_id, uint16_t *csid, ptls_iovec_t *negotiated_protocol, const uint8_t *src, const uint8_t *const end) { @@ -1748,7 +1748,7 @@ int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t * if ((ret = ptls_decode32(ticket_age_add, &src, end)) != 0) goto Exit; ptls_decode_open_block(src, end, 2, { - *server_name = ptls_iovec_init(src, end - src); + *ticket_ctx = ptls_iovec_init(src, end - src); src = end; }); ptls_decode_open_block(src, end, 1, { @@ -4009,7 +4009,7 @@ static int try_psk_handshake(ptls_t *tls, size_t *psk_index, int *accept_early_d ptls_iovec_t ch_trunc) { ptls_buffer_t decbuf; - ptls_iovec_t ticket_psk, ticket_server_name, ticket_negotiated_protocol; + ptls_iovec_t ticket_psk, ticket_ctx, ticket_negotiated_protocol; uint64_t issue_at, now = tls->ctx->get_time->cb(tls->ctx->get_time); uint32_t age_add; uint16_t ticket_key_exchange_id, ticket_csid; @@ -4032,7 +4032,7 @@ static int try_psk_handshake(ptls_t *tls, size_t *psk_index, int *accept_early_d default: /* decryption failure */ continue; } - if (decode_session_identifier(&issue_at, &ticket_psk, &age_add, &ticket_server_name, &ticket_key_exchange_id, &ticket_csid, + if (decode_session_identifier(&issue_at, &ticket_psk, &age_add, &ticket_ctx, &ticket_key_exchange_id, &ticket_csid, &ticket_negotiated_protocol, decbuf.base, decbuf.base + decbuf.off) != 0) continue; /* check age */ @@ -4049,15 +4049,22 @@ static int try_psk_handshake(ptls_t *tls, size_t *psk_index, int *accept_early_d if (tls->ctx->max_early_data_size != 0 && delta <= PTLS_EARLY_DATA_MAX_DELAY) *accept_early_data = 1; } - /* check server-name */ - if (ticket_server_name.len != 0) { - if (tls->server_name == NULL) - continue; - if (!vec_is_string(ticket_server_name, tls->server_name)) + /* check ticket context */ + if (tls->ctx->ticket_context.is_set) { + if (!(ticket_ctx.len == sizeof(tls->ctx->ticket_context.bytes) && + memcmp(ticket_ctx.base, tls->ctx->ticket_context.bytes, ticket_ctx.len) == 0)) continue; } else { - if (tls->server_name != NULL) - continue; + /* check server-name */ + if (ticket_ctx.len != 0) { + if (tls->server_name == NULL) + continue; + if (!vec_is_string(ticket_ctx, tls->server_name)) + continue; + } else { + if (tls->server_name != NULL) + continue; + } } { /* check key-exchange */ ptls_key_exchange_algorithm_t **a; @@ -4677,10 +4684,9 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl /* send certificate request if client authentication is activated */ if (tls->ctx->require_client_authentication) { ptls_push_message(emitter, tls->key_schedule, PTLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST, { - /* certificate_request_context, this field SHALL be zero length, unless the certificate - * request is used for post-handshake authentication. - */ ptls_buffer_t *sendbuf = emitter->buf; + /* certificate_request_context: this field SHALL be zero length, unless the certificate request is used for post- + * handshake authentication. */ ptls_buffer_push(sendbuf, 0); /* extensions */ ptls_buffer_push_block(sendbuf, 2, { @@ -4688,6 +4694,19 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl if ((ret = push_signature_algorithms(tls->ctx->verify_certificate, sendbuf)) != 0) goto Exit; }); + /* certificate authorities entension */ + if (tls->ctx->client_ca_names.count > 0) { + buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_CERTIFICATE_AUTHORITIES, { + ptls_buffer_push_block(sendbuf, 2, { + for (size_t i = 0; i != tls->ctx->client_ca_names.count; ++i) { + ptls_buffer_push_block(sendbuf, 2, { + ptls_iovec_t name = tls->ctx->client_ca_names.list[i]; + ptls_buffer_pushv(sendbuf, name.base, name.len); + }); + } + }); + }); + } }); }); diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj index 053d89efa..338535e88 100644 --- a/picotls.xcodeproj/project.pbxproj +++ b/picotls.xcodeproj/project.pbxproj @@ -205,6 +205,8 @@ 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 = ""; }; + 085BDAE52B1D618E002851EA /* libaegis.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = libaegis.c; sourceTree = ""; }; + 085BDAE62B1D6238002851EA /* libaegis.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libaegis.h; sourceTree = ""; }; 087F1A732B034AEB00E81AC1 /* FindMbedTLS.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = FindMbedTLS.cmake; sourceTree = ""; }; 0883D3272AEF8F2500B711CC /* fusion.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = fusion.cmake; sourceTree = ""; }; 0883D32A2AF601A700B711CC /* mbedtls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mbedtls.c; sourceTree = ""; }; @@ -448,6 +450,7 @@ E97577022212405D00D1EF74 /* ffx.c */, E9B43DBF24619D1700824E51 /* fusion.c */, 08F0FDF52910F67A00EE657D /* hpke.c */, + 085BDAE62B1D6238002851EA /* libaegis.h */, 0883D32B2AF601B900B711CC /* mbedtls.c */, E949EF272073629300511ECA /* minicrypto-pem.c */, 106530C21D9B004B005B2C60 /* openssl.c */, @@ -556,6 +559,7 @@ E9F20BE222E34B340018D260 /* aes128.c */, E9F20BE022E34B340018D260 /* aes256.c */, E9F20BE422E34B340018D260 /* chacha20.c */, + 085BDAE52B1D618E002851EA /* libaegis.c */, E9F20BF922E34C110018D260 /* random.c */, E9F20BE122E34B340018D260 /* x25519.c */, ); diff --git a/t/mbedtls.c b/t/mbedtls.c index 5a2dbd0bb..f427d16d9 100644 --- a/t/mbedtls.c +++ b/t/mbedtls.c @@ -89,111 +89,7 @@ static void test_key_exchanges(void) subtest("x25519", test_x25519); } -/* -Sign certificate implements a callback: - -if ((ret = tls->ctx->sign_certificate->cb( -tls->ctx->sign_certificate, tls, tls->is_server ? &tls->server.async_job : NULL, &algo, sendbuf, -ptls_iovec_init(data, datalen), signature_algorithms != NULL ? signature_algorithms->list : NULL, -signature_algorithms != NULL ? signature_algorithms->count : 0)) != 0) { - -or: - -static int sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, ptls_async_job_t **async, uint16_t *selected_algorithm, -ptls_buffer_t *outbuf, ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms) - -The callback "super" type is ptls_sign_certificate_t, defined by the macro: -PTLS_CALLBACK_TYPE(int, sign_certificate, ptls_t *tls, ptls_async_job_t **async, uint16_t *selected_algorithm, -ptls_buffer_t *output, ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms); - -The notation is simple: input buffer and supported algorithms as input, selected algo and output buffer as output. -Output buffer is already partially filled. - -*/ - -#define ASSET_RSA_KEY "t/assets/rsa/key.pem" -#define ASSET_RSA_PKCS8_KEY "t/assets/rsa-pkcs8/key.pem" -#define ASSET_SECP256R1_KEY "t/assets/secp256r1/key.pem" -#define ASSET_SECP384R1_KEY "t/assets/secp384r1/key.pem" -#define ASSET_SECP521R1_KEY "t/assets/secp521r1/key.pem" -#define ASSET_SECP256R1_PKCS8_KEY "t/assets/secp256r1-pkcs8/key.pem" - -void test_load_one_der_key(char const* path) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char hash[32]; - const unsigned char h0[32] = { - 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32 - }; - ptls_context_t ctx = { 0 }; - psa_status_t status = 0; - - ret = ptls_mbedtls_load_private_key(&ctx, path); - if (ret != 0) { - ok(ret == 0, "Cannot create sign_certificate from: %s\n", path); - } - else if (ctx.sign_certificate == NULL) { - printf("Sign_certificate not set in ptls context for: %s\n", path); - ret = -1; - } - else { - /* Try to sign something */ - int ret; - ptls_mbedtls_sign_certificate_t* signer = (ptls_mbedtls_sign_certificate_t*) - (((unsigned char*)ctx.sign_certificate) - offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); - /* get the key algorithm */ - psa_algorithm_t algo = psa_get_key_algorithm(&signer->attributes); - ptls_buffer_t outbuf; - uint8_t outbuf_smallbuf[256]; - ptls_iovec_t input = { hash, sizeof(hash) }; - uint16_t selected_algorithm = 0; - int num_algorithms = 0; - uint16_t algorithms[16]; - memcpy(hash, h0, 32); - while (signer->schemes[num_algorithms].scheme_id != UINT16_MAX && num_algorithms < 16) { - algorithms[num_algorithms++] = signer->schemes[num_algorithms].scheme_id; - } - - ptls_buffer_init(&outbuf, outbuf_smallbuf, sizeof(outbuf_smallbuf)); - - ret = ptls_mbedtls_sign_certificate(ctx.sign_certificate, NULL, NULL, &selected_algorithm, - &outbuf, input, algorithms, num_algorithms); - if (ret == 0) { - printf("Signed a message, key: %s, scheme: %x, signature size: %zu\n", path, selected_algorithm, outbuf.off); - } - else { - printf("Sign failed, key: %s, scheme: %x, signature size: %zu\n", path, selected_algorithm, outbuf.off); - } - ptls_buffer_dispose(&outbuf); - ptls_mbedtls_dispose_sign_certificate(&signer->super); - } - - if (ret != 0) { - ok(!"fail"); - return; - } - ok(!!"success"); -} - -void test_sign_certificate(void) -{ - int ret = 0; - - ok(test_load_one_der_key(ASSET_RSA_KEY)); - ok(test_load_one_der_key(ASSET_SECP256R1_KEY)); - ok(test_load_one_der_key(ASSET_SECP384R1_KEY)); - ok(test_load_one_der_key(ASSET_SECP521R1_KEY)); - ok(test_load_one_der_key(ASSET_SECP256R1_PKCS8_KEY)); - ok(test_load_one_der_key(ASSET_RSA_PKCS8_KEY)); - - /* we do not test EDDSA keys, because they are not yet supported */ - - return ret; -} - +< DEFINE_FFX_AES128_ALGORITHMS(mbedtls); DEFINE_FFX_CHACHA20_ALGORITHMS(mbedtls); @@ -218,29 +114,29 @@ int main(int argc, char **argv) ptls_minicrypto_init_secp256r1sha256_sign_certificate( &minicrypto_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1)); ptls_context_t minicrypto_ctx = {ptls_minicrypto_random_bytes, - &ptls_get_time, - ptls_minicrypto_key_exchanges, - ptls_minicrypto_cipher_suites, - {&secp256r1_certificate, 1}, - {{NULL}}, - NULL, - NULL, - &minicrypto_sign_certificate.super}; + &ptls_get_time, + ptls_minicrypto_key_exchanges, + ptls_minicrypto_cipher_suites, + {&secp256r1_certificate, 1}, + {{NULL}}, + NULL, + NULL, + &minicrypto_sign_certificate.super}; /* context using mbedtls as backend; minicrypto is used for signing certificate as the mbedtls backend does not (yet) have the - * capability */ + * capability */ ptls_minicrypto_secp256r1sha256_sign_certificate_t mbedtls_sign_certificate; ptls_minicrypto_init_secp256r1sha256_sign_certificate( &mbedtls_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1)); ptls_context_t mbedtls_ctx = {ptls_mbedtls_random_bytes, - &ptls_get_time, - ptls_mbedtls_key_exchanges, - ptls_mbedtls_cipher_suites, - {&secp256r1_certificate, 1}, - {{NULL}}, - NULL, - NULL, - &mbedtls_sign_certificate.super}; + &ptls_get_time, + ptls_mbedtls_key_exchanges, + ptls_mbedtls_cipher_suites, + {&secp256r1_certificate, 1}, + {{NULL}}, + NULL, + NULL, + &mbedtls_sign_certificate.super}; ctx = &mbedtls_ctx; ctx_peer = &mbedtls_ctx; @@ -254,9 +150,6 @@ int main(int argc, char **argv) ctx_peer = &mbedtls_ctx; subtest("minicrypto vs.", test_picotls); - /* test the sign certificate */ - subtest("sign certificate", test_sign_certificate) - /* Deinitialize the PSA crypto library. */ mbedtls_psa_crypto_free(); diff --git a/t/openssl.c b/t/openssl.c index b3188ff0a..d48744522 100644 --- a/t/openssl.c +++ b/t/openssl.c @@ -564,7 +564,8 @@ int main(int argc, char **argv) .sign_certificate = &openssl_sign_certificate.super}; ptls_context_t openssl_ctx_sha256only = openssl_ctx; while (openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size != 32) { - assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */ + assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 64 || /* sha512 */ + openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */ ++openssl_ctx_sha256only.cipher_suites; } assert(openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size == 32); /* sha256 */ diff --git a/t/picotls.c b/t/picotls.c index 80c8543f5..8bc5ab444 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -506,8 +506,8 @@ static void test_aegis128l(void) static void test_aegis256(void) { - ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AEGIS256_SHA384), - *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AEGIS256_SHA384); + ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AEGIS256_SHA512), + *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AEGIS256_SHA512); if (cs != NULL && cs_peer != NULL) { test_ciphersuite(cs, cs_peer); @@ -1901,6 +1901,60 @@ static void test_all_handshakes(void) ctx->sign_certificate = second_sc_orig; } +static void do_test_tlsblock(size_t len_encoded, size_t max_bytes) +{ + ptls_buffer_t buf; + const uint8_t *src, *end; + int expect_overflow = 0, ret; + + /* block that fits in */ + ptls_buffer_init(&buf, "", 0); + ptls_buffer_push_block(&buf, len_encoded, { + for (size_t i = 0; i < max_bytes; ++i) + ptls_buffer_push(&buf, (uint8_t)i); + }); + src = buf.base; + end = buf.base + buf.off; + ptls_decode_block(src, end, len_encoded, { + ok(end - src == max_bytes); + int bytes_eq = 1; + for (size_t i = 0; i < max_bytes; ++i) { + if (src[i] != (uint8_t)i) + bytes_eq = 0; + } + ok(bytes_eq); + src = end; + }); + + /* block that does not fit in */ + ptls_buffer_push_block(&buf, len_encoded, { + for (size_t i = 0; i < max_bytes + 1; i++) + ptls_buffer_push(&buf, 1); + expect_overflow = 1; + }); + ok(!"fail"); + +Exit: + if (ret != 0) { + if (expect_overflow) { + ok(ret == PTLS_ERROR_BLOCK_OVERFLOW); + } else { + ok(!"fail"); + } + } + ptls_buffer_dispose(&buf); +} + +static void test_tlsblock8(void) +{ + do_test_tlsblock(1, 255); +} + +static void test_tlsblock16(void) +{ + do_test_tlsblock(2, 65535); +} + static void test_quicint(void) { #define CHECK_PATTERN(output, ...) \ @@ -2161,6 +2215,8 @@ void test_picotls(void) subtest("chacha20", test_chacha20); subtest("ffx", test_ffx); subtest("base64-decode", test_base64_decode); + subtest("tls-block8", test_tlsblock8); + subtest("tls-block16", test_tlsblock16); subtest("ech", test_ech); subtest("fragmented-message", test_fragmented_message); subtest("handshake", test_all_handshakes); From 8822c258d6446dd86cd8bb0de9a57956fadbce2e Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Mon, 8 Jan 2024 21:50:13 -0800 Subject: [PATCH 125/151] Fix fatal warning in Windows compilers --- include/picotls.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/picotls.h b/include/picotls.h index 70abcf84a..bbf3739ce 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -986,7 +986,11 @@ struct st_ptls_context_t { */ struct { uint8_t bytes[PTLS_SHA256_DIGEST_SIZE]; +#ifdef _WINDOWS + unsigned int is_set : 1; +#else uint8_t is_set : 1; +#endif } ticket_context; /** * (optional) list of CAs advertised to clients as supported in the CertificateRequest message; each item must be DNs in DER From e490432e2392a6da938de577bdb1aafd168c6de9 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Mon, 8 Jan 2024 22:53:37 -0800 Subject: [PATCH 126/151] Remove spurious < character --- t/mbedtls.c | 1 - 1 file changed, 1 deletion(-) diff --git a/t/mbedtls.c b/t/mbedtls.c index f427d16d9..d3651de14 100644 --- a/t/mbedtls.c +++ b/t/mbedtls.c @@ -89,7 +89,6 @@ static void test_key_exchanges(void) subtest("x25519", test_x25519); } -< DEFINE_FFX_AES128_ALGORITHMS(mbedtls); DEFINE_FFX_CHACHA20_ALGORITHMS(mbedtls); From a3032650afaca6b5f9865cf791b60222779e6573 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Wed, 10 Jan 2024 22:01:59 -0800 Subject: [PATCH 127/151] Update include/picotls.h Co-authored-by: Kazuho Oku --- include/picotls.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index bbf3739ce..7a642707d 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -986,11 +986,7 @@ struct st_ptls_context_t { */ struct { uint8_t bytes[PTLS_SHA256_DIGEST_SIZE]; -#ifdef _WINDOWS - unsigned int is_set : 1; -#else - uint8_t is_set : 1; -#endif + unsigned is_set : 1; } ticket_context; /** * (optional) list of CAs advertised to clients as supported in the CertificateRequest message; each item must be DNs in DER From 28da922677a3583d3c85f058b1acab42aeac2bff Mon Sep 17 00:00:00 2001 From: Ichito Nagata Date: Thu, 22 Feb 2024 02:56:16 +0000 Subject: [PATCH 128/151] clang-format --- lib/chacha20poly1305.h | 2 +- lib/cifra.c | 24 +-- lib/cifra/libaegis.c | 4 +- lib/libaegis.h | 12 +- lib/mbedtls_sign.c | 439 +++++++++++++++++------------------------ lib/openssl.c | 66 +++---- lib/picotls.c | 5 +- t/picotls.c | 18 +- 8 files changed, 248 insertions(+), 322 deletions(-) diff --git a/lib/chacha20poly1305.h b/lib/chacha20poly1305.h index ad2d7fe26..9bdc9cc14 100644 --- a/lib/chacha20poly1305.h +++ b/lib/chacha20poly1305.h @@ -161,7 +161,7 @@ static void chacha20poly1305_set_iv(ptls_aead_context_t *_ctx, const void *iv) struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx; memcpy(ctx->static_iv, iv, sizeof(ctx->static_iv)); - } +} static int chacha20poly1305_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv, ptls_cipher_algorithm_t *chacha, diff --git a/lib/cifra.c b/lib/cifra.c index 5fe9febab..6be752fa0 100644 --- a/lib/cifra.c +++ b/lib/cifra.c @@ -23,24 +23,20 @@ #include "picotls.h" #include "picotls/minicrypto.h" -ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {// ciphers used with sha512 and sha384 (must be first) - &ptls_minicrypto_aes256gcmsha384, +ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = { // ciphers used with sha512 and sha384 (must be first) + &ptls_minicrypto_aes256gcmsha384, - // ciphers used with sha256 - &ptls_minicrypto_aes128gcmsha256, - &ptls_minicrypto_chacha20poly1305sha256, - NULL}; + // ciphers used with sha256 + &ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_chacha20poly1305sha256, NULL}; -ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = {// ciphers used with sha512 and sha384 (must be first) +ptls_cipher_suite_t *ptls_minicrypto_cipher_suites_all[] = { // ciphers used with sha512 and sha384 (must be first) #ifdef PTLS_HAVE_AEGIS - &ptls_minicrypto_aegis256sha512, + &ptls_minicrypto_aegis256sha512, #endif - &ptls_minicrypto_aes256gcmsha384, + &ptls_minicrypto_aes256gcmsha384, - // ciphers used with sha256 +// ciphers used with sha256 #ifdef PTLS_HAVE_AEGIS - &ptls_minicrypto_aegis128lsha256, + &ptls_minicrypto_aegis128lsha256, #endif - &ptls_minicrypto_aes128gcmsha256, - &ptls_minicrypto_chacha20poly1305sha256, - NULL}; + &ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_chacha20poly1305sha256, NULL}; diff --git a/lib/cifra/libaegis.c b/lib/cifra/libaegis.c index 76fc9e42a..8956ee4b7 100644 --- a/lib/cifra/libaegis.c +++ b/lib/cifra/libaegis.c @@ -31,7 +31,7 @@ ptls_aead_algorithm_t ptls_minicrypto_aegis128l = {"AEGIS-128L", PTLS_AEGIS128L_KEY_SIZE, PTLS_AEGIS128L_IV_SIZE, PTLS_AEGIS128L_TAG_SIZE, - { 0, 0 }, + {0, 0}, 0, 0, sizeof(struct aegis128l_context_t), @@ -49,7 +49,7 @@ ptls_aead_algorithm_t ptls_minicrypto_aegis256 = {"AEGIS-256", PTLS_AEGIS256_KEY_SIZE, PTLS_AEGIS256_IV_SIZE, PTLS_AEGIS256_TAG_SIZE, - { 0, 0 }, + {0, 0}, 0, 0, sizeof(struct aegis256_context_t), diff --git a/lib/libaegis.h b/lib/libaegis.h index ec78a4bb1..bc820425e 100644 --- a/lib/libaegis.h +++ b/lib/libaegis.h @@ -63,7 +63,8 @@ static size_t aegis128l_encrypt_update(ptls_aead_context_t *_ctx, void *output, struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; size_t written; - aegis128l_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis128l_TAILBYTES_MAX, &written, (const uint8_t *)input, inlen); + aegis128l_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis128l_TAILBYTES_MAX, &written, (const uint8_t *)input, + inlen); return written; } @@ -73,7 +74,8 @@ static size_t aegis128l_encrypt_final(ptls_aead_context_t *_ctx, void *output) struct aegis128l_context_t *ctx = (struct aegis128l_context_t *)_ctx; size_t written; - aegis128l_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis128l_TAILBYTES_MAX + PTLS_AEGIS128L_TAG_SIZE, &written, PTLS_AEGIS128L_TAG_SIZE); + aegis128l_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis128l_TAILBYTES_MAX + PTLS_AEGIS128L_TAG_SIZE, &written, + PTLS_AEGIS128L_TAG_SIZE); return written; } @@ -177,7 +179,8 @@ static size_t aegis256_encrypt_update(ptls_aead_context_t *_ctx, void *output, c struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; size_t written; - aegis256_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis256_TAILBYTES_MAX, &written, (const uint8_t *)input, inlen); + aegis256_state_encrypt_update(&ctx->st, (uint8_t *)output, inlen + aegis256_TAILBYTES_MAX, &written, (const uint8_t *)input, + inlen); return written; } @@ -187,7 +190,8 @@ static size_t aegis256_encrypt_final(ptls_aead_context_t *_ctx, void *output) struct aegis256_context_t *ctx = (struct aegis256_context_t *)_ctx; size_t written; - aegis256_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis256_TAILBYTES_MAX + PTLS_AEGIS256_TAG_SIZE, &written, PTLS_AEGIS256_TAG_SIZE); + aegis256_state_encrypt_final(&ctx->st, (uint8_t *)output, aegis256_TAILBYTES_MAX + PTLS_AEGIS256_TAG_SIZE, &written, + PTLS_AEGIS256_TAG_SIZE); return written; } diff --git a/lib/mbedtls_sign.c b/lib/mbedtls_sign.c index 1098686f3..2e167ae8f 100644 --- a/lib/mbedtls_sign.c +++ b/lib/mbedtls_sign.c @@ -1,24 +1,24 @@ /* -* Copyright (c) 2023, Christian Huitema -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ + * Copyright (c) 2023, Christian Huitema + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ #ifdef _WINDOWS #include "wincompat.h" @@ -47,30 +47,29 @@ typedef struct st_ptls_mbedtls_sign_certificate_t { ptls_sign_certificate_t super; mbedtls_svc_key_id_t key_id; psa_key_attributes_t attributes; - const ptls_mbedtls_signature_scheme_t * schemes; + const ptls_mbedtls_signature_scheme_t *schemes; } ptls_mbedtls_sign_certificate_t; -static const unsigned char ptls_mbedtls_oid_ec_key[] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 }; -static const unsigned char ptls_mbedtls_oid_rsa_key[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }; -static const unsigned char ptls_mbedtls_oid_ed25519[] = { 0x2b, 0x65, 0x70 }; +static const unsigned char ptls_mbedtls_oid_ec_key[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}; +static const unsigned char ptls_mbedtls_oid_rsa_key[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}; +static const unsigned char ptls_mbedtls_oid_ed25519[] = {0x2b, 0x65, 0x70}; -static const ptls_mbedtls_signature_scheme_t rsa_signature_schemes[] = { - {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, PSA_ALG_SHA_256}, - {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, PSA_ALG_SHA_384}, - {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, PSA_ALG_SHA_512}, - {UINT16_MAX, PSA_ALG_NONE}}; +static const ptls_mbedtls_signature_scheme_t rsa_signature_schemes[] = {{PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, PSA_ALG_SHA_256}, + {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, PSA_ALG_SHA_384}, + {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, PSA_ALG_SHA_512}, + {UINT16_MAX, PSA_ALG_NONE}}; static const ptls_mbedtls_signature_scheme_t secp256r1_signature_schemes[] = { {PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, PSA_ALG_SHA_256}, {UINT16_MAX, PSA_ALG_NONE}}; static const ptls_mbedtls_signature_scheme_t secp384r1_signature_schemes[] = { {PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, PSA_ALG_SHA_384}, {UINT16_MAX, PSA_ALG_NONE}}; static const ptls_mbedtls_signature_scheme_t secp521r1_signature_schemes[] = { {PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, PSA_ALG_SHA_512}, {UINT16_MAX, PSA_ALG_NONE}}; -static const ptls_mbedtls_signature_scheme_t ed25519_signature_schemes[] = { - {PTLS_SIGNATURE_ED25519, PSA_ALG_NONE}, {UINT16_MAX, PSA_ALG_NONE}}; +static const ptls_mbedtls_signature_scheme_t ed25519_signature_schemes[] = {{PTLS_SIGNATURE_ED25519, PSA_ALG_NONE}, + {UINT16_MAX, PSA_ALG_NONE}}; #if defined(MBEDTLS_PEM_PARSE_C) -static int ptls_mbedtls_parse_der_length(const unsigned char* pem_buf, size_t pem_len, size_t* px, size_t *pl) +static int ptls_mbedtls_parse_der_length(const unsigned char *pem_buf, size_t pem_len, size_t *px, size_t *pl) { int ret = 0; size_t x = *px; @@ -92,7 +91,7 @@ static int ptls_mbedtls_parse_der_length(const unsigned char* pem_buf, size_t pe return ret; } -static int ptls_mbedtls_parse_ecdsa_field(const unsigned char* pem_buf, size_t pem_len, size_t* key_index, size_t* key_length) +static int ptls_mbedtls_parse_ecdsa_field(const unsigned char *pem_buf, size_t pem_len, size_t *key_index, size_t *key_length) { int ret = 0; int param_index_index = -1; @@ -100,12 +99,9 @@ static int ptls_mbedtls_parse_ecdsa_field(const unsigned char* pem_buf, size_t p size_t x = 0; // const unsigned char head = { 0x30, l-2, 0x02, 0x01, 0x01, 0x04 } - if (pem_len < 16 || - pem_buf[x++] != 0x30 /* type = sequence */) - { + if (pem_len < 16 || pem_buf[x++] != 0x30 /* type = sequence */) { ret = -1; - } - else { + } else { size_t l = 0; ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l); @@ -113,15 +109,11 @@ static int ptls_mbedtls_parse_ecdsa_field(const unsigned char* pem_buf, size_t p ret = -1; } } - if (ret == 0){ - if (pem_buf[x++] != 0x02 /* type = int */ || - pem_buf[x++] != 0x01 /* length of int = 1 */ || - pem_buf[x++] != 0x01 /* version = 1 */ || - pem_buf[x++] != 0x04 /*octet string */ || - pem_buf[x] + x >= pem_len) { + if (ret == 0) { + if (pem_buf[x++] != 0x02 /* type = int */ || pem_buf[x++] != 0x01 /* length of int = 1 */ || + pem_buf[x++] != 0x01 /* version = 1 */ || pem_buf[x++] != 0x04 /*octet string */ || pem_buf[x] + x >= pem_len) { ret = -1; - } - else { + } else { *key_index = x + 1; *key_length = pem_buf[x]; x += 1 + pem_buf[x]; @@ -132,19 +124,16 @@ static int ptls_mbedtls_parse_ecdsa_field(const unsigned char* pem_buf, size_t p if (x + pem_buf[x] >= pem_len) { /* EC parameters extend beyond buffer */ ret = -1; - } - else { + } else { x += pem_buf[x] + 1; } } if (ret == 0 && x < pem_len) { /* skip the public key parameter */ - if (pem_buf[x++] != 0xa1 || - x >= pem_len) { + if (pem_buf[x++] != 0xa1 || x >= pem_len) { ret = -1; - } - else { + } else { size_t l = 0; ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l); x += l; @@ -160,12 +149,11 @@ static int ptls_mbedtls_parse_ecdsa_field(const unsigned char* pem_buf, size_t p } /* On input, key_index points at the "key information" in a -* "private key" message. For EDDSA, this contains an -* octet string carrying the key itself. On return, key index -* and key length are updated to point at the key field. -*/ -static int ptls_mbedtls_parse_eddsa_key(const unsigned char* pem_buf, size_t pem_len, - size_t* key_index, size_t* key_length) + * "private key" message. For EDDSA, this contains an + * octet string carrying the key itself. On return, key index + * and key length are updated to point at the key field. + */ +static int ptls_mbedtls_parse_eddsa_key(const unsigned char *pem_buf, size_t pem_len, size_t *key_index, size_t *key_length) { int ret = 0; size_t x = *key_index; @@ -177,8 +165,7 @@ static int ptls_mbedtls_parse_eddsa_key(const unsigned char* pem_buf, size_t pem ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_key); if (x + l_key != *key_index + *key_length) { ret = -1; - } - else { + } else { *key_index = x; *key_length = l_key; } @@ -187,12 +174,11 @@ static int ptls_mbedtls_parse_eddsa_key(const unsigned char* pem_buf, size_t pem } /* If using PKCS8 encoding, the "private key" field contains the -* same "ecdsa field" found in PEM "EC PRIVATE KEY" files. We -* use the same parser, but we need to reset indices so they -* reflect the unwrapped key. -*/ -int ptls_mbedtls_parse_ec_private_key(const unsigned char* pem_buf, size_t pem_len, - size_t* key_index, size_t* key_length) + * same "ecdsa field" found in PEM "EC PRIVATE KEY" files. We + * use the same parser, but we need to reset indices so they + * reflect the unwrapped key. + */ +int ptls_mbedtls_parse_ec_private_key(const unsigned char *pem_buf, size_t pem_len, size_t *key_index, size_t *key_length) { size_t x_offset = 0; size_t x_len = 0; @@ -205,9 +191,8 @@ int ptls_mbedtls_parse_ec_private_key(const unsigned char* pem_buf, size_t pem_l return ret; } -int test_parse_private_key_field(const unsigned char* pem_buf, size_t pem_len, - size_t* oid_index, size_t *oid_length, - size_t* key_index, size_t* key_length) +int test_parse_private_key_field(const unsigned char *pem_buf, size_t pem_len, size_t *oid_index, size_t *oid_length, + size_t *key_index, size_t *key_length) { int ret = 0; size_t l_oid = 0; @@ -217,12 +202,9 @@ int test_parse_private_key_field(const unsigned char* pem_buf, size_t pem_len, size_t x = 0; /* const unsigned char head = {0x30, l - 2, 0x02, 0x01, 0x00} */ - if (pem_len < 16 || - pem_buf[x++] != 0x30 /* type = sequence */) - { + if (pem_len < 16 || pem_buf[x++] != 0x30 /* type = sequence */) { ret = -1; - } - else { + } else { size_t l = 0; ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l); @@ -231,31 +213,25 @@ int test_parse_private_key_field(const unsigned char* pem_buf, size_t pem_len, } } if (ret == 0) { - if (pem_buf[x++] != 0x02 /* type = int */ || - pem_buf[x++] != 0x01 /* length of int = 1 */ || - pem_buf[x++] != 0x00 /* version = 0 */ || - pem_buf[x++] != 0x30 /* sequence */){ + if (pem_buf[x++] != 0x02 /* type = int */ || pem_buf[x++] != 0x01 /* length of int = 1 */ || + pem_buf[x++] != 0x00 /* version = 0 */ || pem_buf[x++] != 0x30 /* sequence */) { ret = -1; - } - else { + } else { /* the sequence contains the OID and optional key attributes, - * which we ignore for now. - */ + * which we ignore for now. + */ size_t l_seq = 0; size_t x_seq; ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_seq); x_seq = x; - if (x + l_seq >= pem_len || - pem_buf[x++] != 0x06) { + if (x + l_seq >= pem_len || pem_buf[x++] != 0x06) { ret = -1; - } - else { + } else { l_oid = pem_buf[x++]; x_oid = x; if (x + l_oid > x_seq + l_seq) { ret = -1; - } - else { + } else { x = x_seq + l_seq; } } @@ -263,14 +239,12 @@ int test_parse_private_key_field(const unsigned char* pem_buf, size_t pem_len, } if (ret == 0) { /* At that point the oid has been identified. - * The next parameter is an octet string containing the key info. - */ + * The next parameter is an octet string containing the key info. + */ size_t l = 0; - if (x + 2 > pem_len || - pem_buf[x++] != 0x04){ + if (x + 2 > pem_len || pem_buf[x++] != 0x04) { ret = -1; - } - else { + } else { ret = ptls_mbedtls_parse_der_length(pem_buf, pem_len, &x, &l_key); x_key = x; x += l_key; @@ -287,11 +261,8 @@ int test_parse_private_key_field(const unsigned char* pem_buf, size_t pem_len, return ret; } -int ptls_mbedtls_get_der_key(mbedtls_pem_context* pem, - mbedtls_pk_type_t * pk_type, - const unsigned char* key, size_t keylen, - const unsigned char* pwd, size_t pwdlen, - int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) +int ptls_mbedtls_get_der_key(mbedtls_pem_context *pem, mbedtls_pk_type_t *pk_type, const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PEM_PARSE_C) @@ -308,25 +279,19 @@ int ptls_mbedtls_get_der_key(mbedtls_pem_context* pem, /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } - else { - ret = mbedtls_pem_read_buffer(pem, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", - key, pwd, pwdlen, &len); + } else { + ret = mbedtls_pem_read_buffer(pem, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----", key, pwd, pwdlen, + &len); } if (ret == 0) { - * pk_type = MBEDTLS_PK_RSA; + *pk_type = MBEDTLS_PK_RSA; return ret; - } - else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; - } - else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; - } - else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_RSA_C */ @@ -335,24 +300,18 @@ int ptls_mbedtls_get_der_key(mbedtls_pem_context* pem, /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } - else { - ret = mbedtls_pem_read_buffer(pem, - "-----BEGIN EC PRIVATE KEY-----", - "-----END EC PRIVATE KEY-----", - key, pwd, pwdlen, &len); + } else { + ret = + mbedtls_pem_read_buffer(pem, "-----BEGIN EC PRIVATE KEY-----", "-----END EC PRIVATE KEY-----", key, pwd, pwdlen, &len); } if (ret == 0) { - * pk_type = MBEDTLS_PK_ECKEY; + *pk_type = MBEDTLS_PK_ECKEY; return ret; - } - else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; - } - else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; - } - else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ @@ -360,17 +319,12 @@ int ptls_mbedtls_get_der_key(mbedtls_pem_context* pem, /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } - else { - ret = mbedtls_pem_read_buffer(pem, - "-----BEGIN PRIVATE KEY-----", - "-----END PRIVATE KEY-----", - key, NULL, 0, &len); + } else { + ret = mbedtls_pem_read_buffer(pem, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----", key, NULL, 0, &len); if (ret == 0) { /* info is unknown */ return ret; - } - else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } } @@ -379,18 +333,14 @@ int ptls_mbedtls_get_der_key(mbedtls_pem_context* pem, /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } - else { - ret = mbedtls_pem_read_buffer(pem, - "-----BEGIN ENCRYPTED PRIVATE KEY-----", - "-----END ENCRYPTED PRIVATE KEY-----", - key, NULL, 0, &len); + } else { + ret = mbedtls_pem_read_buffer(pem, "-----BEGIN ENCRYPTED PRIVATE KEY-----", "-----END ENCRYPTED PRIVATE KEY-----", key, + NULL, 0, &len); } if (ret == 0) { /* infor is unknown */ return ret; - } - else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ @@ -398,11 +348,10 @@ int ptls_mbedtls_get_der_key(mbedtls_pem_context* pem, } #endif -const ptls_mbedtls_signature_scheme_t* ptls_mbedtls_select_signature_scheme( - const ptls_mbedtls_signature_scheme_t *available, - const uint16_t *algorithms, size_t num_algorithms) +const ptls_mbedtls_signature_scheme_t *ptls_mbedtls_select_signature_scheme(const ptls_mbedtls_signature_scheme_t *available, + const uint16_t *algorithms, size_t num_algorithms) { - const ptls_mbedtls_signature_scheme_t* scheme; + const ptls_mbedtls_signature_scheme_t *scheme; /* select the algorithm, driven by server-isde preference of `available` */ for (scheme = available; scheme->scheme_id != UINT16_MAX; ++scheme) { for (size_t i = 0; i != num_algorithms; ++i) { @@ -414,8 +363,7 @@ const ptls_mbedtls_signature_scheme_t* ptls_mbedtls_select_signature_scheme( return NULL; } -int ptls_mbedtls_set_available_schemes( - ptls_mbedtls_sign_certificate_t* signer) +int ptls_mbedtls_set_available_schemes(ptls_mbedtls_sign_certificate_t *signer) { int ret = 0; psa_algorithm_t algo = psa_get_key_algorithm(&signer->attributes); @@ -463,54 +411,51 @@ int ptls_mbedtls_set_available_schemes( } /* -* Sign a certificate -* - step1, selected a signature algorithm compatible with the public key algorithm -* and with the list specified by the application. -* - step2, compute the hash with the specified algorithm. -* - step3, compute the signature of the hash using psa_sign_hash. -* -* In the case of RSA, we use the algorithm PSA_ALG_RSA_PKCS1V15_SIGN_RAW, which -* pads the hash according to PKCS1V15 before doing the private key operation. -* The implementation of RSA/PKCS1V15 also includes a verification step to protect -* against key attacks through partial faults. -* -* MBEDTLS has a "psa_sign_message" that combines step2 and step3. However, it -* requires specifying an algorithm type that exactly specifies the signature -* algorithm, such as "RSA with SHA384". This is not compatible with the -* "RSA sign raw" algorithm. Instead, we decompose the operation in two steps. -* There is no performance penalty doing so, as "psa_sign_message" is only -* a convenience API. -*/ - -int ptls_mbedtls_sign_certificate(ptls_sign_certificate_t* _self, ptls_t* tls, - ptls_async_job_t** async, uint16_t* selected_algorithm, - ptls_buffer_t* outbuf, ptls_iovec_t input, const uint16_t* algorithms, size_t num_algorithms) + * Sign a certificate + * - step1, selected a signature algorithm compatible with the public key algorithm + * and with the list specified by the application. + * - step2, compute the hash with the specified algorithm. + * - step3, compute the signature of the hash using psa_sign_hash. + * + * In the case of RSA, we use the algorithm PSA_ALG_RSA_PKCS1V15_SIGN_RAW, which + * pads the hash according to PKCS1V15 before doing the private key operation. + * The implementation of RSA/PKCS1V15 also includes a verification step to protect + * against key attacks through partial faults. + * + * MBEDTLS has a "psa_sign_message" that combines step2 and step3. However, it + * requires specifying an algorithm type that exactly specifies the signature + * algorithm, such as "RSA with SHA384". This is not compatible with the + * "RSA sign raw" algorithm. Instead, we decompose the operation in two steps. + * There is no performance penalty doing so, as "psa_sign_message" is only + * a convenience API. + */ + +int ptls_mbedtls_sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, ptls_async_job_t **async, + uint16_t *selected_algorithm, ptls_buffer_t *outbuf, ptls_iovec_t input, + const uint16_t *algorithms, size_t num_algorithms) { int ret = 0; - ptls_mbedtls_sign_certificate_t* self = (ptls_mbedtls_sign_certificate_t*) - (((unsigned char*)_self) - offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); + ptls_mbedtls_sign_certificate_t *self = + (ptls_mbedtls_sign_certificate_t *)(((unsigned char *)_self) - offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); /* First, find the set of compatible algorithms */ - const ptls_mbedtls_signature_scheme_t* scheme = - ptls_mbedtls_select_signature_scheme(self->schemes, algorithms, num_algorithms); + const ptls_mbedtls_signature_scheme_t *scheme = ptls_mbedtls_select_signature_scheme(self->schemes, algorithms, num_algorithms); if (scheme == NULL) { ret = PTLS_ERROR_INCOMPATIBLE_KEY; - } - else { + } else { /* First prepare the hash */ unsigned char hash_buffer[PTLS_MAX_DIGEST_SIZE]; - unsigned char* hash_value = NULL; + unsigned char *hash_value = NULL; size_t hash_length = 0; if (scheme->hash_algo == PSA_ALG_NONE) { hash_value = input.base; hash_length = input.len; - } - else { - if (psa_hash_compute(scheme->hash_algo, input.base, input.len, hash_buffer, PTLS_MAX_DIGEST_SIZE, &hash_length) != PSA_SUCCESS) { + } else { + if (psa_hash_compute(scheme->hash_algo, input.base, input.len, hash_buffer, PTLS_MAX_DIGEST_SIZE, &hash_length) != + PSA_SUCCESS) { ret = PTLS_ERROR_NOT_AVAILABLE; - } - else { + } else { hash_value = hash_buffer; } } @@ -522,8 +467,7 @@ int ptls_mbedtls_sign_certificate(ptls_sign_certificate_t* _self, ptls_t* tls, if (sign_algo == PSA_ALG_RSA_PKCS1V15_SIGN_RAW) { /* assume at most 4096 bit key */ nb_bytes = 512; - } - else { + } else { /* Max size assumed, secp521r1 */ nb_bytes = 124; } @@ -533,11 +477,10 @@ int ptls_mbedtls_sign_certificate(ptls_sign_certificate_t* _self, ptls_t* tls, if ((ret = ptls_buffer_reserve(outbuf, nb_bytes)) == 0) { size_t signature_length = 0; - if (psa_sign_hash(self->key_id, sign_algo, hash_value, hash_length, - outbuf->base + outbuf->off, nb_bytes, &signature_length) != 0) { + if (psa_sign_hash(self->key_id, sign_algo, hash_value, hash_length, outbuf->base + outbuf->off, nb_bytes, + &signature_length) != 0) { ret = PTLS_ERROR_INCOMPATIBLE_KEY; - } - else { + } else { outbuf->off += signature_length; } } @@ -549,8 +492,9 @@ int ptls_mbedtls_sign_certificate(ptls_sign_certificate_t* _self, ptls_t* tls, void ptls_mbedtls_dispose_sign_certificate(ptls_sign_certificate_t *_self) { if (_self != NULL) { - ptls_mbedtls_sign_certificate_t* self = (ptls_mbedtls_sign_certificate_t*) - (((unsigned char*)_self) - offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); + ptls_mbedtls_sign_certificate_t *self = + (ptls_mbedtls_sign_certificate_t *)(((unsigned char *)_self) - + offsetof(struct st_ptls_mbedtls_sign_certificate_t, super)); /* Destroy the key */ psa_destroy_key(self->key_id); psa_reset_key_attributes(&self->attributes); @@ -559,24 +503,24 @@ void ptls_mbedtls_dispose_sign_certificate(ptls_sign_certificate_t *_self) } } /* -* An RSa key is encoded in DER as: -* RSAPrivateKey ::= SEQUENCE { -* version INTEGER, -- must be 0 -* modulus INTEGER, -- n -* publicExponent INTEGER, -- e -* privateExponent INTEGER, -- d -* prime1 INTEGER, -- p -* prime2 INTEGER, -- q -* exponent1 INTEGER, -- d mod (p-1) -* exponent2 INTEGER, -- d mod (q-1) -* coefficient INTEGER, -- (inverse of q) mod p -* } -* -* The number of key bits is the size in bits of the integer N. -* We must decode the length in octets of the integer representation, -* then subtract the number of zeros at the beginning of the data. -*/ -int ptls_mbedtls_rsa_get_key_bits(const unsigned char* key_value, size_t key_length, size_t * p_nb_bits) + * An RSa key is encoded in DER as: + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * + * The number of key bits is the size in bits of the integer N. + * We must decode the length in octets of the integer representation, + * then subtract the number of zeros at the beginning of the data. + */ +int ptls_mbedtls_rsa_get_key_bits(const unsigned char *key_value, size_t key_length, size_t *p_nb_bits) { int ret = 0; size_t nb_bytes = 0; @@ -593,15 +537,10 @@ int ptls_mbedtls_rsa_get_key_bits(const unsigned char* key_value, size_t key_len } } - if (ret == 0 && - key_value[x] == 0x02 && - key_value[x + 1] == 0x01 && - key_value[x + 2] == 0x00 && - key_value[x + 3] == 0x02) { + if (ret == 0 && key_value[x] == 0x02 && key_value[x + 1] == 0x01 && key_value[x + 2] == 0x00 && key_value[x + 3] == 0x02) { x += 4; ret = ptls_mbedtls_parse_der_length(key_value, key_length, &x, &nb_bytes); - } - else { + } else { ret = -1; } @@ -611,8 +550,7 @@ int ptls_mbedtls_rsa_get_key_bits(const unsigned char* key_value, size_t key_len if (v == 0) { nb_bits -= 8; - } - else { + } else { while ((v & 0x80) == 0) { nb_bits--; v <<= 1; @@ -623,8 +561,7 @@ int ptls_mbedtls_rsa_get_key_bits(const unsigned char* key_value, size_t key_len return ret; } -void ptls_mbedtls_set_rsa_key_attributes(ptls_mbedtls_sign_certificate_t* signer, - const unsigned char * key_value, size_t key_length) +void ptls_mbedtls_set_rsa_key_attributes(ptls_mbedtls_sign_certificate_t *signer, const unsigned char *key_value, size_t key_length) { size_t nb_bits = 0; psa_set_key_usage_flags(&signer->attributes, PSA_KEY_USAGE_SIGN_HASH); @@ -635,7 +572,7 @@ void ptls_mbedtls_set_rsa_key_attributes(ptls_mbedtls_sign_certificate_t* signer } } -int ptls_mbedtls_set_ec_key_attributes(ptls_mbedtls_sign_certificate_t* signer, size_t key_length) +int ptls_mbedtls_set_ec_key_attributes(ptls_mbedtls_sign_certificate_t *signer, size_t key_length) { int ret = 0; @@ -643,52 +580,44 @@ int ptls_mbedtls_set_ec_key_attributes(ptls_mbedtls_sign_certificate_t* signer, psa_set_key_algorithm(&signer->attributes, PSA_ALG_ECDSA_BASE); psa_set_key_type(&signer->attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); if (key_length == 32) { - psa_set_key_algorithm(&signer->attributes, - PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_algorithm(&signer->attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); psa_set_key_bits(&signer->attributes, 256); - } - else if (key_length == 48) { - psa_set_key_algorithm(&signer->attributes, - PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384)); + } else if (key_length == 48) { + psa_set_key_algorithm(&signer->attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384)); psa_set_key_bits(&signer->attributes, 384); - } - else if (key_length == 66) { - psa_set_key_algorithm(&signer->attributes, - PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512)); + } else if (key_length == 66) { + psa_set_key_algorithm(&signer->attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512)); psa_set_key_bits(&signer->attributes, 521); - } - else { + } else { ret = -1; } return ret; } - -int ptls_mbedtls_load_private_key(ptls_context_t* ctx, char const* pem_fname) +int ptls_mbedtls_load_private_key(ptls_context_t *ctx, char const *pem_fname) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; - unsigned char* buf; - mbedtls_pem_context pem = { 0 }; + unsigned char *buf; + mbedtls_pem_context pem = {0}; mbedtls_pk_type_t pk_type = 0; mbedtls_svc_key_id_t key_id = 0; size_t key_length = 0; size_t key_index = 0; - ptls_mbedtls_sign_certificate_t* signer = (ptls_mbedtls_sign_certificate_t*)malloc(sizeof(ptls_mbedtls_sign_certificate_t)); + ptls_mbedtls_sign_certificate_t *signer = (ptls_mbedtls_sign_certificate_t *)malloc(sizeof(ptls_mbedtls_sign_certificate_t)); if (signer == NULL) { - return(PTLS_ERROR_NO_MEMORY); + return (PTLS_ERROR_NO_MEMORY); } memset(signer, 0, sizeof(ptls_mbedtls_sign_certificate_t)); signer->attributes = psa_key_attributes_init(); if ((ret = mbedtls_pk_load_file(pem_fname, &buf, &n)) != 0) { if (ret == MBEDTLS_ERR_PK_ALLOC_FAILED) { - return(PTLS_ERROR_NO_MEMORY); - } - else { - return(PTLS_ERROR_NOT_AVAILABLE); + return (PTLS_ERROR_NO_MEMORY); + } else { + return (PTLS_ERROR_NOT_AVAILABLE); } } ret = ptls_mbedtls_get_der_key(&pem, &pk_type, buf, n, NULL, 0, NULL, NULL); @@ -704,21 +633,20 @@ int ptls_mbedtls_load_private_key(ptls_context_t* ctx, char const* pem_fname) if (pk_type == MBEDTLS_PK_RSA) { key_length = pem.private_buflen; ptls_mbedtls_set_rsa_key_attributes(signer, pem.private_buf, key_length); - } - else if (pk_type == MBEDTLS_PK_ECKEY) { + } else if (pk_type == MBEDTLS_PK_ECKEY) { ret = ptls_mbedtls_parse_ecdsa_field(pem.private_buf, pem.private_buflen, &key_index, &key_length); if (ret == 0) { ret = ptls_mbedtls_set_ec_key_attributes(signer, key_length); } - } - else if (pk_type == MBEDTLS_PK_NONE) { + } else if (pk_type == MBEDTLS_PK_NONE) { /* TODO: not clear whether MBDED TLS supports ED25519 yet. Probably not. */ /* Should have option to encode RSA or ECDSA using PKCS8 */ size_t oid_index = 0; size_t oid_length = 0; psa_set_key_usage_flags(&signer->attributes, PSA_KEY_USAGE_SIGN_HASH); - ret = test_parse_private_key_field(pem.private_buf, pem.private_buflen, &oid_index, &oid_length, &key_index, &key_length); + ret = + test_parse_private_key_field(pem.private_buf, pem.private_buflen, &oid_index, &oid_length, &key_index, &key_length); if (ret == 0) { /* need to parse the OID in order to set the parameters */ @@ -728,27 +656,23 @@ int ptls_mbedtls_load_private_key(ptls_context_t* ctx, char const* pem_fname) if (ret == 0) { ret = ptls_mbedtls_set_ec_key_attributes(signer, key_length); } - } - else if (oid_length == sizeof(ptls_mbedtls_oid_ed25519) && - memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_ed25519, sizeof(ptls_mbedtls_oid_ed25519)) == 0) { + } else if (oid_length == sizeof(ptls_mbedtls_oid_ed25519) && + memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_ed25519, sizeof(ptls_mbedtls_oid_ed25519)) == 0) { /* We recognized ED25519 -- PSA_ECC_FAMILY_TWISTED_EDWARDS -- PSA_ALG_ED25519PH */ psa_set_key_algorithm(&signer->attributes, PSA_ALG_PURE_EDDSA); psa_set_key_type(&signer->attributes, PSA_ECC_FAMILY_TWISTED_EDWARDS); ret = ptls_mbedtls_parse_eddsa_key(pem.private_buf, pem.private_buflen, &key_index, &key_length); psa_set_key_bits(&signer->attributes, 256); - } - else if (oid_length == sizeof(ptls_mbedtls_oid_rsa_key) && - memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_rsa_key, sizeof(ptls_mbedtls_oid_rsa_key)) == 0) { + } else if (oid_length == sizeof(ptls_mbedtls_oid_rsa_key) && + memcmp(pem.private_buf + oid_index, ptls_mbedtls_oid_rsa_key, sizeof(ptls_mbedtls_oid_rsa_key)) == 0) { /* We recognized RSA */ key_length = pem.private_buflen; ptls_mbedtls_set_rsa_key_attributes(signer, pem.private_buf, key_length); - } - else { + } else { ret = PTLS_ERROR_NOT_AVAILABLE; } } - } - else { + } else { ret = -1; } @@ -758,8 +682,7 @@ int ptls_mbedtls_load_private_key(ptls_context_t* ctx, char const* pem_fname) if (status != PSA_SUCCESS) { ret = -1; - } - else { + } else { ret = ptls_mbedtls_set_available_schemes(signer); } } diff --git a/lib/openssl.c b/lib/openssl.c index 70a3e7e9a..8ca5a6c53 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -101,22 +101,21 @@ static int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) #endif static const ptls_openssl_signature_scheme_t rsa_signature_schemes[] = {{PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, EVP_sha256}, - {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, EVP_sha384}, - {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, EVP_sha512}, - {UINT16_MAX, NULL}}; -static const ptls_openssl_signature_scheme_t secp256r1_signature_schemes[] = { - {PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, EVP_sha256}, {UINT16_MAX, NULL}}; + {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, EVP_sha384}, + {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, EVP_sha512}, + {UINT16_MAX, NULL}}; +static const ptls_openssl_signature_scheme_t secp256r1_signature_schemes[] = {{PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, EVP_sha256}, + {UINT16_MAX, NULL}}; #if PTLS_OPENSSL_HAVE_SECP384R1 -static const ptls_openssl_signature_scheme_t secp384r1_signature_schemes[] = { - {PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, EVP_sha384}, {UINT16_MAX, NULL}}; +static const ptls_openssl_signature_scheme_t secp384r1_signature_schemes[] = {{PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, EVP_sha384}, + {UINT16_MAX, NULL}}; #endif #if PTLS_OPENSSL_HAVE_SECP521R1 -static const ptls_openssl_signature_scheme_t secp521r1_signature_schemes[] = { - {PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, EVP_sha512}, {UINT16_MAX, NULL}}; +static const ptls_openssl_signature_scheme_t secp521r1_signature_schemes[] = {{PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, EVP_sha512}, + {UINT16_MAX, NULL}}; #endif #if PTLS_OPENSSL_HAVE_ED25519 -static const ptls_openssl_signature_scheme_t ed25519_signature_schemes[] = {{PTLS_SIGNATURE_ED25519, NULL}, - {UINT16_MAX, NULL}}; +static const ptls_openssl_signature_scheme_t ed25519_signature_schemes[] = {{PTLS_SIGNATURE_ED25519, NULL}, {UINT16_MAX, NULL}}; #endif /** @@ -854,8 +853,8 @@ static int do_sign_async(ptls_buffer_t *outbuf, ptls_async_job_t **_async) #endif -static int do_sign(EVP_PKEY *key, const ptls_openssl_signature_scheme_t *scheme, ptls_buffer_t *outbuf, - ptls_iovec_t input, ptls_async_job_t **async) +static int do_sign(EVP_PKEY *key, const ptls_openssl_signature_scheme_t *scheme, ptls_buffer_t *outbuf, ptls_iovec_t input, + ptls_async_job_t **async) { EVP_MD_CTX *ctx = NULL; const EVP_MD *md = scheme->scheme_md != NULL ? scheme->scheme_md() : NULL; @@ -2183,7 +2182,6 @@ ptls_cipher_suite_t ptls_openssl_tls12_ecdhe_ecdsa_chacha20poly1305sha256 = { .hash = &ptls_openssl_sha256}; #endif - #if PTLS_HAVE_AEGIS ptls_aead_algorithm_t ptls_openssl_aegis128l = { .name = "AEGIS-128L", @@ -2194,7 +2192,7 @@ ptls_aead_algorithm_t ptls_openssl_aegis128l = { .key_size = PTLS_AEGIS128L_KEY_SIZE, .iv_size = PTLS_AEGIS128L_IV_SIZE, .tag_size = PTLS_AEGIS128L_TAG_SIZE, - .tls12 = { .fixed_iv_size = 0, .record_iv_size = 0 }, + .tls12 = {.fixed_iv_size = 0, .record_iv_size = 0}, .non_temporal = 0, .align_bits = 0, .context_size = sizeof(struct aegis128l_context_t), @@ -2214,45 +2212,43 @@ ptls_aead_algorithm_t ptls_openssl_aegis256 = { .key_size = PTLS_AEGIS256_KEY_SIZE, .iv_size = PTLS_AEGIS256_IV_SIZE, .tag_size = PTLS_AEGIS256_TAG_SIZE, - .tls12 = { .fixed_iv_size = 0, .record_iv_size = 0 }, + .tls12 = {.fixed_iv_size = 0, .record_iv_size = 0}, .non_temporal = 0, .align_bits = 0, .context_size = sizeof(struct aegis256_context_t), .setup_crypto = aegis256_setup_crypto, }; ptls_cipher_suite_t ptls_openssl_aegis256sha512 = {.id = PTLS_CIPHER_SUITE_AEGIS256_SHA512, - .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512, - .aead = &ptls_openssl_aegis256, - .hash = &ptls_openssl_sha512}; + .name = PTLS_CIPHER_SUITE_NAME_AEGIS256_SHA512, + .aead = &ptls_openssl_aegis256, + .hash = &ptls_openssl_sha512}; #endif +ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = { // ciphers used with sha384 (must be first) + &ptls_openssl_aes256gcmsha384, - -ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = {// ciphers used with sha384 (must be first) - &ptls_openssl_aes256gcmsha384, - - // ciphers used with sha256 - &ptls_openssl_aes128gcmsha256, + // ciphers used with sha256 + &ptls_openssl_aes128gcmsha256, #if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 - &ptls_openssl_chacha20poly1305sha256, + &ptls_openssl_chacha20poly1305sha256, #endif - NULL}; + NULL}; -ptls_cipher_suite_t *ptls_openssl_cipher_suites_all[] = {// ciphers used with sha384 (must be first) +ptls_cipher_suite_t *ptls_openssl_cipher_suites_all[] = { // ciphers used with sha384 (must be first) #if PTLS_HAVE_AEGIS - &ptls_openssl_aegis256sha512, + &ptls_openssl_aegis256sha512, #endif - &ptls_openssl_aes256gcmsha384, + &ptls_openssl_aes256gcmsha384, - // ciphers used with sha256 +// ciphers used with sha256 #if PTLS_HAVE_AEGIS - &ptls_openssl_aegis128lsha256, + &ptls_openssl_aegis128lsha256, #endif - &ptls_openssl_aes128gcmsha256, + &ptls_openssl_aes128gcmsha256, #if PTLS_OPENSSL_HAVE_CHACHA20_POLY1305 - &ptls_openssl_chacha20poly1305sha256, + &ptls_openssl_chacha20poly1305sha256, #endif - NULL}; + NULL}; ptls_cipher_suite_t *ptls_openssl_tls12_cipher_suites[] = {&ptls_openssl_tls12_ecdhe_rsa_aes128gcmsha256, &ptls_openssl_tls12_ecdhe_ecdsa_aes128gcmsha256, diff --git a/lib/picotls.c b/lib/picotls.c index 7f8fd9ae3..c73c2dc2c 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -4371,8 +4371,9 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl { /* select (or check) cipher-suite, create key_schedule */ ptls_cipher_suite_t *cs; - if ((ret = select_cipher(&cs, tls->ctx->cipher_suites, ch->cipher_suites.base, - ch->cipher_suites.base + ch->cipher_suites.len, tls->ctx->server_cipher_preference, tls->ctx->server_cipher_chacha_priority)) != 0) + if ((ret = + select_cipher(&cs, tls->ctx->cipher_suites, ch->cipher_suites.base, ch->cipher_suites.base + ch->cipher_suites.len, + tls->ctx->server_cipher_preference, tls->ctx->server_cipher_chacha_priority)) != 0) goto Exit; if (!is_second_flight) { tls->cipher_suite = cs; diff --git a/t/picotls.c b/t/picotls.c index 8bc5ab444..013783329 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -87,7 +87,8 @@ static void test_select_cipher(void) } { - ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, NULL}; + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes128gcmsha256, &ptls_minicrypto_aes256gcmsha384, + &ptls_minicrypto_chacha20poly1305sha256, NULL}; static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256)}; ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0); ok(selected == &ptls_minicrypto_aes128gcmsha256); @@ -96,8 +97,10 @@ static void test_select_cipher(void) } { - ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL}; - static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, + &ptls_minicrypto_aes128gcmsha256, NULL}; + static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), + C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0); ok(selected == &ptls_minicrypto_aes256gcmsha384); ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); @@ -107,8 +110,10 @@ static void test_select_cipher(void) } { - ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, &ptls_minicrypto_aes128gcmsha256, NULL}; - static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; + ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_chacha20poly1305sha256, + &ptls_minicrypto_aes128gcmsha256, NULL}; + static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), + C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); ok(selected == &ptls_minicrypto_aes256gcmsha384); ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); @@ -117,7 +122,8 @@ static void test_select_cipher(void) { ptls_cipher_suite_t *candidates[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_aes128gcmsha256, NULL}; - static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; + static const uint8_t input[] = {C(PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), C(PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), + C(PTLS_CIPHER_SUITE_AES_256_GCM_SHA384)}; ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 0) == 0); ok(selected == &ptls_minicrypto_aes256gcmsha384); ok(select_cipher(&selected, candidates, input, input + sizeof(input), 1, 1) == 0); From a1a35596b88d1391602c368975b2b7511a0a32ea Mon Sep 17 00:00:00 2001 From: Roberto Guimaraes Date: Fri, 23 Feb 2024 18:54:25 -0700 Subject: [PATCH 129/151] adds support for ptls_import() and ptls_export() TLSv1.3 essentially adding the ability to transfer the traffic secrets from one tls structure to another newly created one. This also adds adds a ptls_dupe test function for t/picotls.c which simulates the usage of import/export in different code paths and handshake types. --- lib/picotls.c | 123 ++++++++++++++++++++++++++++++++++++++------------ t/picotls.c | 115 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 190 insertions(+), 48 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index c73c2dc2c..e05a7c638 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -1615,7 +1615,7 @@ static int get_traffic_keys(ptls_aead_algorithm_t *aead, ptls_hash_algorithm_t * return ret; } -static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, int skip_notify) +static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, int skip_notify, int seq) { static const char *log_labels[2][4] = { {NULL, "CLIENT_EARLY_TRAFFIC_SECRET", "CLIENT_HANDSHAKE_TRAFFIC_SECRET", "CLIENT_TRAFFIC_SECRET_0"}, @@ -1630,8 +1630,9 @@ static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_ ctx->epoch = epoch; - log_secret(tls, log_labels[ptls_is_server(tls) == is_enc][epoch], - ptls_iovec_init(ctx->secret, tls->key_schedule->hashes[0].algo->digest_size)); + if (tls->key_schedule) + log_secret(tls, log_labels[ptls_is_server(tls) == is_enc][epoch], + ptls_iovec_init(ctx->secret, tls->key_schedule->hashes[0].algo->digest_size)); /* special path for applications having their own record layer */ if (tls->ctx->update_traffic_key != NULL) { @@ -1645,7 +1646,7 @@ static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_ if ((ctx->aead = ptls_aead_new(tls->cipher_suite->aead, tls->cipher_suite->hash, is_enc, ctx->secret, tls->ctx->hkdf_label_prefix__obsolete)) == NULL) return PTLS_ERROR_NO_MEMORY; /* TODO obtain error from ptls_aead_new */ - ctx->seq = 0; + ctx->seq = seq; PTLS_DEBUGF("[%s] %02x%02x,%02x%02x\n", log_labels[ptls_is_server(tls)][epoch], (unsigned)ctx->secret[0], (unsigned)ctx->secret[1], (unsigned)ctx->aead->static_iv[0], (unsigned)ctx->aead->static_iv[1]); @@ -1664,7 +1665,7 @@ static int commission_handshake_secret(ptls_t *tls) free(tls->pending_handshake_secret); tls->pending_handshake_secret = NULL; - return setup_traffic_protection(tls, is_enc, NULL, 2, 1); + return setup_traffic_protection(tls, is_enc, NULL, 2, 1, 0); } static void log_client_random(ptls_t *tls) @@ -2479,7 +2480,7 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ if (tls->client.using_early_data) { assert(!is_second_flight); - if ((ret = setup_traffic_protection(tls, 1, "c e traffic", 1, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 1, "c e traffic", 1, 0, 0)) != 0) goto Exit; if ((ret = push_change_cipher_spec(tls, emitter)) != 0) goto Exit; @@ -2795,7 +2796,7 @@ static int client_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl if ((ret = key_schedule_extract(tls->key_schedule, ecdh_secret)) != 0) goto Exit; - if ((ret = setup_traffic_protection(tls, 0, "s hs traffic", 2, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 0, "s hs traffic", 2, 0, 0)) != 0) goto Exit; if (tls->client.using_early_data) { if ((tls->pending_handshake_secret = malloc(PTLS_MAX_DIGEST_SIZE)) == NULL) { @@ -2808,7 +2809,7 @@ static int client_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl (ret = tls->ctx->update_traffic_key->cb(tls->ctx->update_traffic_key, tls, 1, 2, tls->pending_handshake_secret)) != 0) goto Exit; } else { - if ((ret = setup_traffic_protection(tls, 1, "c hs traffic", 2, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 1, "c hs traffic", 2, 0, 0)) != 0) goto Exit; } @@ -3373,7 +3374,7 @@ static int client_handle_finished(ptls_t *tls, ptls_message_emitter_t *emitter, /* update traffic keys by using messages upto ServerFinished, but commission them after sending ClientFinished */ if ((ret = key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0))) != 0) goto Exit; - if ((ret = setup_traffic_protection(tls, 0, "s ap traffic", 3, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 0, "s ap traffic", 3, 0, 0)) != 0) goto Exit; if ((ret = derive_secret(tls->key_schedule, send_secret, "c ap traffic")) != 0) goto Exit; @@ -3407,7 +3408,7 @@ static int client_handle_finished(ptls_t *tls, ptls_message_emitter_t *emitter, ret = send_finished(tls, emitter); memcpy(tls->traffic_protection.enc.secret, send_secret, sizeof(send_secret)); - if ((ret = setup_traffic_protection(tls, 1, NULL, 3, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 1, NULL, 3, 0, 0)) != 0) goto Exit; tls->state = PTLS_STATE_CLIENT_POST_HANDSHAKE; @@ -4572,7 +4573,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl } if ((ret = derive_exporter_secret(tls, 1)) != 0) goto Exit; - if ((ret = setup_traffic_protection(tls, 0, "c e traffic", 1, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 0, "c e traffic", 1, 0, 0)) != 0) goto Exit; } @@ -4631,7 +4632,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl /* create protection contexts for the handshake */ assert(tls->key_schedule->generation == 1); key_schedule_extract(tls->key_schedule, ecdh_secret); - if ((ret = setup_traffic_protection(tls, 1, "s hs traffic", 2, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 1, "s hs traffic", 2, 0, 0)) != 0) goto Exit; if (tls->pending_handshake_secret != NULL) { if ((ret = derive_secret(tls->key_schedule, tls->pending_handshake_secret, "c hs traffic")) != 0) @@ -4640,7 +4641,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl (ret = tls->ctx->update_traffic_key->cb(tls->ctx->update_traffic_key, tls, 0, 2, tls->pending_handshake_secret)) != 0) goto Exit; } else { - if ((ret = setup_traffic_protection(tls, 0, "c hs traffic", 2, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 0, "c hs traffic", 2, 0, 0)) != 0) goto Exit; if (ch->psk.early_data_indication) tls->server.early_data_skipped_bytes = 0; @@ -4766,7 +4767,7 @@ static int server_finish_handshake(ptls_t *tls, ptls_message_emitter_t *emitter, assert(tls->key_schedule->generation == 2); if ((ret = key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0))) != 0) goto Exit; - if ((ret = setup_traffic_protection(tls, 1, "s ap traffic", 3, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 1, "s ap traffic", 3, 0, 0)) != 0) goto Exit; if ((ret = derive_secret(tls->key_schedule, tls->server.pending_traffic_secret, "c ap traffic")) != 0) goto Exit; @@ -4827,7 +4828,7 @@ static int server_handle_finished(ptls_t *tls, ptls_iovec_t message) memcpy(tls->traffic_protection.dec.secret, tls->server.pending_traffic_secret, sizeof(tls->server.pending_traffic_secret)); ptls_clear_memory(tls->server.pending_traffic_secret, sizeof(tls->server.pending_traffic_secret)); - if ((ret = setup_traffic_protection(tls, 0, NULL, 3, 0)) != 0) + if ((ret = setup_traffic_protection(tls, 0, NULL, 3, 0, 0)) != 0) return ret; ptls__key_schedule_update_hash(tls->key_schedule, message.base, message.len, 0); @@ -4847,7 +4848,7 @@ static int update_traffic_key(ptls_t *tls, int is_enc) "traffic upd", ptls_iovec_init(NULL, 0), NULL)) != 0) goto Exit; memcpy(tp->secret, secret, sizeof(secret)); - ret = setup_traffic_protection(tls, is_enc, NULL, 3, 1); + ret = setup_traffic_protection(tls, is_enc, NULL, 3, 1, 0); Exit: ptls_clear_memory(secret, sizeof(secret)); @@ -5017,6 +5018,36 @@ ptls_t *ptls_server_new(ptls_context_t *ctx) return tls; } +static int export_tls13_params(ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher, + const void *client_random, const char *server_name, ptls_iovec_t negotiated_protocol, + const void *enc_key, uint64_t enc_seq, const void *dec_key, uint64_t dec_seq) +{ + int ret; + + ptls_buffer_push_block(output, 2, { + ptls_buffer_push(output, is_server); + ptls_buffer_push(output, session_reused); + ptls_buffer_push16(output, PTLS_PROTOCOL_VERSION_TLS13); + ptls_buffer_push16(output, cipher->id); + ptls_buffer_pushv(output, client_random, PTLS_HELLO_RANDOM_SIZE); + ptls_buffer_push_block(output, 2, { + size_t len = server_name != NULL ? strlen(server_name) : 0; + ptls_buffer_pushv(output, server_name, len); + }); + ptls_buffer_push_block(output, 2, { ptls_buffer_pushv(output, negotiated_protocol.base, negotiated_protocol.len); }); + ptls_buffer_push_block(output, 2, { + ptls_buffer_pushv(output, enc_key, cipher->hash->digest_size); + ptls_buffer_push64(output, enc_seq); + ptls_buffer_pushv(output, dec_key, cipher->hash->digest_size); + ptls_buffer_push64(output, dec_seq); + }); + ptls_buffer_push_block(output, 2, {}); /* for future extensions */ + }); + +Exit: + return ret; +} + static int export_tls12_params(ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher, const void *client_random, const char *server_name, ptls_iovec_t negotiated_protocol, const void *enc_key, const void *enc_iv, uint64_t enc_seq, uint64_t enc_record_iv, @@ -5094,17 +5125,21 @@ int ptls_build_tls12_export_params(ptls_context_t *ctx, ptls_buffer_t *output, i int ptls_export(ptls_t *tls, ptls_buffer_t *output) { - /* TODO add tls13 support */ - if (!tls->traffic_protection.enc.tls12) - return PTLS_ERROR_LIBRARY; - ptls_iovec_t negotiated_protocol = ptls_iovec_init(tls->negotiated_protocol, tls->negotiated_protocol != NULL ? strlen(tls->negotiated_protocol) : 0); - return export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, + if (ptls_get_protocol_version(tls) == PTLS_PROTOCOL_VERSION_TLS13) { + if (tls->state != PTLS_STATE_SERVER_POST_HANDSHAKE) + return PTLS_ERROR_LIBRARY; + return export_tls13_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, + tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, tls->traffic_protection.enc.seq, + tls->traffic_protection.dec.secret, tls->traffic_protection.dec.seq); + } else { + return export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq, tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret, tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.dec.seq); + } } static int build_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end) @@ -5134,6 +5169,23 @@ static int build_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t return 0; } +static int build_tls13_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end) +{ + struct st_ptls_traffic_protection_t *tp = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec; + + /* set properties */ + memcpy(tp->secret, *src, tls->cipher_suite->hash->digest_size); + *src += tls->cipher_suite->hash->digest_size; + if (ptls_decode64(&tp->seq, src, end) != 0) + return PTLS_ALERT_DECODE_ERROR; + + int skip_notify = is_enc ? 1 : 0; + if (setup_traffic_protection(tls, is_enc, NULL, 3, skip_notify, tp->seq) != 0) + return PTLS_ERROR_INCOMPATIBLE_KEY; + + return 0; +} + int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) { const uint8_t *src = params.base, *const end = src + params.len; @@ -5159,11 +5211,6 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) goto Exit; if ((ret = ptls_decode16(&csid, &src, end)) != 0) goto Exit; - (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->tls12_cipher_suites, csid); - if ((*tls)->cipher_suite == NULL) { - ret = PTLS_ALERT_HANDSHAKE_FAILURE; - goto Exit; - } /* other version-independent stuff */ if (end - src < PTLS_HELLO_RANDOM_SIZE) { ret = PTLS_ALERT_DECODE_ERROR; @@ -5189,12 +5236,32 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) ptls_decode_open_block(src, end, 2, { switch (protocol_version) { case PTLS_PROTOCOL_VERSION_TLS12: + (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->tls12_cipher_suites, csid); + if ((*tls)->cipher_suite == NULL) { + ret = PTLS_ALERT_HANDSHAKE_FAILURE; + goto Exit; + } /* setup AEAD keys */ if ((ret = build_tls12_traffic_protection(*tls, 1, &src, end)) != 0) goto Exit; if ((ret = build_tls12_traffic_protection(*tls, 0, &src, end)) != 0) goto Exit; break; + case PTLS_PROTOCOL_VERSION_TLS13: + assert((*tls)->key_schedule == NULL); + (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->cipher_suites, csid); + if ((*tls)->cipher_suite == NULL) { + ret = PTLS_ALERT_HANDSHAKE_FAILURE; + goto Exit; + } + /* setup AEAD keys */ + if ((ret = build_tls13_traffic_protection(*tls, 1, &src, end)) != 0) + goto Exit; + if ((ret = build_tls13_traffic_protection(*tls, 0, &src, end)) != 0) + goto Exit; + (*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, (*tls)->ctx->cipher_suites, (*tls)->ech.aead != NULL); + (*tls)->state = PTLS_STATE_SERVER_POST_HANDSHAKE; + goto Exit; default: ret = PTLS_ALERT_ILLEGAL_PARAMETER; break; @@ -5215,6 +5282,7 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) *tls = NULL; } } + assert(ret == 0); return ret; } @@ -6226,13 +6294,12 @@ ptls_aead_context_t *new_aead(ptls_aead_algorithm_t *aead, ptls_hash_algorithm_t struct { uint8_t key[PTLS_MAX_SECRET_SIZE]; uint8_t iv[PTLS_MAX_IV_SIZE]; - } key_iv; + } key_iv = {0}; int ret; if ((ret = get_traffic_keys(aead, hash, key_iv.key, key_iv.iv, secret, hash_value, label_prefix)) != 0) goto Exit; ctx = ptls_aead_new_direct(aead, is_enc, key_iv.key, key_iv.iv); - Exit: ptls_clear_memory(&key_iv, sizeof(key_iv)); return ctx; diff --git a/t/picotls.c b/t/picotls.c index 013783329..6f4ce81fb 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -864,7 +864,73 @@ static int can_ech(ptls_context_t *ctx, int is_server) } } -static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication) +#define ERROUT_IF(cond, err_string) \ + if (cond) { \ + *err = err_string; \ + return -1; \ + } while (0) + +static int aead_keys_cmp(ptls_t *src, ptls_t *dst, const char **err) +{ + ERROUT_IF((src->cipher_suite->hash->digest_size != dst->cipher_suite->hash->digest_size), "cipher digest size"); + size_t digest_size = dst->cipher_suite->hash->digest_size; + int r = memcmp(src->traffic_protection.enc.secret, dst->traffic_protection.enc.secret, digest_size); + ERROUT_IF((r != 0), "secrets"); + r = memcmp(src->traffic_protection.dec.secret, dst->traffic_protection.dec.secret, digest_size); + ERROUT_IF((r != 0), "secrets"); + const unsigned enc_idx = 0; + const unsigned dec_idx = 1; + struct st_keys { + uint8_t key[PTLS_MAX_SECRET_SIZE]; + uint8_t iv[PTLS_MAX_IV_SIZE]; + uint64_t seq; + }; + struct st_keys src_keys[2] = {0}; + struct st_keys dst_keys[2] = {0}; + r = ptls_get_traffic_keys(src, 1, src_keys[enc_idx].key, src_keys[enc_idx].iv, &src_keys[enc_idx].seq); + assert(r == 0); + r = ptls_get_traffic_keys(src, 0, src_keys[dec_idx].key, src_keys[dec_idx].iv, &src_keys[dec_idx].seq); + assert(r == 0); + r = ptls_get_traffic_keys(dst, 1, dst_keys[enc_idx].key, dst_keys[enc_idx].iv, &dst_keys[enc_idx].seq); + assert(r == 0); + r = ptls_get_traffic_keys(dst, 0, dst_keys[dec_idx].key, dst_keys[dec_idx].iv, &dst_keys[dec_idx].seq); + assert(r == 0); + ERROUT_IF((src_keys[enc_idx].seq != dst_keys[enc_idx].seq), "sequence numbers"); + ERROUT_IF((src_keys[dec_idx].seq != dst_keys[dec_idx].seq), "sequence numbers"); + r = memcmp(src_keys[enc_idx].key, dst_keys[enc_idx].key, PTLS_MAX_SECRET_SIZE); + ERROUT_IF((r != 0), "keys"); + r = memcmp(src_keys[dec_idx].key, dst_keys[dec_idx].key, PTLS_MAX_SECRET_SIZE); + ERROUT_IF((r != 0), "keys"); + r = memcmp(src_keys[enc_idx].iv, dst_keys[enc_idx].iv, PTLS_MAX_IV_SIZE); + ERROUT_IF((r != 0), "ivs"); + r = memcmp(src_keys[dec_idx].iv, dst_keys[dec_idx].iv, PTLS_MAX_IV_SIZE); + ERROUT_IF((r != 0), "ivs"); + return 0; +} +#undef ERROUT_IF + +static ptls_t *ptls_dup(ptls_t *prev_tls) +{ + ptls_buffer_t sess_data; + ptls_buffer_init(&sess_data, "", 0); + int r = ptls_export(prev_tls, &sess_data); + assert(r == 0); + ptls_t *tls = NULL; + r = ptls_import(ctx_peer, &tls, (ptls_iovec_t){ .base = sess_data.base, .len = sess_data.off }); + + assert(r == 0); + const char *err = NULL; + if (aead_keys_cmp(prev_tls, tls, &err) != 0) { + fprintf(stdout, "error: keys mismatch [%s]\n", err); + ptls_free(prev_tls); + ptls_free(tls); + return NULL; + } + ptls_free(prev_tls); + return tls; +} + +static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication, int transfer_session) { ptls_t *client, *server; ptls_handshake_properties_t client_hs_prop = {{{{NULL}, ticket}}}, server_hs_prop = {{{{NULL}}}}; @@ -1069,6 +1135,8 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int decbuf.off = 0; cbuf.off = 0; + server = ptls_dup(server); + ret = ptls_send(server, &sbuf, resp, strlen(resp)); ok(ret == 0); } @@ -1202,19 +1270,19 @@ static int second_sign_certificate(ptls_sign_certificate_t *self, ptls_t *tls, p return second_sc_orig->cb(second_sc_orig, tls, async, selected_algorithm, output, input, algorithms, num_algorithms); } -static void test_full_handshake_impl(int require_client_authentication, int is_async) +static void test_full_handshake_impl(int require_client_authentication, int is_async, int transfer_session) { - test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication); + test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication, transfer_session); ok(server_sc_callcnt == 1); ok(async_sc_callcnt == is_async); ok(client_sc_callcnt == require_client_authentication); - test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication); + test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication, transfer_session); ok(server_sc_callcnt == 1); ok(async_sc_callcnt == is_async); ok(client_sc_callcnt == require_client_authentication); - test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1, require_client_authentication); + test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1, require_client_authentication, transfer_session); ok(server_sc_callcnt == 1); ok(async_sc_callcnt == is_async); ok(client_sc_callcnt == require_client_authentication); @@ -1222,28 +1290,32 @@ static void test_full_handshake_impl(int require_client_authentication, int is_a static void test_full_handshake(void) { - test_full_handshake_impl(0, 0); + test_full_handshake_impl(0, 0, 0); + test_full_handshake_impl(0, 0, 0); } static void test_full_handshake_with_client_authentication(void) { - test_full_handshake_impl(1, 0); + test_full_handshake_impl(1, 0, 0); + test_full_handshake_impl(1, 0, 1); } static void test_key_update(void) { - test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0); + test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0, 0); + test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0, 1); } static void test_hrr_handshake(void) { - test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0); + test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0, 0); ok(server_sc_callcnt == 1); + test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0, 0); } static void test_hrr_stateless_handshake(void) { - test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0, 0); + test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0, 0, 0); ok(server_sc_callcnt == 1); } @@ -1269,7 +1341,7 @@ static int on_save_ticket(ptls_save_ticket_t *self, ptls_t *tls, ptls_iovec_t sr return 0; } -static void test_resumption_impl(int different_preferred_key_share, int require_client_authentication) +static void test_resumption_impl(int different_preferred_key_share, int require_client_authentication, int transfer_session) { assert(ctx->key_exchanges[0]->id == ctx_peer->key_exchanges[0]->id); assert(ctx->key_exchanges[1] == NULL); @@ -1295,29 +1367,29 @@ static void test_resumption_impl(int different_preferred_key_share, int require_ ctx_peer->encrypt_ticket = &et; ctx->save_ticket = &st; - test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0); + test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0, transfer_session); ok(server_sc_callcnt == 1); ok(saved_ticket.base != NULL); /* psk using saved ticket */ - test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication); + test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication, transfer_session); ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */ ok(client_sc_callcnt == require_client_authentication); /* 0-rtt psk using saved ticket */ - test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication); + test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication, transfer_session); ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */ ok(client_sc_callcnt == require_client_authentication); ctx->require_dhe_on_psk = 1; /* psk-dhe using saved ticket */ - test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication); + test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication, transfer_session); ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */ ok(client_sc_callcnt == require_client_authentication); /* 0-rtt psk-dhe using saved ticket */ - test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication); + test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication, transfer_session); ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */ ok(client_sc_callcnt == require_client_authentication); @@ -1331,19 +1403,22 @@ static void test_resumption_impl(int different_preferred_key_share, int require_ static void test_resumption(void) { - test_resumption_impl(0, 0); + test_resumption_impl(0, 0, 0); + test_resumption_impl(0, 0, 1); } static void test_resumption_different_preferred_key_share(void) { if (ctx == ctx_peer) return; - test_resumption_impl(1, 0); + test_resumption_impl(1, 0, 0); + test_resumption_impl(0, 0, 1); } static void test_resumption_with_client_authentication(void) { - test_resumption_impl(0, 1); + test_resumption_impl(0, 0, 0); + test_resumption_impl(0, 1, 1); } static void test_async_sign_certificate(void) @@ -1353,7 +1428,7 @@ static void test_async_sign_certificate(void) ptls_sign_certificate_t async_sc = {async_sign_certificate}, *orig_sc = ctx_peer->sign_certificate; ctx_peer->sign_certificate = &async_sc; - test_full_handshake_impl(0, 1); + test_full_handshake_impl(0, 1, 0); ctx_peer->sign_certificate = orig_sc; } From 266a066b421de535c2c29586f1f8bb8b10e48a71 Mon Sep 17 00:00:00 2001 From: robguima Date: Sun, 25 Feb 2024 15:56:00 -0700 Subject: [PATCH 130/151] Update lib/picotls.c Co-authored-by: Kazuho Oku --- lib/picotls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/picotls.c b/lib/picotls.c index e05a7c638..7597631cb 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -1630,7 +1630,7 @@ static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_ ctx->epoch = epoch; - if (tls->key_schedule) + if (tls->key_schedule != NULL) log_secret(tls, log_labels[ptls_is_server(tls) == is_enc][epoch], ptls_iovec_init(ctx->secret, tls->key_schedule->hashes[0].algo->digest_size)); From 381a15470eafc19b7e975062f08268726fc746bf Mon Sep 17 00:00:00 2001 From: Roberto Guimaraes Date: Sun, 25 Feb 2024 16:14:21 -0700 Subject: [PATCH 131/151] address comments: adjust tests, cleanup forther, and fix seq size --- lib/picotls.c | 11 +++++----- t/picotls.c | 56 ++++++++++++++++----------------------------------- 2 files changed, 22 insertions(+), 45 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index 7597631cb..f866f0ece 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -1615,7 +1615,7 @@ static int get_traffic_keys(ptls_aead_algorithm_t *aead, ptls_hash_algorithm_t * return ret; } -static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, int skip_notify, int seq) +static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, uint64_t seq, int skip_notify) { static const char *log_labels[2][4] = { {NULL, "CLIENT_EARLY_TRAFFIC_SECRET", "CLIENT_HANDSHAKE_TRAFFIC_SECRET", "CLIENT_TRAFFIC_SECRET_0"}, @@ -1665,7 +1665,7 @@ static int commission_handshake_secret(ptls_t *tls) free(tls->pending_handshake_secret); tls->pending_handshake_secret = NULL; - return setup_traffic_protection(tls, is_enc, NULL, 2, 1, 0); + return setup_traffic_protection(tls, is_enc, NULL, 2, 0, 1); } static void log_client_random(ptls_t *tls) @@ -4848,7 +4848,7 @@ static int update_traffic_key(ptls_t *tls, int is_enc) "traffic upd", ptls_iovec_init(NULL, 0), NULL)) != 0) goto Exit; memcpy(tp->secret, secret, sizeof(secret)); - ret = setup_traffic_protection(tls, is_enc, NULL, 3, 1, 0); + ret = setup_traffic_protection(tls, is_enc, NULL, 3, 0, 1); Exit: ptls_clear_memory(secret, sizeof(secret)); @@ -5180,7 +5180,7 @@ static int build_tls13_traffic_protection(ptls_t *tls, int is_enc, const uint8_t return PTLS_ALERT_DECODE_ERROR; int skip_notify = is_enc ? 1 : 0; - if (setup_traffic_protection(tls, is_enc, NULL, 3, skip_notify, tp->seq) != 0) + if (setup_traffic_protection(tls, is_enc, NULL, 3, tp->seq, skip_notify) != 0) return PTLS_ERROR_INCOMPATIBLE_KEY; return 0; @@ -5282,7 +5282,6 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) *tls = NULL; } } - assert(ret == 0); return ret; } @@ -6294,7 +6293,7 @@ ptls_aead_context_t *new_aead(ptls_aead_algorithm_t *aead, ptls_hash_algorithm_t struct { uint8_t key[PTLS_MAX_SECRET_SIZE]; uint8_t iv[PTLS_MAX_IV_SIZE]; - } key_iv = {0}; + } key_iv; int ret; if ((ret = get_traffic_keys(aead, hash, key_iv.key, key_iv.iv, secret, hash_value, label_prefix)) != 0) diff --git a/t/picotls.c b/t/picotls.c index 6f4ce81fb..0ffb6c55e 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -864,20 +864,12 @@ static int can_ech(ptls_context_t *ctx, int is_server) } } -#define ERROUT_IF(cond, err_string) \ - if (cond) { \ - *err = err_string; \ - return -1; \ - } while (0) - -static int aead_keys_cmp(ptls_t *src, ptls_t *dst, const char **err) +static void aead_keys_cmp(ptls_t *src, ptls_t *dst, const char **err) { - ERROUT_IF((src->cipher_suite->hash->digest_size != dst->cipher_suite->hash->digest_size), "cipher digest size"); + ok(src->cipher_suite->hash->digest_size == dst->cipher_suite->hash->digest_size); size_t digest_size = dst->cipher_suite->hash->digest_size; - int r = memcmp(src->traffic_protection.enc.secret, dst->traffic_protection.enc.secret, digest_size); - ERROUT_IF((r != 0), "secrets"); - r = memcmp(src->traffic_protection.dec.secret, dst->traffic_protection.dec.secret, digest_size); - ERROUT_IF((r != 0), "secrets"); + ok(memcmp(src->traffic_protection.enc.secret, dst->traffic_protection.enc.secret, digest_size) == 0); + ok(memcmp(src->traffic_protection.dec.secret, dst->traffic_protection.dec.secret, digest_size) == 0); const unsigned enc_idx = 0; const unsigned dec_idx = 1; struct st_keys { @@ -887,29 +879,20 @@ static int aead_keys_cmp(ptls_t *src, ptls_t *dst, const char **err) }; struct st_keys src_keys[2] = {0}; struct st_keys dst_keys[2] = {0}; - r = ptls_get_traffic_keys(src, 1, src_keys[enc_idx].key, src_keys[enc_idx].iv, &src_keys[enc_idx].seq); - assert(r == 0); - r = ptls_get_traffic_keys(src, 0, src_keys[dec_idx].key, src_keys[dec_idx].iv, &src_keys[dec_idx].seq); - assert(r == 0); - r = ptls_get_traffic_keys(dst, 1, dst_keys[enc_idx].key, dst_keys[enc_idx].iv, &dst_keys[enc_idx].seq); - assert(r == 0); - r = ptls_get_traffic_keys(dst, 0, dst_keys[dec_idx].key, dst_keys[dec_idx].iv, &dst_keys[dec_idx].seq); - assert(r == 0); - ERROUT_IF((src_keys[enc_idx].seq != dst_keys[enc_idx].seq), "sequence numbers"); - ERROUT_IF((src_keys[dec_idx].seq != dst_keys[dec_idx].seq), "sequence numbers"); - r = memcmp(src_keys[enc_idx].key, dst_keys[enc_idx].key, PTLS_MAX_SECRET_SIZE); - ERROUT_IF((r != 0), "keys"); - r = memcmp(src_keys[dec_idx].key, dst_keys[dec_idx].key, PTLS_MAX_SECRET_SIZE); - ERROUT_IF((r != 0), "keys"); - r = memcmp(src_keys[enc_idx].iv, dst_keys[enc_idx].iv, PTLS_MAX_IV_SIZE); - ERROUT_IF((r != 0), "ivs"); - r = memcmp(src_keys[dec_idx].iv, dst_keys[dec_idx].iv, PTLS_MAX_IV_SIZE); - ERROUT_IF((r != 0), "ivs"); - return 0; + ok(ptls_get_traffic_keys(src, 1, src_keys[enc_idx].key, src_keys[enc_idx].iv, &src_keys[enc_idx].seq) == 0); + ok(ptls_get_traffic_keys(src, 0, src_keys[dec_idx].key, src_keys[dec_idx].iv, &src_keys[dec_idx].seq) == 0); + ok(ptls_get_traffic_keys(dst, 1, dst_keys[enc_idx].key, dst_keys[enc_idx].iv, &dst_keys[enc_idx].seq) == 0); + ok(ptls_get_traffic_keys(dst, 0, dst_keys[dec_idx].key, dst_keys[dec_idx].iv, &dst_keys[dec_idx].seq) == 0); + ok(src_keys[enc_idx].seq == dst_keys[enc_idx].seq); + ok(src_keys[dec_idx].seq == dst_keys[dec_idx].seq); + ok(memcmp(src_keys[enc_idx].key, dst_keys[enc_idx].key, PTLS_MAX_SECRET_SIZE) == 0); + ok(memcmp(src_keys[dec_idx].key, dst_keys[dec_idx].key, PTLS_MAX_SECRET_SIZE) == 0); + ok(memcmp(src_keys[enc_idx].iv, dst_keys[enc_idx].iv, PTLS_MAX_IV_SIZE) == 0); + ok(memcmp(src_keys[dec_idx].iv, dst_keys[dec_idx].iv, PTLS_MAX_IV_SIZE) == 0); } #undef ERROUT_IF -static ptls_t *ptls_dup(ptls_t *prev_tls) +static ptls_t *test_alloc_and_migrate_tls_context(ptls_t *prev_tls) { ptls_buffer_t sess_data; ptls_buffer_init(&sess_data, "", 0); @@ -920,12 +903,7 @@ static ptls_t *ptls_dup(ptls_t *prev_tls) assert(r == 0); const char *err = NULL; - if (aead_keys_cmp(prev_tls, tls, &err) != 0) { - fprintf(stdout, "error: keys mismatch [%s]\n", err); - ptls_free(prev_tls); - ptls_free(tls); - return NULL; - } + aead_keys_cmp(prev_tls, tls, &err); ptls_free(prev_tls); return tls; } @@ -1135,7 +1113,7 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int decbuf.off = 0; cbuf.off = 0; - server = ptls_dup(server); + server = test_alloc_and_migrate_tls_context(server); ret = ptls_send(server, &sbuf, resp, strlen(resp)); ok(ret == 0); From 61e0403d97d449019bddf0e8833bcd53a2f3eeb1 Mon Sep 17 00:00:00 2001 From: Roberto Guimaraes Date: Sun, 25 Feb 2024 16:38:40 -0700 Subject: [PATCH 132/151] fix test failures: store the original server ptls_t pointer to use for ptls_is_ech_handshake because the migrated ptls_t does not contain handshake information --- t/picotls.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/t/picotls.c b/t/picotls.c index 0ffb6c55e..d50fb4d9b 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -890,7 +890,6 @@ static void aead_keys_cmp(ptls_t *src, ptls_t *dst, const char **err) ok(memcmp(src_keys[enc_idx].iv, dst_keys[enc_idx].iv, PTLS_MAX_IV_SIZE) == 0); ok(memcmp(src_keys[dec_idx].iv, dst_keys[dec_idx].iv, PTLS_MAX_IV_SIZE) == 0); } -#undef ERROUT_IF static ptls_t *test_alloc_and_migrate_tls_context(ptls_t *prev_tls) { @@ -904,7 +903,6 @@ static ptls_t *test_alloc_and_migrate_tls_context(ptls_t *prev_tls) assert(r == 0); const char *err = NULL; aead_keys_cmp(prev_tls, tls, &err); - ptls_free(prev_tls); return tls; } @@ -1099,6 +1097,9 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int cbuf.off = 0; } + /* holds the ptls_t pointer of server prior to migration */ + ptls_t *original_server = server; + if (mode != TEST_HANDSHAKE_EARLY_DATA || require_client_authentication) { ret = ptls_send(client, &cbuf, req, strlen(req)); ok(ret == 0); @@ -1112,8 +1113,7 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int ok(ptls_handshake_is_complete(server)); decbuf.off = 0; cbuf.off = 0; - - server = test_alloc_and_migrate_tls_context(server); + server = test_alloc_and_migrate_tls_context(original_server); ret = ptls_send(server, &sbuf, resp, strlen(resp)); ok(ret == 0); @@ -1171,18 +1171,21 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int decbuf.off = 0; } + /* original_server is used for the server-side checks because handshake data is never migrated */ if (can_ech(ctx_peer, 1) && can_ech(ctx, 0)) { ok(ptls_is_ech_handshake(client, NULL, NULL, NULL)); - ok(ptls_is_ech_handshake(server, NULL, NULL, NULL)); + ok(ptls_is_ech_handshake(original_server, NULL, NULL, NULL)); } else { ok(!ptls_is_ech_handshake(client, NULL, NULL, NULL)); - ok(!ptls_is_ech_handshake(server, NULL, NULL, NULL)); + ok(!ptls_is_ech_handshake(original_server, NULL, NULL, NULL)); } ptls_buffer_dispose(&cbuf); ptls_buffer_dispose(&sbuf); ptls_buffer_dispose(&decbuf); ptls_free(client); + if (original_server != server) + ptls_free(original_server); ptls_free(server); if (check_ch) From e4c793b78d678c6eb90dbd32137c3547faa6721d Mon Sep 17 00:00:00 2001 From: Roberto Guimaraes Date: Mon, 26 Feb 2024 09:32:00 -0700 Subject: [PATCH 133/151] cosmetic: rename function so it does not read as a test run clang-format against lib/picotls.c and t/picotls.c --- lib/picotls.c | 15 ++++++++------- t/picotls.c | 12 +++++++----- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index f866f0ece..34e6b5e3d 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5131,14 +5131,15 @@ int ptls_export(ptls_t *tls, ptls_buffer_t *output) if (tls->state != PTLS_STATE_SERVER_POST_HANDSHAKE) return PTLS_ERROR_LIBRARY; return export_tls13_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, - tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, tls->traffic_protection.enc.seq, - tls->traffic_protection.dec.secret, tls->traffic_protection.dec.seq); + tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, + tls->traffic_protection.enc.seq, tls->traffic_protection.dec.secret, + tls->traffic_protection.dec.seq); } else { return export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, - tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, - tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq, - tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret, - tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.dec.seq); + tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, + tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq, + tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret, + tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.dec.seq); } } @@ -5261,7 +5262,7 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) goto Exit; (*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, (*tls)->ctx->cipher_suites, (*tls)->ech.aead != NULL); (*tls)->state = PTLS_STATE_SERVER_POST_HANDSHAKE; - goto Exit; + goto Exit; default: ret = PTLS_ALERT_ILLEGAL_PARAMETER; break; diff --git a/t/picotls.c b/t/picotls.c index d50fb4d9b..e07f97220 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -891,14 +891,14 @@ static void aead_keys_cmp(ptls_t *src, ptls_t *dst, const char **err) ok(memcmp(src_keys[dec_idx].iv, dst_keys[dec_idx].iv, PTLS_MAX_IV_SIZE) == 0); } -static ptls_t *test_alloc_and_migrate_tls_context(ptls_t *prev_tls) +static ptls_t *alloc_and_migrate_tls_context(ptls_t *prev_tls) { ptls_buffer_t sess_data; ptls_buffer_init(&sess_data, "", 0); int r = ptls_export(prev_tls, &sess_data); assert(r == 0); ptls_t *tls = NULL; - r = ptls_import(ctx_peer, &tls, (ptls_iovec_t){ .base = sess_data.base, .len = sess_data.off }); + r = ptls_import(ctx_peer, &tls, (ptls_iovec_t){.base = sess_data.base, .len = sess_data.off}); assert(r == 0); const char *err = NULL; @@ -906,7 +906,8 @@ static ptls_t *test_alloc_and_migrate_tls_context(ptls_t *prev_tls) return tls; } -static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication, int transfer_session) +static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication, + int transfer_session) { ptls_t *client, *server; ptls_handshake_properties_t client_hs_prop = {{{{NULL}, ticket}}}, server_hs_prop = {{{{NULL}}}}; @@ -1113,7 +1114,7 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int ok(ptls_handshake_is_complete(server)); decbuf.off = 0; cbuf.off = 0; - server = test_alloc_and_migrate_tls_context(original_server); + server = alloc_and_migrate_tls_context(original_server); ret = ptls_send(server, &sbuf, resp, strlen(resp)); ok(ret == 0); @@ -1348,7 +1349,8 @@ static void test_resumption_impl(int different_preferred_key_share, int require_ ctx_peer->encrypt_ticket = &et; ctx->save_ticket = &st; - test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0, transfer_session); + test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0, + transfer_session); ok(server_sc_callcnt == 1); ok(saved_ticket.base != NULL); From f765b59220b5941e2a4776b5f5c505f5cce98cad Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 11:05:26 +0900 Subject: [PATCH 134/151] transfer only when requested --- t/picotls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/t/picotls.c b/t/picotls.c index e07f97220..c770e0979 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -1114,7 +1114,8 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int ok(ptls_handshake_is_complete(server)); decbuf.off = 0; cbuf.off = 0; - server = alloc_and_migrate_tls_context(original_server); + if (transfer_session) + server = alloc_and_migrate_tls_context(original_server); ret = ptls_send(server, &sbuf, resp, strlen(resp)); ok(ret == 0); From b586480503834727f4a9ba37a19e9c6d9e4b0989 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 11:05:51 +0900 Subject: [PATCH 135/151] no need to build hashes for other cipher suites than the one being selected --- lib/picotls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/picotls.c b/lib/picotls.c index 34e6b5e3d..08a1094af 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5260,7 +5260,7 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) goto Exit; if ((ret = build_tls13_traffic_protection(*tls, 0, &src, end)) != 0) goto Exit; - (*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, (*tls)->ctx->cipher_suites, (*tls)->ech.aead != NULL); + (*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, NULL, (*tls)->ech.aead != NULL); (*tls)->state = PTLS_STATE_SERVER_POST_HANDSHAKE; goto Exit; default: From e8c3a80e8e1b5c117afa9615a22a35ce59f001f3 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 11:21:25 +0900 Subject: [PATCH 136/151] key_schedule_new might fail due to low memory --- lib/picotls.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/picotls.c b/lib/picotls.c index 08a1094af..e4ff028cc 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5260,7 +5260,10 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) goto Exit; if ((ret = build_tls13_traffic_protection(*tls, 0, &src, end)) != 0) goto Exit; - (*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, NULL, (*tls)->ech.aead != NULL); + if (((*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, NULL, (*tls)->ech.aead != NULL)) == NULL) { + ret = PTLS_ERROR_NO_MEMORY; + goto Exit; + } (*tls)->state = PTLS_STATE_SERVER_POST_HANDSHAKE; goto Exit; default: From 424ecd0f0ad84323eec77cd982194b5c28dccd1f Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 11:24:40 +0900 Subject: [PATCH 137/151] setup key_schedule before building traffic keys, and we can avoid adding `if` --- lib/picotls.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index e4ff028cc..0d150f59b 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -1630,9 +1630,8 @@ static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_ ctx->epoch = epoch; - if (tls->key_schedule != NULL) - log_secret(tls, log_labels[ptls_is_server(tls) == is_enc][epoch], - ptls_iovec_init(ctx->secret, tls->key_schedule->hashes[0].algo->digest_size)); + log_secret(tls, log_labels[ptls_is_server(tls) == is_enc][epoch], + ptls_iovec_init(ctx->secret, tls->key_schedule->hashes[0].algo->digest_size)); /* special path for applications having their own record layer */ if (tls->ctx->update_traffic_key != NULL) { @@ -5256,14 +5255,14 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) goto Exit; } /* setup AEAD keys */ - if ((ret = build_tls13_traffic_protection(*tls, 1, &src, end)) != 0) - goto Exit; - if ((ret = build_tls13_traffic_protection(*tls, 0, &src, end)) != 0) - goto Exit; if (((*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, NULL, (*tls)->ech.aead != NULL)) == NULL) { ret = PTLS_ERROR_NO_MEMORY; goto Exit; } + if ((ret = build_tls13_traffic_protection(*tls, 1, &src, end)) != 0) + goto Exit; + if ((ret = build_tls13_traffic_protection(*tls, 0, &src, end)) != 0) + goto Exit; (*tls)->state = PTLS_STATE_SERVER_POST_HANDSHAKE; goto Exit; default: From a451c0bf8aaaca221a31f33cc51ed7848fb7fe58 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 11:33:03 +0900 Subject: [PATCH 138/151] rename; tls13 traffic keys are constructed in two ways, the name of the function should imply the case being dealt --- lib/picotls.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index 0d150f59b..dec352c80 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5142,7 +5142,7 @@ int ptls_export(ptls_t *tls, ptls_buffer_t *output) } } -static int build_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end) +static int import_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end) { struct st_ptls_traffic_protection_t *tp = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec; @@ -5169,7 +5169,7 @@ static int build_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t return 0; } -static int build_tls13_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end) +static int import_tls13_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end) { struct st_ptls_traffic_protection_t *tp = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec; @@ -5242,9 +5242,9 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) goto Exit; } /* setup AEAD keys */ - if ((ret = build_tls12_traffic_protection(*tls, 1, &src, end)) != 0) + if ((ret = import_tls12_traffic_protection(*tls, 1, &src, end)) != 0) goto Exit; - if ((ret = build_tls12_traffic_protection(*tls, 0, &src, end)) != 0) + if ((ret = import_tls12_traffic_protection(*tls, 0, &src, end)) != 0) goto Exit; break; case PTLS_PROTOCOL_VERSION_TLS13: @@ -5259,9 +5259,9 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) ret = PTLS_ERROR_NO_MEMORY; goto Exit; } - if ((ret = build_tls13_traffic_protection(*tls, 1, &src, end)) != 0) + if ((ret = import_tls13_traffic_protection(*tls, 1, &src, end)) != 0) goto Exit; - if ((ret = build_tls13_traffic_protection(*tls, 0, &src, end)) != 0) + if ((ret = import_tls13_traffic_protection(*tls, 0, &src, end)) != 0) goto Exit; (*tls)->state = PTLS_STATE_SERVER_POST_HANDSHAKE; goto Exit; From 46a037510f77ba6865cd2d538feeb10b07eb526c Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 11:39:37 +0900 Subject: [PATCH 139/151] we can assume this; see server_handle_hello --- lib/picotls.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/picotls.c b/lib/picotls.c index dec352c80..c30da3031 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5248,7 +5248,6 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) goto Exit; break; case PTLS_PROTOCOL_VERSION_TLS13: - assert((*tls)->key_schedule == NULL); (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->cipher_suites, csid); if ((*tls)->cipher_suite == NULL) { ret = PTLS_ALERT_HANDSHAKE_FAILURE; From 33635738587735232159827093ae70e1ac9819bb Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 11:41:29 +0900 Subject: [PATCH 140/151] exit version-specific logic the same way, setting `state` to value that reflects the role --- lib/picotls.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index c30da3031..b1b3d7216 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5262,11 +5262,10 @@ int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params) goto Exit; if ((ret = import_tls13_traffic_protection(*tls, 0, &src, end)) != 0) goto Exit; - (*tls)->state = PTLS_STATE_SERVER_POST_HANDSHAKE; - goto Exit; + break; default: ret = PTLS_ALERT_ILLEGAL_PARAMETER; - break; + goto Exit; } }); /* extensions */ From 69e65f81a6d3c861b01e9c0d742c80bc42affdb5 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 12:29:26 +0900 Subject: [PATCH 141/151] better notify the key update; the install key cannot be derived / has not been notified at an earlier moment --- lib/picotls.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index b1b3d7216..b2aa2f625 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5179,8 +5179,7 @@ static int import_tls13_traffic_protection(ptls_t *tls, int is_enc, const uint8_ if (ptls_decode64(&tp->seq, src, end) != 0) return PTLS_ALERT_DECODE_ERROR; - int skip_notify = is_enc ? 1 : 0; - if (setup_traffic_protection(tls, is_enc, NULL, 3, tp->seq, skip_notify) != 0) + if (setup_traffic_protection(tls, is_enc, NULL, 3, tp->seq, 0) != 0) return PTLS_ERROR_INCOMPATIBLE_KEY; return 0; From 9158265380bc58080b0d19f74e09c96a9d9f55f1 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 12:49:04 +0900 Subject: [PATCH 142/151] code reuse --- lib/picotls.c | 121 ++++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 63 deletions(-) diff --git a/lib/picotls.c b/lib/picotls.c index b2aa2f625..2feba7ef9 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -5017,35 +5017,27 @@ ptls_t *ptls_server_new(ptls_context_t *ctx) return tls; } -static int export_tls13_params(ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher, - const void *client_random, const char *server_name, ptls_iovec_t negotiated_protocol, - const void *enc_key, uint64_t enc_seq, const void *dec_key, uint64_t dec_seq) -{ - int ret; - - ptls_buffer_push_block(output, 2, { - ptls_buffer_push(output, is_server); - ptls_buffer_push(output, session_reused); - ptls_buffer_push16(output, PTLS_PROTOCOL_VERSION_TLS13); - ptls_buffer_push16(output, cipher->id); - ptls_buffer_pushv(output, client_random, PTLS_HELLO_RANDOM_SIZE); - ptls_buffer_push_block(output, 2, { - size_t len = server_name != NULL ? strlen(server_name) : 0; - ptls_buffer_pushv(output, server_name, len); - }); - ptls_buffer_push_block(output, 2, { ptls_buffer_pushv(output, negotiated_protocol.base, negotiated_protocol.len); }); - ptls_buffer_push_block(output, 2, { - ptls_buffer_pushv(output, enc_key, cipher->hash->digest_size); - ptls_buffer_push64(output, enc_seq); - ptls_buffer_pushv(output, dec_key, cipher->hash->digest_size); - ptls_buffer_push64(output, dec_seq); - }); - ptls_buffer_push_block(output, 2, {}); /* for future extensions */ - }); - -Exit: - return ret; -} +#define export_tls_params(output, is_server, session_reused, protocol_version, cipher, client_random, server_name, \ + negotiated_protocol, ver_block) \ + do { \ + const char *_server_name = (server_name); \ + ptls_iovec_t _negotiated_protocol = (negotiated_protocol); \ + ptls_buffer_push_block((output), 2, { \ + ptls_buffer_push((output), (is_server)); \ + ptls_buffer_push((output), (session_reused)); \ + ptls_buffer_push16((output), (protocol_version)); \ + ptls_buffer_push16((output), (cipher)->id); \ + ptls_buffer_pushv((output), (client_random), PTLS_HELLO_RANDOM_SIZE); \ + ptls_buffer_push_block((output), 2, { \ + size_t len = _server_name != NULL ? strlen(_server_name) : 0; \ + ptls_buffer_pushv((output), _server_name, len); \ + }); \ + ptls_buffer_push_block((output), 2, \ + { ptls_buffer_pushv((output), _negotiated_protocol.base, _negotiated_protocol.len); }); \ + ptls_buffer_push_block((output), 2, {ver_block}); /* version-specific block */ \ + ptls_buffer_push_block((output), 2, {}); /* for future extensions */ \ + }); \ + } while (0) static int export_tls12_params(ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher, const void *client_random, const char *server_name, ptls_iovec_t negotiated_protocol, @@ -5054,29 +5046,18 @@ static int export_tls12_params(ptls_buffer_t *output, int is_server, int session { int ret; - ptls_buffer_push_block(output, 2, { - ptls_buffer_push(output, is_server); - ptls_buffer_push(output, session_reused); - ptls_buffer_push16(output, PTLS_PROTOCOL_VERSION_TLS12); - ptls_buffer_push16(output, cipher->id); - ptls_buffer_pushv(output, client_random, PTLS_HELLO_RANDOM_SIZE); - ptls_buffer_push_block(output, 2, { - size_t len = server_name != NULL ? strlen(server_name) : 0; - ptls_buffer_pushv(output, server_name, len); - }); - ptls_buffer_push_block(output, 2, { ptls_buffer_pushv(output, negotiated_protocol.base, negotiated_protocol.len); }); - ptls_buffer_push_block(output, 2, { - ptls_buffer_pushv(output, enc_key, cipher->aead->key_size); - ptls_buffer_pushv(output, enc_iv, cipher->aead->tls12.fixed_iv_size); - ptls_buffer_push64(output, enc_seq); - if (cipher->aead->tls12.record_iv_size != 0) - ptls_buffer_push64(output, enc_record_iv); - ptls_buffer_pushv(output, dec_key, cipher->aead->key_size); - ptls_buffer_pushv(output, dec_iv, cipher->aead->tls12.fixed_iv_size); - ptls_buffer_push64(output, dec_seq); - }); - ptls_buffer_push_block(output, 2, {}); /* for future extensions */ - }); + export_tls_params(output, is_server, session_reused, PTLS_PROTOCOL_VERSION_TLS12, cipher, client_random, server_name, + negotiated_protocol, { + ptls_buffer_pushv(output, enc_key, cipher->aead->key_size); + ptls_buffer_pushv(output, enc_iv, cipher->aead->tls12.fixed_iv_size); + ptls_buffer_push64(output, enc_seq); + if (cipher->aead->tls12.record_iv_size != 0) + ptls_buffer_push64(output, enc_record_iv); + ptls_buffer_pushv(output, dec_key, cipher->aead->key_size); + ptls_buffer_pushv(output, dec_iv, cipher->aead->tls12.fixed_iv_size); + ptls_buffer_push64(output, dec_seq); + }); + ret = 0; Exit: return ret; @@ -5126,20 +5107,34 @@ int ptls_export(ptls_t *tls, ptls_buffer_t *output) { ptls_iovec_t negotiated_protocol = ptls_iovec_init(tls->negotiated_protocol, tls->negotiated_protocol != NULL ? strlen(tls->negotiated_protocol) : 0); + int ret; + + if (tls->state != PTLS_STATE_SERVER_POST_HANDSHAKE) { + ret = PTLS_ERROR_LIBRARY; + goto Exit; + } + if (ptls_get_protocol_version(tls) == PTLS_PROTOCOL_VERSION_TLS13) { - if (tls->state != PTLS_STATE_SERVER_POST_HANDSHAKE) - return PTLS_ERROR_LIBRARY; - return export_tls13_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, - tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, - tls->traffic_protection.enc.seq, tls->traffic_protection.dec.secret, - tls->traffic_protection.dec.seq); + export_tls_params(output, tls->is_server, tls->is_psk_handshake, PTLS_PROTOCOL_VERSION_TLS13, tls->cipher_suite, + tls->client_random, tls->server_name, negotiated_protocol, { + ptls_buffer_pushv(output, tls->traffic_protection.enc.secret, tls->cipher_suite->hash->digest_size); + ptls_buffer_push64(output, tls->traffic_protection.enc.seq); + ptls_buffer_pushv(output, tls->traffic_protection.dec.secret, tls->cipher_suite->hash->digest_size); + ptls_buffer_push64(output, tls->traffic_protection.dec.seq); + }); + ret = 0; } else { - return export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, - tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, - tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq, - tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret, - tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.dec.seq); + if ((ret = export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, + tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, + tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq, + tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret, + tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, + tls->traffic_protection.dec.seq)) != 0) + goto Exit; } + +Exit: + return ret; } static int import_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end) From adc17a632a4c40cd0b6a4c5370f6e38f42d67375 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 13:05:19 +0900 Subject: [PATCH 143/151] remove unused arg --- t/picotls.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/t/picotls.c b/t/picotls.c index c770e0979..c757c77b2 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -864,7 +864,7 @@ static int can_ech(ptls_context_t *ctx, int is_server) } } -static void aead_keys_cmp(ptls_t *src, ptls_t *dst, const char **err) +static void aead_keys_cmp(ptls_t *src, ptls_t *dst) { ok(src->cipher_suite->hash->digest_size == dst->cipher_suite->hash->digest_size); size_t digest_size = dst->cipher_suite->hash->digest_size; @@ -901,8 +901,7 @@ static ptls_t *alloc_and_migrate_tls_context(ptls_t *prev_tls) r = ptls_import(ctx_peer, &tls, (ptls_iovec_t){.base = sess_data.base, .len = sess_data.off}); assert(r == 0); - const char *err = NULL; - aead_keys_cmp(prev_tls, tls, &err); + aead_keys_cmp(prev_tls, tls); return tls; } From 9fa602cdb54881c19953fbf08b695897f3972f94 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 13:07:07 +0900 Subject: [PATCH 144/151] rename for readability --- t/picotls.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/t/picotls.c b/t/picotls.c index c757c77b2..83070dd4e 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -891,18 +891,18 @@ static void aead_keys_cmp(ptls_t *src, ptls_t *dst) ok(memcmp(src_keys[dec_idx].iv, dst_keys[dec_idx].iv, PTLS_MAX_IV_SIZE) == 0); } -static ptls_t *alloc_and_migrate_tls_context(ptls_t *prev_tls) +static ptls_t *clone_tls(ptls_t *src) { ptls_buffer_t sess_data; ptls_buffer_init(&sess_data, "", 0); - int r = ptls_export(prev_tls, &sess_data); + int r = ptls_export(src, &sess_data); assert(r == 0); - ptls_t *tls = NULL; - r = ptls_import(ctx_peer, &tls, (ptls_iovec_t){.base = sess_data.base, .len = sess_data.off}); + ptls_t *dest = NULL; + r = ptls_import(ctx_peer, &dest, (ptls_iovec_t){.base = sess_data.base, .len = sess_data.off}); assert(r == 0); - aead_keys_cmp(prev_tls, tls); - return tls; + aead_keys_cmp(src, dest); + return dest; } static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication, @@ -1114,7 +1114,7 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int decbuf.off = 0; cbuf.off = 0; if (transfer_session) - server = alloc_and_migrate_tls_context(original_server); + server = clone_tls(original_server); ret = ptls_send(server, &sbuf, resp, strlen(resp)); ok(ret == 0); From 1676eb8ff9995b1943fc6c043a239c6201b12221 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 13:08:20 +0900 Subject: [PATCH 145/151] dispose buffer --- t/picotls.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/t/picotls.c b/t/picotls.c index 83070dd4e..d8fc4b406 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -893,14 +893,16 @@ static void aead_keys_cmp(ptls_t *src, ptls_t *dst) static ptls_t *clone_tls(ptls_t *src) { + ptls_t *dest = NULL; ptls_buffer_t sess_data; + ptls_buffer_init(&sess_data, "", 0); int r = ptls_export(src, &sess_data); assert(r == 0); - ptls_t *dest = NULL; r = ptls_import(ctx_peer, &dest, (ptls_iovec_t){.base = sess_data.base, .len = sess_data.off}); - assert(r == 0); + ptls_buffer_dispose(&sess_data); + aead_keys_cmp(src, dest); return dest; } From 16d547221acb2887d9510a4ed8c78bd2fd8b4c9f Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 13:10:30 +0900 Subject: [PATCH 146/151] rename --- t/picotls.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/t/picotls.c b/t/picotls.c index d8fc4b406..1ce592588 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -864,31 +864,29 @@ static int can_ech(ptls_context_t *ctx, int is_server) } } -static void aead_keys_cmp(ptls_t *src, ptls_t *dst) +static void check_clone(ptls_t *src, ptls_t *dest) { - ok(src->cipher_suite->hash->digest_size == dst->cipher_suite->hash->digest_size); - size_t digest_size = dst->cipher_suite->hash->digest_size; - ok(memcmp(src->traffic_protection.enc.secret, dst->traffic_protection.enc.secret, digest_size) == 0); - ok(memcmp(src->traffic_protection.dec.secret, dst->traffic_protection.dec.secret, digest_size) == 0); + ok(src->cipher_suite->hash->digest_size == dest->cipher_suite->hash->digest_size); + size_t digest_size = dest->cipher_suite->hash->digest_size; + ok(memcmp(src->traffic_protection.enc.secret, dest->traffic_protection.enc.secret, digest_size) == 0); + ok(memcmp(src->traffic_protection.dec.secret, dest->traffic_protection.dec.secret, digest_size) == 0); const unsigned enc_idx = 0; const unsigned dec_idx = 1; - struct st_keys { + struct { uint8_t key[PTLS_MAX_SECRET_SIZE]; uint8_t iv[PTLS_MAX_IV_SIZE]; uint64_t seq; - }; - struct st_keys src_keys[2] = {0}; - struct st_keys dst_keys[2] = {0}; + } src_keys[2] = {0}, dest_keys[2] = {0}; ok(ptls_get_traffic_keys(src, 1, src_keys[enc_idx].key, src_keys[enc_idx].iv, &src_keys[enc_idx].seq) == 0); ok(ptls_get_traffic_keys(src, 0, src_keys[dec_idx].key, src_keys[dec_idx].iv, &src_keys[dec_idx].seq) == 0); - ok(ptls_get_traffic_keys(dst, 1, dst_keys[enc_idx].key, dst_keys[enc_idx].iv, &dst_keys[enc_idx].seq) == 0); - ok(ptls_get_traffic_keys(dst, 0, dst_keys[dec_idx].key, dst_keys[dec_idx].iv, &dst_keys[dec_idx].seq) == 0); - ok(src_keys[enc_idx].seq == dst_keys[enc_idx].seq); - ok(src_keys[dec_idx].seq == dst_keys[dec_idx].seq); - ok(memcmp(src_keys[enc_idx].key, dst_keys[enc_idx].key, PTLS_MAX_SECRET_SIZE) == 0); - ok(memcmp(src_keys[dec_idx].key, dst_keys[dec_idx].key, PTLS_MAX_SECRET_SIZE) == 0); - ok(memcmp(src_keys[enc_idx].iv, dst_keys[enc_idx].iv, PTLS_MAX_IV_SIZE) == 0); - ok(memcmp(src_keys[dec_idx].iv, dst_keys[dec_idx].iv, PTLS_MAX_IV_SIZE) == 0); + ok(ptls_get_traffic_keys(dest, 1, dest_keys[enc_idx].key, dest_keys[enc_idx].iv, &dest_keys[enc_idx].seq) == 0); + ok(ptls_get_traffic_keys(dest, 0, dest_keys[dec_idx].key, dest_keys[dec_idx].iv, &dest_keys[dec_idx].seq) == 0); + ok(src_keys[enc_idx].seq == dest_keys[enc_idx].seq); + ok(src_keys[dec_idx].seq == dest_keys[dec_idx].seq); + ok(memcmp(src_keys[enc_idx].key, dest_keys[enc_idx].key, PTLS_MAX_SECRET_SIZE) == 0); + ok(memcmp(src_keys[dec_idx].key, dest_keys[dec_idx].key, PTLS_MAX_SECRET_SIZE) == 0); + ok(memcmp(src_keys[enc_idx].iv, dest_keys[enc_idx].iv, PTLS_MAX_IV_SIZE) == 0); + ok(memcmp(src_keys[dec_idx].iv, dest_keys[dec_idx].iv, PTLS_MAX_IV_SIZE) == 0); } static ptls_t *clone_tls(ptls_t *src) @@ -903,7 +901,8 @@ static ptls_t *clone_tls(ptls_t *src) assert(r == 0); ptls_buffer_dispose(&sess_data); - aead_keys_cmp(src, dest); + check_clone(src, dest); + return dest; } From 483973c9eb24b4b7dd2be7aa5182c393f1cd07da Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 29 Feb 2024 13:55:53 +0900 Subject: [PATCH 147/151] add FIXME --- include/picotls.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/picotls.h b/include/picotls.h index 7a642707d..218f68208 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -1588,6 +1588,7 @@ int ptls_handshake_is_complete(ptls_t *tls); int ptls_is_psk_handshake(ptls_t *tls); /** * return if a ECH handshake was performed, as well as optionally the kem and cipher-suite being used + * FIXME: this function always return false when the TLS session is exported and imported */ int ptls_is_ech_handshake(ptls_t *tls, uint8_t *config_id, ptls_hpke_kem_t **kem, ptls_hpke_cipher_suite_t **cipher); /** From de804a8578dca59f5a0e7034dbb6df090cf26eb5 Mon Sep 17 00:00:00 2001 From: Tim Evens Date: Tue, 26 Mar 2024 10:21:49 -0700 Subject: [PATCH 148/151] Remove brotli --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc146a8f7..0a25cfe6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,8 +70,8 @@ IF (WITH_DTRACE) ENDIF () ENDIF () -PKG_CHECK_MODULES(BROTLI_DEC libbrotlidec) -PKG_CHECK_MODULES(BROTLI_ENC libbrotlienc) +#PKG_CHECK_MODULES(BROTLI_DEC libbrotlidec) +#PKG_CHECK_MODULES(BROTLI_ENC libbrotlienc) IF (BROTLI_DEC_FOUND AND BROTLI_ENC_FOUND) INCLUDE_DIRECTORIES(${BROTLI_DEC_INCLUDE_DIRS} ${BROTLI_ENC_INCLUDE_DIRS}) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPICOTLS_USE_BROTLI=1") From c9834fd0751a294131dafaa4a34ccb3a5d48f39b Mon Sep 17 00:00:00 2001 From: Tim Evens Date: Tue, 26 Mar 2024 13:44:23 -0700 Subject: [PATCH 149/151] Remove decrepit from boringssl adjust --- cmake/boringssl-adjust.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/boringssl-adjust.cmake b/cmake/boringssl-adjust.cmake index 0ae12965e..d3b6ea853 100644 --- a/cmake/boringssl-adjust.cmake +++ b/cmake/boringssl-adjust.cmake @@ -17,8 +17,7 @@ FUNCTION (BORINGSSL_ADJUST) #LIST(APPEND OPENSSL_CRYPTO_LIBRARIES "${BORINGSSL_LIBDIR}/crypto/libcrypto.a") #SET (OPENSSL_CRYPTO_LIBRARIES "${OPENSSL_CRYPTO_LIBRARIES}" PARENT_SCOPE) - SET (OPENSSL_CRYPTO_LIBRARIES "decrepit") - LIST(APPEND OPENSSL_CRYPTO_LIBRARIES "crypto") + SET (OPENSSL_CRYPTO_LIBRARIES "crypto") SET (OPENSSL_CRYPTO_LIBRARIES "${OPENSSL_CRYPTO_LIBRARIES}" PARENT_SCOPE) set (OPENSSL_LIBRARIES ${BORINGSSL_LIBRARIES}) From 621e4d2bd78fedf4dd4b42f363a01242d0fc2911 Mon Sep 17 00:00:00 2001 From: Tim Evens Date: Tue, 26 Mar 2024 15:14:47 -0700 Subject: [PATCH 150/151] Update boringssl adjust to support build test --- cmake/boringssl-adjust.cmake | 41 ++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/cmake/boringssl-adjust.cmake b/cmake/boringssl-adjust.cmake index d3b6ea853..35dfa678b 100644 --- a/cmake/boringssl-adjust.cmake +++ b/cmake/boringssl-adjust.cmake @@ -1,27 +1,32 @@ FUNCTION (BORINGSSL_ADJUST) + cmake_minimum_required(VERSION 3.14) + IF (OPENSSL_FOUND AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/base.h") MESSAGE(STATUS " BoringSSL found; assuming OpenSSL 1.1.1 compatibility") SET(OPENSSL_VERSION "1.1.1" PARENT_SCOPE) - # LIST(GET OPENSSL_CRYPTO_LIBRARIES 0 OPENSSL_ONE_LIB_PATH) - # GET_FILENAME_COMPONENT(OPENSSL_LIBDIR "${OPENSSL_ONE_LIB_PATH}" DIRECTORY) - # SET(LIBDECREPIT_PATH "${OPENSSL_LIBDIR}/libdecrepit.a") - # IF (NOT EXISTS "${LIBDECREPIT_PATH}") - # MESSAGE(FATAL_ERROR "libdecrepit.a was not found under ${OPENSSL_LIBDIR}; maybe you need to manually copy the file there") - # ENDIF () - # LIST(APPEND OPENSSL_CRYPTO_LIBRARIES "${LIBDECREPIT_PATH}") - # SET(OPENSSL_CRYPTO_LIBRARIES "${OPENSSL_CRYPTO_LIBRARIES}" PARENT_SCOPE) - # LIST(APPEND OPENSSL_LIBRARIES "${LIBDECREPIT_PATH}") - # SET(OPENSSL_LIBRARIES "${OPENSSL_LIBRARIES}" PARENT_SCOPE) - #SET (OPENSSL_CRYPTO_LIBRARIES "${BORINGSSL_LIBDIR}/decrepit/libdecrepit.a") - #LIST(APPEND OPENSSL_CRYPTO_LIBRARIES "${BORINGSSL_LIBDIR}/crypto/libcrypto.a") - #SET (OPENSSL_CRYPTO_LIBRARIES "${OPENSSL_CRYPTO_LIBRARIES}" PARENT_SCOPE) + message("OpenSSL libs: ${OPENSSL_LIBRARIES}") + + if ("BoringSSL::ssl" IN_LIST OPENSSL_LIBRARIES) + LIST(APPEND OPENSSL_CRYPTO_LIBRARIES "BoringSSL::decrepit") + SET (OPENSSL_CRYPTO_LIBRARIES "${OPENSSL_CRYPTO_LIBRARIES}" PARENT_SCOPE) + LIST(APPEND OPENSSL_LIBRARIES "BoringSSL::decrepit") + set (OPENSSL_LIBRARIES ${OPENSSL_LIBRARIES} PARENT_SCOPE) + + message("Appending decrepit: ${OPENSSL_LIBRARIES}") - SET (OPENSSL_CRYPTO_LIBRARIES "crypto") - SET (OPENSSL_CRYPTO_LIBRARIES "${OPENSSL_CRYPTO_LIBRARIES}" PARENT_SCOPE) + else () + LIST(GET OPENSSL_CRYPTO_LIBRARIES 0 OPENSSL_ONE_LIB_PATH) + GET_FILENAME_COMPONENT(OPENSSL_LIBDIR "${OPENSSL_ONE_LIB_PATH}" DIRECTORY) + SET(LIBDECREPIT_PATH "${OPENSSL_LIBDIR}/libdecrepit.a") + IF (NOT EXISTS "${LIBDECREPIT_PATH}") + MESSAGE(FATAL_ERROR "libdecrepit.a was not found under ${OPENSSL_LIBDIR}; maybe you need to manually copy the file there") + ENDIF () + LIST(APPEND OPENSSL_CRYPTO_LIBRARIES "${LIBDECREPIT_PATH}") + SET(OPENSSL_CRYPTO_LIBRARIES "${OPENSSL_CRYPTO_LIBRARIES}" PARENT_SCOPE) + LIST(APPEND OPENSSL_LIBRARIES "${LIBDECREPIT_PATH}") + SET(OPENSSL_LIBRARIES "${OPENSSL_LIBRARIES}" PARENT_SCOPE) + endif () - set (OPENSSL_LIBRARIES ${BORINGSSL_LIBRARIES}) - LIST(APPEND OPENSSL_LIBRARIES "${OPENSSL_CRYPTO_LIBRARIES}") - set (OPENSSL_LIBRARIES ${BORINGSSL_LIBRARIES} PARENT_SCOPE) ENDIF () ENDFUNCTION () From e24e609087eb3a786bb4d1187f5472fb067f53f3 Mon Sep 17 00:00:00 2001 From: Tim Evens Date: Tue, 26 Mar 2024 15:21:03 -0700 Subject: [PATCH 151/151] Reduce cmake min to 3.3 --- cmake/boringssl-adjust.cmake | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmake/boringssl-adjust.cmake b/cmake/boringssl-adjust.cmake index 35dfa678b..bf156e0e5 100644 --- a/cmake/boringssl-adjust.cmake +++ b/cmake/boringssl-adjust.cmake @@ -1,5 +1,5 @@ FUNCTION (BORINGSSL_ADJUST) - cmake_minimum_required(VERSION 3.14) + cmake_minimum_required(VERSION 3.3) IF (OPENSSL_FOUND AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/base.h") MESSAGE(STATUS " BoringSSL found; assuming OpenSSL 1.1.1 compatibility") @@ -13,8 +13,6 @@ FUNCTION (BORINGSSL_ADJUST) LIST(APPEND OPENSSL_LIBRARIES "BoringSSL::decrepit") set (OPENSSL_LIBRARIES ${OPENSSL_LIBRARIES} PARENT_SCOPE) - message("Appending decrepit: ${OPENSSL_LIBRARIES}") - else () LIST(GET OPENSSL_CRYPTO_LIBRARIES 0 OPENSSL_ONE_LIB_PATH) GET_FILENAME_COMPONENT(OPENSSL_LIBDIR "${OPENSSL_ONE_LIB_PATH}" DIRECTORY)