Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional support for the AEGIS cipher suites #478

Merged
merged 2 commits into from Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Expand Up @@ -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"
Expand Down
39 changes: 32 additions & 7 deletions CMakeLists.txt
Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -120,19 +127,37 @@ 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()

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
Expand All @@ -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 ()
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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()
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -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:
Expand All @@ -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)<sup>1</sup> | 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)<sup>1</sup> | 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.

Expand Down
18 changes: 17 additions & 1 deletion include/picotls.h
Expand Up @@ -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

Expand All @@ -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 */
Expand All @@ -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
Expand Down
9 changes: 9 additions & 0 deletions include/picotls/minicrypto.h
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions include/picotls/openssl.h
Expand Up @@ -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
Expand All @@ -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;
Expand Down
23 changes: 21 additions & 2 deletions lib/cifra.c
Expand Up @@ -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};
62 changes: 62 additions & 0 deletions 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};