From 133efd7b72b2441a7d1ede61f665e01484451201 Mon Sep 17 00:00:00 2001 From: Rene Meusel Date: Tue, 31 Oct 2023 17:24:29 +0100 Subject: [PATCH] Non KEX-algos may choose to not implement ::generate_another() Some algorithms (like HSS/LMS) cannot even implement it at all, because their public key does not provide enough information about the private key's internal parameters. --- src/lib/pubkey/pk_keys.h | 4 +++- src/tests/test_pubkey.cpp | 28 ++++++++++++++++++---------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/lib/pubkey/pk_keys.h b/src/lib/pubkey/pk_keys.h index b490e48fe25..5f838c98a97 100644 --- a/src/lib/pubkey/pk_keys.h +++ b/src/lib/pubkey/pk_keys.h @@ -104,7 +104,9 @@ class BOTAN_PUBLIC_API(3, 0) Asymmetric_Key { /** * Generate another (cryptographically independent) key pair using the - * same algorithm parameters as this key. + * same algorithm parameters as this key. This is most useful for algorithms + * that support PublicKeyOperation::KeyAgreement to generate a fitting ephemeral + * key pair. For other key types it might throw NotImplemented. */ virtual std::unique_ptr generate_another(RandomNumberGenerator& rng) const = 0; }; diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp index 864f836cab8..b50a7e36ff4 100644 --- a/src/tests/test_pubkey.cpp +++ b/src/tests/test_pubkey.cpp @@ -602,16 +602,24 @@ std::vector PK_Key_Generation_Test::run() { "public_key has same encoding", Botan::X509::PEM_encode(key), Botan::X509::PEM_encode(*public_key)); // Test generation of another key pair from a given (abstract) asymmetric key - auto sk2 = public_key->generate_another(Test::rng()); - auto pk2 = sk2->public_key(); - - result.test_eq("new private key has the same name", sk2->algo_name(), key.algo_name()); - result.test_eq("new public key has the same name", pk2->algo_name(), public_key->algo_name()); - result.test_eq( - "new private key has the same est. strength", sk2->estimated_strength(), key.estimated_strength()); - result.test_eq( - "new public key has the same est. strength", pk2->estimated_strength(), public_key->estimated_strength()); - result.test_ne("new private keys are different keys", sk2->private_key_bits(), key.private_key_bits()); + // KEX algorithms must support that (so that we can generate ephemeral keys in + // an abstract fashion). For other algorithms it's a nice-to-have. + try { + auto sk2 = public_key->generate_another(Test::rng()); + auto pk2 = sk2->public_key(); + + result.test_eq("new private key has the same name", sk2->algo_name(), key.algo_name()); + result.test_eq("new public key has the same name", pk2->algo_name(), public_key->algo_name()); + result.test_eq( + "new private key has the same est. strength", sk2->estimated_strength(), key.estimated_strength()); + result.test_eq("new public key has the same est. strength", + pk2->estimated_strength(), + public_key->estimated_strength()); + result.test_ne("new private keys are different keys", sk2->private_key_bits(), key.private_key_bits()); + } catch(const Botan::Not_Implemented&) { + result.confirm("KEX algorithms are required to implement 'generate_another'", + !public_key->supports_operation(Botan::PublicKeyOperation::KeyAgreement)); + } // Test PEM public key round trips OK try {