From: Daiki Ueno Date: Sat, 1 Jun 2024 22:19:14 +0000 (+0900) Subject: key_share: support X25519Kyber768Draft00 X-Git-Tag: 3.8.7~13^2~1 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=1bc78c387a9796e8248ffb644576074f8de4e6ad;p=thirdparty%2Fgnutls.git key_share: support X25519Kyber768Draft00 This implements X25519Kyber768Draft00 hybrid post-quantum key exchange in TLS 1.3, based on the draft: https://datatracker.ietf.org/doc/draft-tls-westerbaan-xyber768d00/ Signed-off-by: Daiki Ueno --- diff --git a/lib/Makefile.am b/lib/Makefile.am index 067772c322..0e89fdf184 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -273,6 +273,10 @@ thirdparty_libadd += $(NETTLE_LIBS) $(HOGWEED_LIBS) $(GMP_LIBS) libgnutls_la_LIBADD += nettle/libcrypto.la endif +if ENABLE_LIBOQS +libgnutls_la_LIBADD += liboqs/libcrypto.la +endif + if HAVE_LD_OUTPUT_DEF libgnutls_la_LDFLAGS += -Wl,--output-def,libgnutls-$(DLL_VERSION).def libgnutls-$(DLL_VERSION).def: libgnutls.la diff --git a/lib/algorithms/groups.c b/lib/algorithms/groups.c index 9093de6eb2..a329c746e9 100644 --- a/lib/algorithms/groups.c +++ b/lib/algorithms/groups.c @@ -169,6 +169,14 @@ static const gnutls_group_entry_st supported_groups[] = { .q_bits = &gnutls_ffdhe_8192_key_bits, .pk = GNUTLS_PK_DH, .tls_id = 0x104 }, +#endif +#ifdef HAVE_LIBOQS + { .name = "X25519-KYBER768", + .id = GNUTLS_GROUP_EXP_X25519_KYBER768, + .curve = GNUTLS_ECC_CURVE_X25519, + .pk = GNUTLS_PK_ECDH_X25519, + .pk2 = GNUTLS_PK_EXP_KYBER768, + .tls_id = 0x6399 }, #endif { 0, 0, 0 } }; diff --git a/lib/algorithms/publickey.c b/lib/algorithms/publickey.c index 0ef0834933..10938bce0e 100644 --- a/lib/algorithms/publickey.c +++ b/lib/algorithms/publickey.c @@ -202,6 +202,12 @@ static const gnutls_pk_entry pk_algorithms[] = { .oid = ECDH_X448_OID, .id = GNUTLS_PK_ECDH_X448, .curve = GNUTLS_ECC_CURVE_X448 }, +#ifdef HAVE_LIBOQS + { .name = "KYBER768", + .oid = NULL, + .id = GNUTLS_PK_EXP_KYBER768, + .curve = GNUTLS_ECC_CURVE_INVALID }, +#endif { .name = "UNKNOWN", .oid = NULL, .id = GNUTLS_PK_UNKNOWN, diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h index fd8ee0c728..5c0630adaa 100644 --- a/lib/crypto-backend.h +++ b/lib/crypto-backend.h @@ -411,6 +411,13 @@ typedef struct gnutls_crypto_pk { const gnutls_pk_params_st *pub, const gnutls_datum_t *nonce, unsigned int flags); + int (*encaps)(gnutls_pk_algorithm_t, gnutls_datum_t *ciphertext, + gnutls_datum_t *shared_secret, const gnutls_datum_t *pub); + + int (*decaps)(gnutls_pk_algorithm_t, gnutls_datum_t *shared_secret, + const gnutls_datum_t *ciphertext, + const gnutls_datum_t *priv); + int (*curve_exists)(gnutls_ecc_curve_t); /* true/false */ int (*pk_exists)(gnutls_pk_algorithm_t); /* true/false */ int (*sign_exists)(gnutls_sign_algorithm_t); /* true/false */ diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c index 575ffaf8f2..6926cdd00e 100644 --- a/lib/ext/key_share.c +++ b/lib/ext/key_share.c @@ -120,6 +120,8 @@ static int client_gen_key_share(gnutls_session_t session, } else if (group->pk == GNUTLS_PK_ECDH_X25519 || group->pk == GNUTLS_PK_ECDH_X448) { + unsigned int length_pos; + gnutls_pk_params_release(&session->key.kshare.ecdhx_params); gnutls_pk_params_init(&session->key.kshare.ecdhx_params); @@ -129,6 +131,8 @@ static int client_gen_key_share(gnutls_session_t session, if (ret < 0) return gnutls_assert_val(ret); + length_pos = extdata->length; + ret = _gnutls_buffer_append_data_prefix( extdata, 16, session->key.kshare.ecdhx_params.raw_pub.data, @@ -141,6 +145,33 @@ static int client_gen_key_share(gnutls_session_t session, session->key.kshare.ecdhx_params.algo = group->pk; session->key.kshare.ecdhx_params.curve = group->curve; + if (group->pk2 != GNUTLS_PK_UNKNOWN) { + gnutls_pk_params_release( + &session->key.kshare.kem_params); + gnutls_pk_params_init(&session->key.kshare.kem_params); + + ret = _gnutls_pk_generate_keys( + group->pk2, 0, &session->key.kshare.kem_params, + 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_buffer_append_data( + extdata, + session->key.kshare.kem_params.raw_pub.data, + session->key.kshare.kem_params.raw_pub.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* copy actual length */ + _gnutls_write_uint16(extdata->length - length_pos - 2, + &extdata->data[length_pos]); + } + ret = 0; } else if (group->pk == GNUTLS_PK_DH) { @@ -243,6 +274,10 @@ static int server_gen_key_share(gnutls_session_t session, } else if (group->pk == GNUTLS_PK_ECDH_X25519 || group->pk == GNUTLS_PK_ECDH_X448) { + unsigned int length_pos; + + length_pos = extdata->length; + ret = _gnutls_buffer_append_data_prefix( extdata, 16, session->key.kshare.ecdhx_params.raw_pub.data, @@ -250,8 +285,22 @@ static int server_gen_key_share(gnutls_session_t session, if (ret < 0) return gnutls_assert_val(ret); - ret = 0; + if (group->pk2 != GNUTLS_PK_UNKNOWN) { + ret = _gnutls_buffer_append_data( + extdata, + session->key.kshare.kem_params.raw_pub.data, + session->key.kshare.kem_params.raw_pub.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + /* copy actual length */ + _gnutls_write_uint16(extdata->length - length_pos - 2, + &extdata->data[length_pos]); + } + + ret = 0; } else if (group->pk == GNUTLS_PK_DH) { ret = _gnutls_buffer_append_prefix(extdata, 16, group->prime->size); @@ -333,9 +382,15 @@ static int server_use_key_share(gnutls_session_t session, curve = _gnutls_ecc_curve_get_params(group->curve); - if (curve->size != data_size) - return gnutls_assert_val( - GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + if (group->pk2 != GNUTLS_PK_UNKNOWN) { + if (curve->size > data_size) + return gnutls_assert_val( + GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } else { + if (curve->size != data_size) + return gnutls_assert_val( + GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } /* generate our key */ ret = _gnutls_pk_generate_keys( @@ -351,7 +406,7 @@ static int server_use_key_share(gnutls_session_t session, pub.curve = curve->id; pub.raw_pub.data = (void *)data; - pub.raw_pub.size = data_size; + pub.raw_pub.size = curve->size; /* We don't mask the MSB in the final byte as required * by RFC7748. This will be done internally by nettle 3.3 or later. @@ -363,6 +418,50 @@ static int server_use_key_share(gnutls_session_t session, return gnutls_assert_val(ret); } + if (group->pk2 != GNUTLS_PK_UNKNOWN) { + gnutls_datum_t key; + gnutls_datum_t peer_pub; + + gnutls_pk_params_release( + &session->key.kshare.kem_params); + gnutls_pk_params_init(&session->key.kshare.kem_params); + + /* generate our key */ + ret = _gnutls_pk_generate_keys( + group->pk2, 0, &session->key.kshare.kem_params, + 1); + if (ret < 0) + return gnutls_assert_val(ret); + + /* server's public key is unused, but the raw_pub field + * is used to store ciphertext */ + gnutls_free( + session->key.kshare.kem_params.raw_pub.data); + + peer_pub.data = (uint8_t *)data + curve->size; + peer_pub.size = data_size - curve->size; + + ret = _gnutls_pk_encaps( + group->pk2, + &session->key.kshare.kem_params.raw_pub, &key, + &peer_pub); + if (ret < 0) + return gnutls_assert_val(ret); + + session->key.key.data = gnutls_realloc_fast( + session->key.key.data, + session->key.key.size + key.size); + if (!session->key.key.data) { + _gnutls_free_datum(&key); + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + memcpy(session->key.key.data + session->key.key.size, + key.data, key.size); + session->key.key.size += key.size; + _gnutls_free_datum(&key); + } + ret = 0; } else if (group->pk == GNUTLS_PK_DH) { @@ -496,9 +595,15 @@ static int client_use_key_share(gnutls_session_t session, return gnutls_assert_val( GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); - if (curve->size != data_size) - return gnutls_assert_val( - GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + if (group->pk2 != GNUTLS_PK_UNKNOWN) { + if (curve->size > data_size) + return gnutls_assert_val( + GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } else { + if (curve->size != data_size) + return gnutls_assert_val( + GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } /* read the public key and generate shared */ gnutls_pk_params_init(&pub); @@ -519,6 +624,33 @@ static int client_use_key_share(gnutls_session_t session, return gnutls_assert_val(ret); } + if (group->pk2 != GNUTLS_PK_UNKNOWN) { + gnutls_datum_t key; + gnutls_datum_t ciphertext; + + ciphertext.data = (uint8_t *)data + curve->size; + ciphertext.size = data_size - curve->size; + + ret = _gnutls_pk_decaps( + group->pk2, &key, &ciphertext, + &session->key.kshare.kem_params.raw_priv); + if (ret < 0) + return gnutls_assert_val(ret); + + session->key.key.data = gnutls_realloc_fast( + session->key.key.data, + session->key.key.size + key.size); + if (!session->key.key.data) { + _gnutls_free_datum(&key); + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + memcpy(session->key.key.data + session->key.key.size, + key.data, key.size); + session->key.key.size += key.size; + _gnutls_free_datum(&key); + } + ret = 0; } else if (group->pk == GNUTLS_PK_DH) { diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 258a08c842..5727739bdc 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -594,6 +594,7 @@ struct gnutls_key_st { gnutls_pk_params_st ecdh_params; gnutls_pk_params_st ecdhx_params; gnutls_pk_params_st dh_params; + gnutls_pk_params_st kem_params; } kshare; /* The union contents depend on the negotiated protocol. @@ -764,6 +765,7 @@ typedef struct gnutls_group_entry_st { const unsigned *q_bits; gnutls_ecc_curve_t curve; gnutls_pk_algorithm_t pk; + gnutls_pk_algorithm_t pk2; unsigned tls_id; /* The RFC4492 namedCurve ID or TLS 1.3 group ID */ } gnutls_group_entry_st; diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 6b87610c44..790406e4df 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -908,7 +908,12 @@ typedef enum { GNUTLS_PK_ECDH_X448 = 11, GNUTLS_PK_EDDSA_ED448 = 12, GNUTLS_PK_RSA_OAEP = 13, - GNUTLS_PK_MAX = GNUTLS_PK_RSA_OAEP + GNUTLS_PK_MAX = GNUTLS_PK_RSA_OAEP, + + /* Experimental algorithms */ + GNUTLS_PK_EXP_MIN = 256, + GNUTLS_PK_EXP_KYBER768 = GNUTLS_PK_EXP_MIN, + GNUTLS_PK_EXP_MAX = GNUTLS_PK_EXP_KYBER768 } gnutls_pk_algorithm_t; const char *gnutls_pk_algorithm_get_name(gnutls_pk_algorithm_t algorithm); @@ -1136,6 +1141,11 @@ typedef enum { GNUTLS_GROUP_FFDHE8192, GNUTLS_GROUP_FFDHE6144, GNUTLS_GROUP_MAX = GNUTLS_GROUP_FFDHE6144, + + /* Experimental algorithms */ + GNUTLS_GROUP_EXP_MIN = 512, + GNUTLS_GROUP_EXP_X25519_KYBER768 = GNUTLS_GROUP_EXP_MIN, + GNUTLS_GROUP_EXP_MAX = GNUTLS_GROUP_EXP_X25519_KYBER768 } gnutls_group_t; /* macros to allow specifying a specific curve in gnutls_privkey_generate() diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am index b855c8c193..0f21823cb4 100644 --- a/lib/nettle/Makefile.am +++ b/lib/nettle/Makefile.am @@ -36,6 +36,10 @@ if ENABLE_MINITASN1 AM_CPPFLAGS += -I$(srcdir)/../minitasn1 endif +if ENABLE_DLOPEN +AM_CPPFLAGS += $(LIBOQS_CFLAGS) -DGNUTLS_OQS_ENABLE_DLOPEN=1 +endif + noinst_LTLIBRARIES = libcrypto.la libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c init.c \ diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index b317b790d7..4155a540ed 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -70,6 +70,9 @@ #include "gnettle.h" #include "fips.h" #include "dh.h" +#ifdef HAVE_LIBOQS +#include "dlwrap/oqs.h" +#endif static inline const struct ecc_curve *get_supported_nist_curve(int curve); static inline const struct ecc_curve *get_supported_gost_curve(int curve); @@ -687,6 +690,111 @@ cleanup: return ret; } +static int _wrap_nettle_pk_encaps(gnutls_pk_algorithm_t algo, + gnutls_datum_t *ciphertext, + gnutls_datum_t *shared_secret, + const gnutls_datum_t *pub) +{ + int ret; + + switch (algo) { +#ifdef HAVE_LIBOQS + case GNUTLS_PK_EXP_KYBER768: { + OQS_KEM *kem = NULL; + OQS_STATUS rc; + + kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768); + if (kem == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + ciphertext->data = gnutls_malloc(kem->length_ciphertext); + if (ciphertext->data == NULL) { + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; + } + ciphertext->size = kem->length_ciphertext; + + shared_secret->data = gnutls_malloc(kem->length_shared_secret); + if (shared_secret->data == NULL) { + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; + } + shared_secret->size = kem->length_shared_secret; + + rc = GNUTLS_OQS_FUNC(OQS_KEM_encaps)( + kem, ciphertext->data, shared_secret->data, pub->data); + if (rc != OQS_SUCCESS) { + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + goto cleanup; + } + + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = 0; + } break; +#endif + default: + ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM); + goto cleanup; + } + +cleanup: + if (ret < 0) { + gnutls_free(ciphertext->data); + gnutls_free(shared_secret->data); + } + return ret; +} + +static int _wrap_nettle_pk_decaps(gnutls_pk_algorithm_t algo, + gnutls_datum_t *shared_secret, + const gnutls_datum_t *ciphertext, + const gnutls_datum_t *priv) +{ + int ret; + + switch (algo) { +#ifdef HAVE_LIBOQS + case GNUTLS_PK_EXP_KYBER768: { + OQS_KEM *kem = NULL; + OQS_STATUS rc; + + kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768); + if (kem == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + shared_secret->data = gnutls_malloc(kem->length_shared_secret); + if (shared_secret->data == NULL) { + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; + } + shared_secret->size = kem->length_shared_secret; + + rc = GNUTLS_OQS_FUNC(OQS_KEM_decaps)( + kem, shared_secret->data, ciphertext->data, priv->data); + if (rc != OQS_SUCCESS) { + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + goto cleanup; + } + + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = 0; + } break; +#endif + default: + ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM); + goto cleanup; + } +cleanup: + if (ret < 0) + gnutls_free(shared_secret->data); + return ret; +} + /* This wraps nettle_rsa_encrypt so it returns ciphertext as a byte * array instead of a mpz_t value. Returns 1 on success; 0 otherwise. */ @@ -2234,6 +2342,9 @@ static int _wrap_nettle_pk_exists(gnutls_pk_algorithm_t pk) case GNUTLS_PK_RSA_PSS: case GNUTLS_PK_RSA_OAEP: case GNUTLS_PK_EDDSA_ED25519: +#ifdef HAVE_LIBOQS + case GNUTLS_PK_EXP_KYBER768: +#endif #if ENABLE_GOST case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: @@ -2875,6 +2986,9 @@ static int pct_test(gnutls_pk_algorithm_t algo, } case GNUTLS_PK_ECDH_X25519: case GNUTLS_PK_ECDH_X448: +#ifdef HAVE_LIBOQS + case GNUTLS_PK_EXP_KYBER768: +#endif ret = 0; goto cleanup; default: @@ -3605,6 +3719,49 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, goto cleanup; break; } +#ifdef HAVE_LIBOQS + case GNUTLS_PK_EXP_KYBER768: { + OQS_KEM *kem = NULL; + OQS_STATUS rc; + + not_approved = true; + + kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768); + if (kem == NULL) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; + } + + params->raw_priv.size = kem->length_secret_key; + params->raw_priv.data = gnutls_malloc(params->raw_priv.size); + if (params->raw_priv.data == NULL) { + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; + } + + params->raw_pub.size = kem->length_public_key; + params->raw_pub.data = gnutls_malloc(params->raw_pub.size); + if (params->raw_pub.data == NULL) { + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; + } + + rc = GNUTLS_OQS_FUNC(OQS_KEM_keypair)(kem, params->raw_pub.data, + params->raw_priv.data); + if (rc != OQS_SUCCESS) { + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); + goto cleanup; + } + + GNUTLS_OQS_FUNC(OQS_KEM_free)(kem); + + ret = 0; + break; + } +#endif default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; @@ -3858,6 +4015,11 @@ static int wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, ret = 0; break; } +#ifdef HAVE_LIBOQS + case GNUTLS_PK_EXP_KYBER768: + ret = 0; + break; +#endif #if ENABLE_GOST case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: @@ -4307,6 +4469,8 @@ gnutls_crypto_pk_st _gnutls_pk_ops = { .generate_keys = wrap_nettle_pk_generate_keys, .pk_fixup_private_params = wrap_nettle_pk_fixup, .derive = _wrap_nettle_pk_derive, + .encaps = _wrap_nettle_pk_encaps, + .decaps = _wrap_nettle_pk_decaps, .curve_exists = _wrap_nettle_pk_curve_exists, .pk_exists = _wrap_nettle_pk_exists, .sign_exists = _wrap_nettle_pk_sign_exists diff --git a/lib/pk.h b/lib/pk.h index 20fe314f94..eca4e02d73 100644 --- a/lib/pk.h +++ b/lib/pk.h @@ -46,6 +46,10 @@ extern gnutls_crypto_pk_st _gnutls_pk_ops; _gnutls_pk_ops.derive(algo, out, pub, priv, nonce, 0) #define _gnutls_pk_derive_tls13(algo, out, pub, priv) \ _gnutls_pk_ops.derive(algo, out, pub, priv, NULL, PK_DERIVE_TLS13) +#define _gnutls_pk_encaps(algo, ciphertext, shared_secret, pub) \ + _gnutls_pk_ops.encaps(algo, ciphertext, shared_secret, pub) +#define _gnutls_pk_decaps(algo, shared_secret, ciphertext, priv) \ + _gnutls_pk_ops.decaps(algo, shared_secret, ciphertext, priv) #define _gnutls_pk_generate_keys(algo, bits, params, temporal) \ _gnutls_pk_ops.generate_keys(algo, bits, params, temporal) #define _gnutls_pk_generate_params(algo, bits, priv) \ diff --git a/lib/state.c b/lib/state.c index ec514c0cd2..f2c74d97d0 100644 --- a/lib/state.c +++ b/lib/state.c @@ -459,6 +459,7 @@ static void deinit_keys(gnutls_session_t session) gnutls_pk_params_release(&session->key.kshare.ecdhx_params); gnutls_pk_params_release(&session->key.kshare.ecdh_params); gnutls_pk_params_release(&session->key.kshare.dh_params); + gnutls_pk_params_release(&session->key.kshare.kem_params); if (!vers->tls13_sem && session->key.binders[0].prf == NULL) { gnutls_pk_params_release(&session->key.proto.tls12.ecdh.params); diff --git a/tests/Makefile.am b/tests/Makefile.am index c674835c1f..ca76736d2e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -600,6 +600,10 @@ ctests += win32-certopenstore endif +if ENABLE_LIBOQS +dist_check_SCRIPTS += pqc-hybrid-kx.sh +endif + cpptests = if ENABLE_CXX if HAVE_CMOCKA diff --git a/tests/pqc-hybrid-kx.sh b/tests/pqc-hybrid-kx.sh new file mode 100644 index 0000000000..b9302b43b1 --- /dev/null +++ b/tests/pqc-hybrid-kx.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +# Copyright (C) 2022 Red Hat, Inc. +# +# Author: Daiki Ueno +# +# This file is part of GnuTLS. +# +# GnuTLS is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# GnuTLS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GnuTLS. If not, see . + +: ${srcdir=.} +: ${SERV=../src/gnutls-serv${EXEEXT}} +: ${CLI=../src/gnutls-cli${EXEEXT}} + +if ! test -x "${SERV}"; then + exit 77 +fi + +if ! test -x "${CLI}"; then + exit 77 +fi + +. "${srcdir}/scripts/common.sh" +testdir=`create_testdir pqc-hybrid-kx` + +KEY="$srcdir/../doc/credentials/x509/key-ed25519.pem" +CERT="$srcdir/../doc/credentials/x509/cert-ed25519.pem" +CACERT="$srcdir/../doc/credentials/x509/ca.pem" + +eval "${GETPORT}" +launch_server --echo --priority NORMAL:-GROUP-ALL:+GROUP-X25519-KYBER768 --x509keyfile="$KEY" --x509certfile="$CERT" +PID=$! +wait_server ${PID} + +${VALGRIND} "${CLI}" -p "${PORT}" 127.0.0.1 --priority NORMAL:-GROUP-ALL:+GROUP-X25519-KYBER768 --x509cafile="$CACERT" --logfile="$testdir/cli.log"