From 7779e874691dbc1c3f000ecc5aba30b241c1d01b Mon Sep 17 00:00:00 2001 From: gcr Date: Fri, 2 Aug 2024 14:48:22 +0000 Subject: [PATCH] Add liboqs-backed implementation of sntrup761x25519-sha512@openssh.com `sntrup761x25519-sha512@openssh.com` is a PQ key exchange algorithm available in upstream OpenSSH. This implements that algorithm using the sntrup761 implementation within liboqs. Using this, we are able to demonstrate interop with upstream OpenSSH for this specific algorithm and more generally the construction of the hybrid combiner. While sntrup761 has fallen out of fashion, we have received [reassurances](https://github.com/open-quantum-safe/liboqs/pull/1328#issuecomment-1354111314) from upstream OpenSSH that it will be supported until at least 2027. Support for the algorithm is added by adding the necessary entry to `generate.yml` and generating the relevant code snippets. In addition, we had to address the conflicting implementation from upstream by disabling the preprocessor macro and/or removing the conflicting code segment. Testing Updated `try_connection.py` to accept a specific KEX and/or SIG to test. This allows us to test arbitrary algorithms against arbitrary SSH implementations including the upstream OpenSSH. It was necessary to add a classical signature to the test so that there would be a supported signature in upstream OpenSSH that OQS could test against. In a follow-up PR I plan to add a CI job to do this, but am running short on time this week. Related to Issue #163 Signed-off-by: Gerardo Ravago --- README.md | 2 ++ defines.h | 3 ++- kex.c | 6 ++--- kex.h | 20 +++++++++------- kexgen.c | 31 +++++++++++++++--------- kexoqs.c | 40 +++++++++++++++++++++++++++++++ kexoqsx25519.c | 41 ++++++++++++++++++++++++++++++++ monitor.c | 3 ++- myproposal.h | 5 ++-- oqs-template/generate.yml | 10 ++++++++ oqs-test/try_connection.py | 17 +++++++++---- regress/unittests/kex/test_kex.c | 4 ---- ssh-keyscan.c | 3 ++- ssh_api.c | 6 +++-- sshconnect2.c | 3 ++- sshd.c | 3 ++- 16 files changed, 156 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 310e11bfe642..af20dcd7e9cf 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ The following quantum-safe algorithms from liboqs are supported (assuming they h - **HQC**: `hqc-128-sha256`, `hqc-192-sha384`, `hqc-256-sha512`† - **Kyber**: `kyber-512-sha256`, `kyber-768-sha384`, `kyber-1024-sha512` - **ML-KEM**: `ml-kem-512-sha256`, `ml-kem-768-sha256`, `ml-kem-1024-sha384` +- **NTRU-Prime**: `ntruprime-sntrup761-sha512` The following hybrid algorithms are made available: @@ -82,6 +83,7 @@ The following hybrid algorithms are made available: - **HQC**: `ecdh-nistp256-hqc-128r3-sha256@openquantumsafe.org` `x25519-hqc-128r3-sha256@openquantumsafe.org` `ecdh-nistp384-hqc-192r3-sha384@openquantumsafe.org` `ecdh-nistp521-hqc-256r3-sha512@openquantumsafe.org` - **Kyber**: `ecdh-nistp256-kyber-512r3-sha256-d00@openquantumsafe.org` `x25519-kyber-512r3-sha256-d00@amazon.com` `ecdh-nistp384-kyber-768r3-sha384-d00@openquantumsafe.org` `ecdh-nistp521-kyber-1024r3-sha512-d00@openquantumsafe.org` - **ML-KEM**: `ecdh-nistp256-ml-kem-512-sha256@openquantumsafe.org` `x25519-ml-kem-512-sha256@openquantumsafe.org` `mlkem768nistp256-sha256` `mlkem768x25519-sha256` `mlkem1024nistp384-sha384` +- **NTRU-Prime**: `sntrup761x25519-sha512@openssh.com` Note that algorithms marked with a dagger (†) have large stack usage and may cause failures when run on threads or in constrained environments. For example, McEliece require building `oqs-openssh` with a large(r) stack provision than is default: Adding `LDFLAGS="-Wl,--stack,20000000"` to [the `./configure` command below](#step-2-build-the-fork) is required to allow cygwin-based testing to pass. diff --git a/defines.h b/defines.h index 279e509aae22..08e03fe9d633 100644 --- a/defines.h +++ b/defines.h @@ -940,6 +940,7 @@ struct winsize { * so only enable if the compiler supports them. */ #if defined(VARIABLE_LENGTH_ARRAYS) && defined(VARIABLE_DECLARATION_AFTER_CODE) -# define USE_SNTRUP761X25519 1 +// OQS Note: Disabled upstream SNTRUP761X25519 support. +# define USE_SNTRUP761X25519 0 #endif #endif /* _DEFINES_H */ diff --git a/kex.c b/kex.c index 4440bd8f5d94..1915fc43135a 100644 --- a/kex.c +++ b/kex.c @@ -113,10 +113,6 @@ static const struct kexalg kexalgs[] = { #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, -#ifdef USE_SNTRUP761X25519 - { KEX_SNTRUP761X25519_SHA512, KEX_KEM_SNTRUP761X25519_SHA512, 0, - SSH_DIGEST_SHA512 }, -#endif #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ ///// OQS_TEMPLATE_FRAGMENT_ADD_KEX_ALGS_START @@ -157,6 +153,8 @@ static const struct kexalg kexalgs[] = { { KEX_ML_KEM_768_SHA256, KEX_KEM_ML_KEM_768_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_ML_KEM_768_X25519_SHA256, KEX_KEM_ML_KEM_768_X25519_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_ML_KEM_1024_SHA384, KEX_KEM_ML_KEM_1024_SHA384, 0, SSH_DIGEST_SHA384 }, + { KEX_NTRUPRIME_SNTRUP761_SHA512, KEX_KEM_NTRUPRIME_SNTRUP761_SHA512, 0, SSH_DIGEST_SHA512 }, + { KEX_NTRUPRIME_SNTRUP761_X25519_SHA512, KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512, 0, SSH_DIGEST_SHA512 }, #ifdef OPENSSL_HAS_ECC { KEX_FRODOKEM_640_AES_ECDH_NISTP256_SHA256, KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256, NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, { KEX_FRODOKEM_976_AES_ECDH_NISTP384_SHA384, KEX_KEM_FRODOKEM_976_AES_ECDH_NISTP384_SHA384, NID_secp384r1, SSH_DIGEST_SHA384 }, diff --git a/kex.h b/kex.h index a752dc488012..148b76be5688 100644 --- a/kex.h +++ b/kex.h @@ -63,7 +63,6 @@ #define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521" #define KEX_CURVE25519_SHA256 "curve25519-sha256" #define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org" -#define KEX_SNTRUP761X25519_SHA512 "sntrup761x25519-sha512@openssh.com" ///// OQS_TEMPLATE_FRAGMENT_DEFINE_KEX_PRETTY_NAMES_START #define KEX_FRODOKEM_640_AES_SHA256 "frodokem-640-aes-sha256" #define KEX_FRODOKEM_640_AES_X25519_SHA256 "x25519-frodokem-640-aesr2-sha256@openquantumsafe.org" @@ -102,6 +101,8 @@ #define KEX_ML_KEM_768_SHA256 "ml-kem-768-sha256" #define KEX_ML_KEM_768_X25519_SHA256 "mlkem768x25519-sha256" #define KEX_ML_KEM_1024_SHA384 "ml-kem-1024-sha384" +#define KEX_NTRUPRIME_SNTRUP761_SHA512 "sntrup761-sha512" +#define KEX_NTRUPRIME_SNTRUP761_X25519_SHA512 "sntrup761x25519-sha512@openssh.com" #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC #define KEX_FRODOKEM_640_AES_ECDH_NISTP256_SHA256 "ecdh-nistp256-frodokem-640-aesr2-sha256@openquantumsafe.org" @@ -173,7 +174,6 @@ enum kex_exchange { KEX_DH_GEX_SHA256, KEX_ECDH_SHA2, KEX_C25519_SHA256, - KEX_KEM_SNTRUP761X25519_SHA512, ///// OQS_TEMPLATE_FRAGMENT_ADD_KEX_ENUMS_START KEX_KEM_FRODOKEM_640_AES_SHA256, KEX_KEM_FRODOKEM_640_AES_X25519_SHA256, @@ -212,6 +212,8 @@ enum kex_exchange { KEX_KEM_ML_KEM_768_SHA256, KEX_KEM_ML_KEM_768_X25519_SHA256, KEX_KEM_ML_KEM_1024_SHA384, + KEX_KEM_NTRUPRIME_SNTRUP761_SHA512, + KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512, #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256, @@ -380,12 +382,6 @@ int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); -int kex_kem_sntrup761x25519_keypair(struct kex *); -int kex_kem_sntrup761x25519_enc(struct kex *, const struct sshbuf *, - struct sshbuf **, struct sshbuf **); -int kex_kem_sntrup761x25519_dec(struct kex *, const struct sshbuf *, - struct sshbuf **); - ///// OQS_TEMPLATE_FRAGMENT_DECLARE_KEX_PROTOTYPES_START /* frodokem_640_aes prototypes */ int kex_kem_frodokem_640_aes_keypair(struct kex *); @@ -535,6 +531,14 @@ int kex_kem_ml_kem_768_x25519_dec(struct kex *, const struct sshbuf *, struct s int kex_kem_ml_kem_1024_keypair(struct kex *); int kex_kem_ml_kem_1024_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_kem_ml_kem_1024_dec(struct kex *, const struct sshbuf *, struct sshbuf **); +/* ntruprime_sntrup761 prototypes */ +int kex_kem_ntruprime_sntrup761_keypair(struct kex *); +int kex_kem_ntruprime_sntrup761_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); +int kex_kem_ntruprime_sntrup761_dec(struct kex *, const struct sshbuf *, struct sshbuf **); +/* ntruprime_sntrup761_x25519 prototypes */ +int kex_kem_ntruprime_sntrup761_x25519_keypair(struct kex *); +int kex_kem_ntruprime_sntrup761_x25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); +int kex_kem_ntruprime_sntrup761_x25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC /* frodokem_640_aes_nistp256 prototypes */ diff --git a/kexgen.c b/kexgen.c index 2a04b40558dc..47e6336b71f3 100644 --- a/kexgen.c +++ b/kexgen.c @@ -118,9 +118,6 @@ kex_gen_client(struct ssh *ssh) case KEX_C25519_SHA256: r = kex_c25519_keypair(kex); break; - case KEX_KEM_SNTRUP761X25519_SHA512: - r = kex_kem_sntrup761x25519_keypair(kex); - break; ///// OQS_TEMPLATE_FRAGMENT_ADD_CLIENT_SWITCH_CASES_START case KEX_KEM_FRODOKEM_640_AES_SHA256: r = kex_kem_frodokem_640_aes_keypair(kex); @@ -233,6 +230,12 @@ kex_gen_client(struct ssh *ssh) case KEX_KEM_ML_KEM_1024_SHA384: r = kex_kem_ml_kem_1024_keypair(kex); break; + case KEX_KEM_NTRUPRIME_SNTRUP761_SHA512: + r = kex_kem_ntruprime_sntrup761_keypair(kex); + break; + case KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512: + r = kex_kem_ntruprime_sntrup761_x25519_keypair(kex); + break; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC case KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256: @@ -390,10 +393,6 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) case KEX_C25519_SHA256: r = kex_c25519_dec(kex, server_blob, &shared_secret); break; - case KEX_KEM_SNTRUP761X25519_SHA512: - r = kex_kem_sntrup761x25519_dec(kex, server_blob, - &shared_secret); - break; ///// OQS_TEMPLATE_FRAGMENT_ADD_REPLY_SWITCH_CASES_START case KEX_KEM_FRODOKEM_640_AES_SHA256: r = kex_kem_frodokem_640_aes_dec(kex, server_blob, &shared_secret); @@ -506,6 +505,12 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) case KEX_KEM_ML_KEM_1024_SHA384: r = kex_kem_ml_kem_1024_dec(kex, server_blob, &shared_secret); break; + case KEX_KEM_NTRUPRIME_SNTRUP761_SHA512: + r = kex_kem_ntruprime_sntrup761_dec(kex, server_blob, &shared_secret); + break; + case KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512: + r = kex_kem_ntruprime_sntrup761_x25519_dec(kex, server_blob, &shared_secret); + break; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC case KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256: @@ -714,10 +719,6 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; - case KEX_KEM_SNTRUP761X25519_SHA512: - r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, - &server_pubkey, &shared_secret); - break; ///// OQS_TEMPLATE_FRAGMENT_ADD_INIT_SWITCH_CASES_START case KEX_KEM_FRODOKEM_640_AES_SHA256: r = kex_kem_frodokem_640_aes_enc(kex, client_pubkey, @@ -867,6 +868,14 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) r = kex_kem_ml_kem_1024_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; + case KEX_KEM_NTRUPRIME_SNTRUP761_SHA512: + r = kex_kem_ntruprime_sntrup761_enc(kex, client_pubkey, + &server_pubkey, &shared_secret); + break; + case KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512: + r = kex_kem_ntruprime_sntrup761_x25519_enc(kex, client_pubkey, + &server_pubkey, &shared_secret); + break; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC case KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256: diff --git a/kexoqs.c b/kexoqs.c index 5012bf44d3c0..070086f3190c 100644 --- a/kexoqs.c +++ b/kexoqs.c @@ -1283,4 +1283,44 @@ int kex_kem_ml_kem_1024_dec(struct kex *kex, OQS_KEM_free(kem); return r; } +/*--------------------------------------------------- + * NTRUPRIME_SNTRUP761 METHODS + *--------------------------------------------------- + */ +int kex_kem_ntruprime_sntrup761_keypair(struct kex *kex) +{ + OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ntruprime_sntrup761); + if (kem == NULL) { + return SSH_ERR_ALLOC_FAIL; + } + int r = kex_kem_generic_keypair(kem, kex); + OQS_KEM_free(kem); + return r; +} +int kex_kem_ntruprime_sntrup761_enc(struct kex *kex, + const struct sshbuf *client_blob, + struct sshbuf **server_blobp, + struct sshbuf **shared_secretp) +{ + OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ntruprime_sntrup761); + if (kem == NULL) { + return SSH_ERR_ALLOC_FAIL; + } + int r = kex_kem_generic_enc(kem, kex, client_blob, server_blobp, shared_secretp); + OQS_KEM_free(kem); + return r; +} + +int kex_kem_ntruprime_sntrup761_dec(struct kex *kex, + const struct sshbuf *server_blob, + struct sshbuf **shared_secretp) +{ + OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ntruprime_sntrup761); + if (kem == NULL) { + return SSH_ERR_ALLOC_FAIL; + } + int r = kex_kem_generic_dec(kem, kex, server_blob, shared_secretp); + OQS_KEM_free(kem); + return r; +} ///// OQS_TEMPLATE_FRAGMENT_DEFINE_KEX_METHODS_END diff --git a/kexoqsx25519.c b/kexoqsx25519.c index ccba8a2530c5..26c3482258e2 100644 --- a/kexoqsx25519.c +++ b/kexoqsx25519.c @@ -579,4 +579,45 @@ int kex_kem_ml_kem_768_x25519_dec(struct kex *kex, OQS_KEM_free(kem); return r; } +/*--------------------------------------------------------------- + * NTRUPRIME_SNTRUP761_X25519 METHODS + *--------------------------------------------------------------- + */ +int kex_kem_ntruprime_sntrup761_x25519_keypair(struct kex *kex) +{ + OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ntruprime_sntrup761); + if (kem == NULL) { + return SSH_ERR_ALLOC_FAIL; + } + int r = kex_kem_generic_with_x25519_keypair(kem, kex); + OQS_KEM_free(kem); + return r; +} + +int kex_kem_ntruprime_sntrup761_x25519_enc(struct kex *kex, + const struct sshbuf *client_blob, + struct sshbuf **server_blobp, + struct sshbuf **shared_secretp) +{ + OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ntruprime_sntrup761); + if (kem == NULL) { + return SSH_ERR_ALLOC_FAIL; + } + int r = kex_kem_generic_with_x25519_enc(kem, kex, client_blob, server_blobp, shared_secretp); + OQS_KEM_free(kem); + return r; +} + +int kex_kem_ntruprime_sntrup761_x25519_dec(struct kex *kex, + const struct sshbuf *server_blobp, + struct sshbuf **shared_secretp) +{ + OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ntruprime_sntrup761); + if (kem == NULL) { + return SSH_ERR_ALLOC_FAIL; + } + int r = kex_kem_generic_with_x25519_dec(kem, kex, server_blobp, shared_secretp); + OQS_KEM_free(kem); + return r; +} ///// OQS_TEMPLATE_FRAGMENT_DEFINE_KEX_WITH_X25519_METHODS_END diff --git a/monitor.c b/monitor.c index cf31bc3b5ab6..600f0893bba3 100644 --- a/monitor.c +++ b/monitor.c @@ -1748,7 +1748,6 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) # endif #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; - kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; ///// OQS_TEMPLATE_FRAGMENT_APPLY_KEYSTATE_START kex->kex[KEX_KEM_FRODOKEM_640_AES_SHA256] = kex_gen_server; kex->kex[KEX_KEM_FRODOKEM_640_AES_X25519_SHA256] = kex_gen_server; @@ -1787,6 +1786,8 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) kex->kex[KEX_KEM_ML_KEM_768_SHA256] = kex_gen_server; kex->kex[KEX_KEM_ML_KEM_768_X25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_ML_KEM_1024_SHA384] = kex_gen_server; + kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_SHA512] = kex_gen_server; + kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512] = kex_gen_server; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC kex->kex[KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256] = kex_gen_server; diff --git a/myproposal.h b/myproposal.h index b833aa9970b4..8e4c6f2b14f5 100644 --- a/myproposal.h +++ b/myproposal.h @@ -28,7 +28,6 @@ // OQS-TODO: should I add the PQ auth methods here? they were not added in 7.9 branch... #define KEX_SERVER_KEX \ - "sntrup761x25519-sha512@openssh.com," \ "curve25519-sha256," \ "curve25519-sha256@libssh.org," \ "ecdh-sha2-nistp256," \ @@ -103,7 +102,9 @@ "mlkem768nistp256-sha256," \ "mlkem768x25519-sha256," \ "ml-kem-1024-sha384," \ - "mlkem1024nistp384-sha384" + "mlkem1024nistp384-sha384," \ + "sntrup761-sha512," \ + "sntrup761x25519-sha512@openssh.com" /*/// OQS_TEMPLATE_FRAGMENT_ADD_SERVER_KEXS_END */ #define KEX_CLIENT_KEX KEX_SERVER_KEX diff --git a/oqs-template/generate.yml b/oqs-template/generate.yml index ddd9b065825b..8e448dce84c3 100644 --- a/oqs-template/generate.yml +++ b/oqs-template/generate.yml @@ -316,6 +316,16 @@ kexs: name: 'nistp384' openssl_nid: 'NID_secp384r1' pretty_name: 'mlkem1024nistp384-sha384' + - + family: 'NTRU-Prime' + name: 'ntruprime_sntrup761' + hash: 'sha512' + pretty_name: 'sntrup761-sha512' + mix_with: + - + name: 'x25519' + x25519: true + pretty_name: 'sntrup761x25519-sha512@openssh.com' sigs: - diff --git a/oqs-test/try_connection.py b/oqs-test/try_connection.py index fe4c210ee495..b092d99e744a 100644 --- a/oqs-test/try_connection.py +++ b/oqs-test/try_connection.py @@ -78,6 +78,8 @@ "mlkem768x25519-sha256", "ml-kem-1024-sha384", "mlkem1024nistp384-sha384", + "sntrup761-sha512", + "sntrup761x25519-sha512@openssh.com", ##### OQS_TEMPLATE_FRAGMENT_LIST_ALL_KEXS_END ] @@ -108,6 +110,7 @@ "ssh-mayo5", "ssh-ecdsa-nistp521-mayo5", ##### OQS_TEMPLATE_FRAGMENT_LIST_ALL_SIGS_END + "ssh-ed25519", # Classical signature algorithm for OpenSSH interop testing ] def do_handshake(ssh, sshd, test_sig, test_kex): @@ -144,11 +147,11 @@ def do_handshake(ssh, sshd, test_sig, test_kex): print("Success! Key Exchange Algorithm: {}. Signature Algorithm: {}.".format(test_kex, test_sig)) -def try_handshake(ssh, sshd, dorandom="random"): +def try_handshake(ssh, sshd, test_kexes, test_sigs, dorandom="random"): if dorandom!="random": - for test_kex in kexs: - for test_sig in sigs: - if dorandom=="doall" or (dorandom=="doone" and (test_kex==kexs[0] or test_sig==sigs[0])): + for test_kex in test_kexes: + for test_sig in test_sigs: + if dorandom=="doall" or (dorandom=="doone" and (test_kex==test_kexes[0] or test_sig==test_sigs[0])): do_handshake(ssh, sshd, test_sig, test_kex) else: test_sig = random.choice(sigs) @@ -158,9 +161,13 @@ def try_handshake(ssh, sshd, dorandom="random"): if __name__ == '__main__': parser = argparse.ArgumentParser(description="Test connections between ssh and sshd using PQ algorithms.") parser.add_argument("--ssh", default=os.path.abspath('ssh'), type=str, help="Override the ssh binary.") + parser.add_argument("--kex", choices=kexs, help="Specific KEX algorithm to test.") + parser.add_argument("--sig", choices=sigs, help="Specific SIG algorithm to test.") parser.add_argument("--sshd", default=os.path.abspath('sshd'), type=str, help="Override the sshd binary.") parser.add_argument("dorandom", type=str, default="random", choices=["doall", "doone", "random"], help="Slice of test cases to run.") args = parser.parse_args() - try_handshake(args.ssh, args.sshd, args.dorandom) + test_kexes = [args.kex] if args.kex else kexs + test_sigs = [args.sig] if args.sig else sigs + try_handshake(args.ssh, args.sshd, test_kexes, test_sigs, args.dorandom) diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c index dc1014ea4492..181ca0834d57 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c @@ -151,7 +151,6 @@ do_kex_with_key(char *kex, int keytype, int bits) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; - server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; server2->kex->load_host_public_key = server->kex->load_host_public_key; server2->kex->load_host_private_key = server->kex->load_host_private_key; server2->kex->sign = server->kex->sign; @@ -203,8 +202,5 @@ kex_tests(void) do_kex("diffie-hellman-group-exchange-sha1"); do_kex("diffie-hellman-group14-sha1"); do_kex("diffie-hellman-group1-sha1"); -# ifdef USE_SNTRUP761X25519 - do_kex("sntrup761x25519-sha512@openssh.com"); -# endif /* USE_SNTRUP761X25519 */ #endif /* WITH_OPENSSL */ } diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 635ebc13bbb5..1a3281c4c9e3 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -474,6 +474,8 @@ keygrab_ssh2(con *c) c->c_ssh->kex->kex[KEX_KEM_ML_KEM_768_SHA256] = kex_gen_client; c->c_ssh->kex->kex[KEX_KEM_ML_KEM_768_X25519_SHA256] = kex_gen_client; c->c_ssh->kex->kex[KEX_KEM_ML_KEM_1024_SHA384] = kex_gen_client; + c->c_ssh->kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_SHA512] = kex_gen_client; + c->c_ssh->kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512] = kex_gen_client; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC c->c_ssh->kex->kex[KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256] = kex_gen_client; @@ -507,7 +509,6 @@ keygrab_ssh2(con *c) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ ///// OQS_TEMPLATE_FRAGMENT_ASSIGN_KEX_GEN_CLIENT_END - c->c_ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); /* * do the key-exchange until an error occurs or until diff --git a/ssh_api.c b/ssh_api.c index 9ddbccad2914..b45d85b7da10 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -167,6 +167,8 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_KEM_ML_KEM_768_SHA256] = kex_gen_server; ssh->kex->kex[KEX_KEM_ML_KEM_768_X25519_SHA256] = kex_gen_server; ssh->kex->kex[KEX_KEM_ML_KEM_1024_SHA384] = kex_gen_server; + ssh->kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_SHA512] = kex_gen_server; + ssh->kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512] = kex_gen_server; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256] = kex_gen_server; @@ -200,7 +202,6 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ ///// OQS_TEMPLATE_FRAGMENT_POINT_TO_KEX_GEN_SERVER_END - ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; ssh->kex->load_host_public_key=&_ssh_host_public_key; ssh->kex->load_host_private_key=&_ssh_host_private_key; ssh->kex->sign=&_ssh_host_key_sign; @@ -256,6 +257,8 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_KEM_ML_KEM_768_SHA256] = kex_gen_client; ssh->kex->kex[KEX_KEM_ML_KEM_768_X25519_SHA256] = kex_gen_client; ssh->kex->kex[KEX_KEM_ML_KEM_1024_SHA384] = kex_gen_client; + ssh->kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512] = kex_gen_client; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256] = kex_gen_client; @@ -289,7 +292,6 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ ///// OQS_TEMPLATE_FRAGMENT_POINT_TO_KEX_GEN_CLIENT_END - ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } *sshp = ssh; diff --git a/sshconnect2.c b/sshconnect2.c index c67007466672..55855fd010e2 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -315,6 +315,8 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, ssh->kex->kex[KEX_KEM_ML_KEM_768_SHA256] = kex_gen_client; ssh->kex->kex[KEX_KEM_ML_KEM_768_X25519_SHA256] = kex_gen_client; ssh->kex->kex[KEX_KEM_ML_KEM_1024_SHA384] = kex_gen_client; + ssh->kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512] = kex_gen_client; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256] = kex_gen_client; @@ -348,7 +350,6 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ ///// OQS_TEMPLATE_FRAGMENT_POINT_TO_KEX_GEN_END - ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); diff --git a/sshd.c b/sshd.c index 200b775d01fb..aecee65106a6 100644 --- a/sshd.c +++ b/sshd.c @@ -2468,6 +2468,8 @@ do_ssh2_kex(struct ssh *ssh) kex->kex[KEX_KEM_ML_KEM_768_SHA256] = kex_gen_server; kex->kex[KEX_KEM_ML_KEM_768_X25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_ML_KEM_1024_SHA384] = kex_gen_server; + kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_SHA512] = kex_gen_server; + kex->kex[KEX_KEM_NTRUPRIME_SNTRUP761_X25519_SHA512] = kex_gen_server; #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC kex->kex[KEX_KEM_FRODOKEM_640_AES_ECDH_NISTP256_SHA256] = kex_gen_server; @@ -2501,7 +2503,6 @@ do_ssh2_kex(struct ssh *ssh) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ ///// OQS_TEMPLATE_FRAGMENT_POINT_TO_KEX_GEN_END - kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index;