• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 12548935066

30 Dec 2024 04:04PM UTC coverage: 91.262% (+0.05%) from 91.208%
12548935066

Pull #4507

github

web-flow
Merge 3aca433ed into 9b8f3cc80
Pull Request #4507: Remove support for Kyber r3 key exchange in TLS

93394 of 102336 relevant lines covered (91.26%)

11408572.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.53
/src/lib/pubkey/elgamal/elgamal.cpp
1
/*
2
* ElGamal
3
* (C) 1999-2007,2018,2019,2023 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/elgamal.h>
9

10
#include <botan/internal/blinding.h>
11
#include <botan/internal/dl_scheme.h>
12
#include <botan/internal/keypair.h>
13
#include <botan/internal/monty_exp.h>
14
#include <botan/internal/pk_ops_impl.h>
15

16
namespace Botan {
17

18
ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& group, const BigInt& y) {
3✔
19
   m_public_key = std::make_shared<DL_PublicKey>(group, y);
3✔
20
}
3✔
21

22
ElGamal_PublicKey::ElGamal_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
4✔
23
   m_public_key = std::make_shared<DL_PublicKey>(alg_id, key_bits, DL_Group_Format::ANSI_X9_42);
4✔
24
}
4✔
25

26
size_t ElGamal_PublicKey::estimated_strength() const {
8✔
27
   return m_public_key->estimated_strength();
8✔
28
}
29

30
size_t ElGamal_PublicKey::key_length() const {
×
31
   return m_public_key->p_bits();
×
32
}
33

34
AlgorithmIdentifier ElGamal_PublicKey::algorithm_identifier() const {
44✔
35
   return AlgorithmIdentifier(object_identifier(), m_public_key->group().DER_encode(DL_Group_Format::ANSI_X9_42));
88✔
36
}
37

38
std::vector<uint8_t> ElGamal_PublicKey::raw_public_key_bits() const {
1✔
39
   return m_public_key->public_key_as_bytes();
1✔
40
}
41

42
std::vector<uint8_t> ElGamal_PublicKey::public_key_bits() const {
19✔
43
   return m_public_key->DER_encode();
19✔
44
}
45

46
const BigInt& ElGamal_PublicKey::get_int_field(std::string_view field) const {
6✔
47
   return m_public_key->get_int_field(algo_name(), field);
6✔
48
}
49

50
std::unique_ptr<Private_Key> ElGamal_PublicKey::generate_another(RandomNumberGenerator& rng) const {
1✔
51
   return std::make_unique<ElGamal_PrivateKey>(rng, m_public_key->group());
2✔
52
}
53

54
bool ElGamal_PublicKey::check_key(RandomNumberGenerator& rng, bool strong) const {
5✔
55
   return m_public_key->check_key(rng, strong);
5✔
56
}
57

58
ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group) {
9✔
59
   m_private_key = std::make_shared<DL_PrivateKey>(group, rng);
9✔
60
   m_public_key = m_private_key->public_key();
9✔
61
}
9✔
62

63
ElGamal_PrivateKey::ElGamal_PrivateKey(const DL_Group& group, const BigInt& x) {
25✔
64
   m_private_key = std::make_shared<DL_PrivateKey>(group, x);
25✔
65
   m_public_key = m_private_key->public_key();
25✔
66
}
25✔
67

68
ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
14✔
69
   m_private_key = std::make_shared<DL_PrivateKey>(alg_id, key_bits, DL_Group_Format::ANSI_X9_42);
14✔
70
   m_public_key = m_private_key->public_key();
14✔
71
}
14✔
72

73
std::unique_ptr<Public_Key> ElGamal_PrivateKey::public_key() const {
4✔
74
   return std::unique_ptr<Public_Key>(new ElGamal_PublicKey(m_public_key));
4✔
75
}
76

77
const BigInt& ElGamal_PrivateKey::get_int_field(std::string_view field) const {
2✔
78
   return m_private_key->get_int_field(algo_name(), field);
2✔
79
}
80

81
secure_vector<uint8_t> ElGamal_PrivateKey::private_key_bits() const {
33✔
82
   return m_private_key->DER_encode();
33✔
83
}
84

85
secure_vector<uint8_t> ElGamal_PrivateKey::raw_private_key_bits() const {
×
86
   return m_private_key->raw_private_key_bits();
×
87
}
88

89
bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const {
3✔
90
   if(!m_private_key->check_key(rng, strong)) {
3✔
91
      return false;
92
   }
93

94
   return KeyPair::encryption_consistency_check(rng, *this, "OAEP(SHA-256)");
3✔
95
}
96

97
namespace {
98

99
/**
100
* ElGamal encryption operation
101
*/
102
class ElGamal_Encryption_Operation final : public PK_Ops::Encryption_with_EME {
×
103
   public:
104
      ElGamal_Encryption_Operation(const std::shared_ptr<const DL_PublicKey>& key, std::string_view eme) :
15✔
105
            PK_Ops::Encryption_with_EME(eme), m_key(key) {
15✔
106
         const size_t powm_window = 4;
15✔
107
         m_monty_y_p = monty_precompute(m_key->group().monty_params_p(), m_key->public_key(), powm_window);
15✔
108
      }
15✔
109

110
      size_t ciphertext_length(size_t /*ptext_len*/) const override { return 2 * m_key->group().p_bytes(); }
8✔
111

112
      size_t max_ptext_input_bits() const override { return m_key->group().p_bits() - 1; }
31✔
113

114
      std::vector<uint8_t> raw_encrypt(std::span<const uint8_t> ptext, RandomNumberGenerator& rng) override;
115

116
   private:
117
      std::shared_ptr<const DL_PublicKey> m_key;
118
      std::shared_ptr<const Montgomery_Exponentation_State> m_monty_y_p;
119
};
120

