diff options
-rw-r--r-- | src/lib/ffi/ffi.h | 2 | ||||
-rw-r--r-- | src/lib/ffi/ffi_pk_op.cpp | 7 | ||||
-rw-r--r-- | src/lib/prov/pkcs11/p11_ecdh.cpp | 1 | ||||
-rw-r--r-- | src/lib/pubkey/curve25519/curve25519.cpp | 2 | ||||
-rw-r--r-- | src/lib/pubkey/dh/dh.cpp | 2 | ||||
-rw-r--r-- | src/lib/pubkey/ecdh/ecdh.cpp | 2 | ||||
-rw-r--r-- | src/lib/pubkey/ecies/ecies.cpp | 2 | ||||
-rw-r--r-- | src/lib/pubkey/pk_ops.h | 6 | ||||
-rw-r--r-- | src/lib/pubkey/pubkey.cpp | 5 | ||||
-rw-r--r-- | src/lib/pubkey/pubkey.h | 17 | ||||
-rw-r--r-- | src/tests/test_pubkey.cpp | 9 |
11 files changed, 47 insertions, 8 deletions
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index fe847e94a..96cdf1de4 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -1203,6 +1203,8 @@ BOTAN_PUBLIC_API(2,0) int botan_pk_op_key_agreement_destroy(botan_pk_op_ka_t op) BOTAN_PUBLIC_API(2,0) int botan_pk_op_key_agreement_export_public(botan_privkey_t key, uint8_t out[], size_t* out_len); +BOTAN_PUBLIC_API(2,8) int botan_pk_op_key_agreement_size(botan_pk_op_ka_t op, size_t* out_len); + BOTAN_PUBLIC_API(2,0) int botan_pk_op_key_agreement(botan_pk_op_ka_t op, uint8_t out[], size_t* out_len, diff --git a/src/lib/ffi/ffi_pk_op.cpp b/src/lib/ffi/ffi_pk_op.cpp index 5f2437a10..4e548fff8 100644 --- a/src/lib/ffi/ffi_pk_op.cpp +++ b/src/lib/ffi/ffi_pk_op.cpp @@ -221,6 +221,13 @@ int botan_pk_op_key_agreement_export_public(botan_privkey_t key, }); } +int botan_pk_op_key_agreement_size(botan_pk_op_ka_t op, size_t* out_len) + { + return BOTAN_FFI_DO(Botan::PK_Key_Agreement, op, o, { + *out_len = o.agreed_value_size(); + }); + } + int botan_pk_op_key_agreement(botan_pk_op_ka_t op, uint8_t out[], size_t* out_len, const uint8_t other_key[], size_t other_key_len, diff --git a/src/lib/prov/pkcs11/p11_ecdh.cpp b/src/lib/prov/pkcs11/p11_ecdh.cpp index d7b0fae5c..0cd671bcb 100644 --- a/src/lib/prov/pkcs11/p11_ecdh.cpp +++ b/src/lib/prov/pkcs11/p11_ecdh.cpp @@ -45,6 +45,7 @@ class PKCS11_ECDH_KA_Operation final : public PK_Ops::Key_Agreement : PK_Ops::Key_Agreement(), m_key(key), m_mechanism(MechanismWrapper::create_ecdh_mechanism(params)) {} + size_t agreed_value_size() const override { return m_key.domain().get_p_bytes(); } /// The encoding in V2.20 was not specified and resulted in different implementations choosing different encodings. /// Applications relying only on a V2.20 encoding (e.g. the DER variant) other than the one specified now (raw) may not work with all V2.30 compliant tokens. diff --git a/src/lib/pubkey/curve25519/curve25519.cpp b/src/lib/pubkey/curve25519/curve25519.cpp index c43f526a8..68b4f5a4f 100644 --- a/src/lib/pubkey/curve25519/curve25519.cpp +++ b/src/lib/pubkey/curve25519/curve25519.cpp @@ -118,6 +118,8 @@ class Curve25519_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF PK_Ops::Key_Agreement_with_KDF(kdf), m_key(key) {} + size_t agreed_value_size() const { return 32; } + secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override { return m_key.agree(w, w_len); diff --git a/src/lib/pubkey/dh/dh.cpp b/src/lib/pubkey/dh/dh.cpp index ae6e9c589..75b0db2f6 100644 --- a/src/lib/pubkey/dh/dh.cpp +++ b/src/lib/pubkey/dh/dh.cpp @@ -93,6 +93,8 @@ class DH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF [this](const BigInt& k) { return m_powermod_x_p(inverse_mod(k, m_p)); }) {} + size_t agreed_value_size() const override { return m_p.bytes(); } + secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override; private: const BigInt& m_p; diff --git a/src/lib/pubkey/ecdh/ecdh.cpp b/src/lib/pubkey/ecdh/ecdh.cpp index 59f245a00..e7e49a74f 100644 --- a/src/lib/pubkey/ecdh/ecdh.cpp +++ b/src/lib/pubkey/ecdh/ecdh.cpp @@ -34,6 +34,8 @@ class ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF m_l_times_priv = m_group.inverse_mod_order(m_group.get_cofactor()) * key.private_value(); } + size_t agreed_value_size() const override { return m_group.get_p_bytes(); } + secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override { PointGFp input_point = m_group.get_cofactor() * m_group.OS2ECP(w, w_len); diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp index 8f5c445ed..ebfd9121e 100644 --- a/src/lib/pubkey/ecies/ecies.cpp +++ b/src/lib/pubkey/ecies/ecies.cpp @@ -64,6 +64,8 @@ class ECIES_ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF { } + size_t agreed_value_size() const { return m_key.domain().get_p_bytes(); } + secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override { const EC_Group& group = m_key.domain(); diff --git a/src/lib/pubkey/pk_ops.h b/src/lib/pubkey/pk_ops.h index 3f794f00d..63ef9fa9b 100644 --- a/src/lib/pubkey/pk_ops.h +++ b/src/lib/pubkey/pk_ops.h @@ -118,8 +118,10 @@ class BOTAN_PUBLIC_API(2,0) Key_Agreement { public: virtual secure_vector<uint8_t> agree(size_t key_len, - const uint8_t other_key[], size_t other_key_len, - const uint8_t salt[], size_t salt_len) = 0; + const uint8_t other_key[], size_t other_key_len, + const uint8_t salt[], size_t salt_len) = 0; + + virtual size_t agreed_value_size() const = 0; virtual ~Key_Agreement() = default; }; diff --git a/src/lib/pubkey/pubkey.cpp b/src/lib/pubkey/pubkey.cpp index fef81a620..bb0170548 100644 --- a/src/lib/pubkey/pubkey.cpp +++ b/src/lib/pubkey/pubkey.cpp @@ -210,6 +210,11 @@ PK_Key_Agreement::PK_Key_Agreement(PK_Key_Agreement&& other) : m_op(std::move(other.m_op)) {} +size_t PK_Key_Agreement::agreed_value_size() const + { + return m_op->agreed_value_size(); + } + SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, const uint8_t in[], size_t in_len, const uint8_t salt[], diff --git a/src/lib/pubkey/pubkey.h b/src/lib/pubkey/pubkey.h index a1404135d..43e1f987a 100644 --- a/src/lib/pubkey/pubkey.h +++ b/src/lib/pubkey/pubkey.h @@ -412,7 +412,7 @@ class BOTAN_PUBLIC_API(2,0) PK_Verifier final }; /** -* Key used for key agreement +* Object used for key agreement */ class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final { @@ -454,7 +454,7 @@ class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final PK_Key_Agreement& operator=(const PK_Key_Agreement&) = delete; PK_Key_Agreement(const PK_Key_Agreement&) = delete; - /* + /** * Perform Key Agreement Operation * @param key_len the desired key output size * @param in the other parties key @@ -468,7 +468,7 @@ class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final const uint8_t params[], size_t params_len) const; - /* + /** * Perform Key Agreement Operation * @param key_len the desired key output size * @param in the other parties key @@ -485,7 +485,7 @@ class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final params, params_len); } - /* + /** * Perform Key Agreement Operation * @param key_len the desired key output size * @param in the other parties key @@ -501,7 +501,7 @@ class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final params.length()); } - /* + /** * Perform Key Agreement Operation * @param key_len the desired key output size * @param in the other parties key @@ -516,6 +516,13 @@ class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final params.length()); } + /** + * Return the underlying size of the value that is agreed. + * If derive_key is called with a length of 0 with a "Raw" + * KDF, it will return a value of this size. + */ + size_t agreed_value_size() const; + private: std::unique_ptr<PK_Ops::Key_Agreement> m_op; }; diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp index bc2d19bb7..765e7e396 100644 --- a/src/tests/test_pubkey.cpp +++ b/src/tests/test_pubkey.cpp @@ -509,7 +509,14 @@ Test::Result PK_Key_Agreement_Test::run_one_test(const std::string& header, cons try { kas.reset(new Botan::PK_Key_Agreement(*privkey, Test::rng(), kdf, provider)); - result.test_eq(provider, "agreement", kas->derive_key(key_len, pubkey).bits_of(), shared); + + auto derived_key = kas->derive_key(key_len, pubkey).bits_of(); + result.test_eq(provider, "agreement", derived_key, shared); + + if(key_len == 0 && kdf == "Raw") + { + result.test_eq("Expected size", derived_key.size(), kas->agreed_value_size()); + } } catch(Botan::Lookup_Error&) { |