/src/botan/src/lib/pubkey/ecdh/ecdh.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * ECDH implemenation |
3 | | * (C) 2007 Manuel Hartl, FlexSecure GmbH |
4 | | * 2007 Falko Strenzke, FlexSecure GmbH |
5 | | * 2008-2010 Jack Lloyd |
6 | | * |
7 | | * Botan is released under the Simplified BSD License (see license.txt) |
8 | | */ |
9 | | |
10 | | #include <botan/ecdh.h> |
11 | | |
12 | | #include <botan/bigint.h> |
13 | | #include <botan/internal/pk_ops_impl.h> |
14 | | |
15 | | namespace Botan { |
16 | | |
17 | 0 | std::unique_ptr<Public_Key> ECDH_PrivateKey::public_key() const { |
18 | 0 | return std::make_unique<ECDH_PublicKey>(domain(), _public_ec_point()); |
19 | 0 | } |
20 | | |
21 | | namespace { |
22 | | |
23 | | /** |
24 | | * ECDH operation |
25 | | */ |
26 | | class ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF { |
27 | | public: |
28 | | ECDH_KA_Operation(const ECDH_PrivateKey& key, std::string_view kdf, RandomNumberGenerator& rng) : |
29 | 1.72k | PK_Ops::Key_Agreement_with_KDF(kdf), |
30 | 1.72k | m_group(key.domain()), |
31 | 1.72k | m_l_times_priv(mul_cofactor_inv(m_group, key._private_key())), |
32 | 1.72k | m_rng(rng) {} |
33 | | |
34 | 0 | size_t agreed_value_size() const override { return m_group.get_p_bytes(); } |
35 | | |
36 | 1.72k | secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override { |
37 | 1.72k | const auto input_point = [&] { |
38 | 1.72k | if(m_group.has_cofactor()) { |
39 | 0 | #if defined(BOTAN_HAS_LEGACY_EC_POINT) |
40 | 0 | return EC_AffinePoint(m_group, m_group.get_cofactor() * m_group.OS2ECP(w, w_len)); |
41 | | #else |
42 | | throw Not_Implemented( |
43 | | "Support for DH with cofactor adjustment not available in this build configuration"); |
44 | | #endif |
45 | 1.72k | } else { |
46 | 1.72k | if(auto point = EC_AffinePoint::deserialize(m_group, {w, w_len})) { |
47 | 1.72k | return *point; |
48 | 1.72k | } else { |
49 | 0 | throw Decoding_Error("ECDH - Invalid elliptic curve point: not on curve"); |
50 | 0 | } |
51 | 1.72k | } |
52 | 1.72k | }(); |
53 | | |
54 | | // Typical specs (such as BSI's TR-03111 Section 4.3.1) require that |
55 | | // we check the resulting point of the multiplication to not be the |
56 | | // point at infinity. However, since we ensure that our ECC private |
57 | | // scalar can never be zero, checking the peer's input point is |
58 | | // equivalent. |
59 | 1.72k | if(input_point.is_identity()) { |
60 | 0 | throw Decoding_Error("ECDH - Invalid elliptic curve point: identity"); |
61 | 0 | } |
62 | | |
63 | 1.72k | return input_point.mul_x_only(m_l_times_priv, m_rng); |
64 | 1.72k | } |
65 | | |
66 | | private: |
67 | 1.72k | static EC_Scalar mul_cofactor_inv(const EC_Group& group, const EC_Scalar& x) { |
68 | | // We implement BSI TR-03111 ECKAEG which only matters in the (rare/deprecated) |
69 | | // case of a curve with cofactor. |
70 | | |
71 | 1.72k | if(group.has_cofactor()) { |
72 | | // We could precompute this but cofactors are rare |
73 | 0 | return x * EC_Scalar::from_bigint(group, group.get_cofactor()).invert_vartime(); |
74 | 1.72k | } else { |
75 | 1.72k | return x; |
76 | 1.72k | } |
77 | 1.72k | } |
78 | | |
79 | | const EC_Group m_group; |
80 | | const EC_Scalar m_l_times_priv; |
81 | | RandomNumberGenerator& m_rng; |
82 | | }; |
83 | | |
84 | | } // namespace |
85 | | |
86 | 0 | std::unique_ptr<Private_Key> ECDH_PublicKey::generate_another(RandomNumberGenerator& rng) const { |
87 | 0 | return std::make_unique<ECDH_PrivateKey>(rng, domain()); |
88 | 0 | } |
89 | | |
90 | 12.8k | std::vector<uint8_t> ECDH_PublicKey::public_value(EC_Point_Format format) const { |
91 | 12.8k | return _public_ec_point().serialize(format); |
92 | 12.8k | } |
93 | | |
94 | | std::unique_ptr<PK_Ops::Key_Agreement> ECDH_PrivateKey::create_key_agreement_op(RandomNumberGenerator& rng, |
95 | | std::string_view params, |
96 | 1.72k | std::string_view provider) const { |
97 | 1.72k | if(provider == "base" || provider.empty()) { |
98 | 1.72k | return std::make_unique<ECDH_KA_Operation>(*this, params, rng); |
99 | 1.72k | } |
100 | | |
101 | 0 | throw Provider_Not_Found(algo_name(), provider); |
102 | 1.72k | } |
103 | | |
104 | | } // namespace Botan |