121
std::vector<uint8_t> ElGamal_Encryption_Operation::raw_encrypt(std::span<const uint8_t> ptext,
15✔
122
                                                               RandomNumberGenerator& rng) {
123
   BigInt m(ptext);
15✔
124

125
   const auto& group = m_key->group();
15✔
126

127
   if(m >= group.get_p()) {
15✔
128
      throw Invalid_Argument("ElGamal encryption: Input is too large");
×
129
   }
130

131
   /*
132
   Some weird PGP implementations generate keys using bad parameters
133
   which result in easily breakable encryption if short exponents are
134
   used during encryption. To avoid this problem, always use full size
135
   exponents.
136

137
   See https://eprint.iacr.org/2021/923
138
   */
139
   const size_t k_bits = group.p_bits() - 1;
15✔
140
   const BigInt k(rng, k_bits, false);
15✔
141

142
   const BigInt a = group.power_g_p(k, k_bits);
15✔
143
   const BigInt b = group.multiply_mod_p(m, monty_execute(*m_monty_y_p, k, k_bits));
15✔
144

145
   return unlock(BigInt::encode_fixed_length_int_pair(a, b, group.p_bytes()));
45✔
146
}
60✔
147

148
/**
149
* ElGamal decryption operation
150
*/
151
class ElGamal_Decryption_Operation final : public PK_Ops::Decryption_with_EME {
×
152
   public:
153
      ElGamal_Decryption_Operation(const std::shared_ptr<const DL_PrivateKey>& key,
32✔
154
                                   std::string_view eme,
155
                                   RandomNumberGenerator& rng) :
32✔
156
            PK_Ops::Decryption_with_EME(eme),
157
            m_key(key),
64✔
158
            m_blinder(
64✔
159
               m_key->group().get_p(),
32✔
160
               rng,
161
               [](const BigInt& k) { return k; },
32✔
162
               [this](const BigInt& k) { return powermod_x_p(k); }) {}
64✔
163

164
      size_t plaintext_length(size_t /*ctext_len*/) const override { return m_key->group().p_bytes(); }
8✔
165

166
      secure_vector<uint8_t> raw_decrypt(std::span<const uint8_t> ctext) override;
167

168
   private:
169
      BigInt powermod_x_p(const BigInt& v) const { return m_key->group().power_b_p(v, m_key->private_key()); }
32✔
170

171
      std::shared_ptr<const DL_PrivateKey> m_key;
172
      Blinder m_blinder;
173
};
174

175
secure_vector<uint8_t> ElGamal_Decryption_Operation::raw_decrypt(std::span<const uint8_t> ctext) {
492✔
176
   const auto& group = m_key->group();
492✔
177

178
   const size_t p_bytes = group.p_bytes();
492✔
179

180
   if(ctext.size() != 2 * p_bytes) {
492✔
181
      throw Invalid_Argument("ElGamal decryption: Invalid message");
×
182
   }
183

184
   BigInt a(ctext.first(p_bytes));
492✔
185
   const BigInt b(ctext.last(p_bytes));
492✔
186

187
   if(a >= group.get_p() || b >= group.get_p()) {
492✔
188
      throw Invalid_Argument("ElGamal decryption: Invalid message");
×
189
   }
190

191
   a = m_blinder.blind(a);
492✔
192

193
   const BigInt r = group.multiply_mod_p(group.inverse_mod_p(powermod_x_p(a)), b);
984✔
194

195
   return m_blinder.unblind(r).serialize<secure_vector<uint8_t>>(p_bytes);
984✔
196
}
1,476✔
197

198
}  // namespace
199

200
std::unique_ptr<PK_Ops::Encryption> ElGamal_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/,
33✔
201
                                                                            std::string_view params,
202
                                                                            std::string_view provider) const {
203
   if(provider == "base" || provider.empty()) {
39✔
204
      return std::make_unique<ElGamal_Encryption_Operation>(this->m_public_key, params);
15✔
205
   }
206
   throw Provider_Not_Found(algo_name(), provider);
36✔
207
}
208

209
std::unique_ptr<PK_Ops::Decryption> ElGamal_PrivateKey::create_decryption_op(RandomNumberGenerator& rng,
101✔
210
                                                                             std::string_view params,
211
                                                                             std::string_view provider) const {
212
   if(provider == "base" || provider.empty()) {
124✔
213
      return std::make_unique<ElGamal_Decryption_Operation>(this->m_private_key, params, rng);
32✔
214
   }
215
   throw Provider_Not_Found(algo_name(), provider);
138✔
216
}
217

218
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc