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 6faf288c9..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 ()
@@ -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 2d829cc89..b701e780b 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..ca3a31d9d 100644
--- a/include/picotls/minicrypto.h
+++ b/include/picotls/minicrypto.h
@@ -47,9 +47,18 @@ 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[];
+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 b41d3bc0d..d51f2b703 100644
--- a/lib/cifra.c
+++ b/lib/cifra.c
@@ -23,5 +23,24 @@
#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)
+ &ptls_minicrypto_aes256gcmsha384,
+
+ // ciphers used with sha256
+ &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/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..b03533909 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,12 +2164,78 @@ 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_openssl_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_openssl_aegis128l,
+ .hash = &ptls_openssl_sha256};
+
+ptls_aead_algorithm_t ptls_openssl_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_openssl_aegis256,
+ .hash = &ptls_openssl_sha384};
+#endif
+
+
+
+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,
#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/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/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 4ca49aa38..b3188ff0a 100644
--- a/t/openssl.c
+++ b/t/openssl.c
@@ -555,16 +555,18 @@ 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},
.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},