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

randombit / botan / 4871472097

03 May 2023 12:13PM UTC coverage: 91.724% (+0.005%) from 91.719%
4871472097

Pull #3539

github

Pull Request #3539: FIX: allow custom KEX logic for TLS 1.2 server

77612 of 84615 relevant lines covered (91.72%)

11978513.0 hits per line

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

91.35
/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/dl_scheme.h>
11
#include <botan/internal/pk_ops_impl.h>
12
#include <botan/internal/monty_exp.h>
13
#include <botan/internal/keypair.h>
14
#include <botan/internal/blinding.h>
15

16
namespace Botan {
17

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

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

29
size_t ElGamal_PublicKey::estimated_strength() const
4✔
30
   {
31
   return m_public_key->estimated_strength();
4✔
32
   }
33

34
size_t ElGamal_PublicKey::key_length() const
×
35
   {
36
   return m_public_key->p_bits();
×
37
   }
38

39
AlgorithmIdentifier ElGamal_PublicKey::algorithm_identifier() const
44✔
40
   {
41
   return AlgorithmIdentifier(
44✔
42
      object_identifier(),
88✔
43
      m_public_key->group().DER_encode(DL_Group_Format::ANSI_X9_42));
132✔
44
   }
45

46
std::vector<uint8_t> ElGamal_PublicKey::public_key_bits() const
17✔
47
   {
48
   return m_public_key->DER_encode();
17✔
49
   }
50

51
const BigInt& ElGamal_PublicKey::get_int_field(std::string_view field) const
6✔
52
   {
53
   return m_public_key->get_int_field(algo_name(), field);
6✔
54
   }
55

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

61
ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng,
8✔
62
                                       const DL_Group& group)
8✔
63
   {
64
   m_private_key = std::make_shared<DL_PrivateKey>(group, rng);
8✔
65
   m_public_key = m_private_key->public_key();
8✔
66
   }
8✔
67

68
ElGamal_PrivateKey::ElGamal_PrivateKey(const DL_Group& group,
25✔
69
                                       const BigInt& x)
25✔
70
   {
71
   m_private_key = std::make_shared<DL_PrivateKey>(group, x);
25✔
72
   m_public_key = m_private_key->public_key();
25✔
73
   }
25✔
74

75
ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
14✔
76
                                       std::span<const uint8_t> key_bits)
14✔
77
   {
78
   m_private_key = std::make_shared<DL_PrivateKey>(alg_id, key_bits, DL_Group_Format::ANSI_X9_42);
14✔
79
   m_public_key = m_private_key->public_key();
14✔
80
   }
14✔
81

82
std::unique_ptr<Public_Key> ElGamal_PrivateKey::public_key() const
3✔
83
   {
84
   return std::unique_ptr<Public_Key>(new ElGamal_PublicKey(m_public_key));
6✔
85
   }
86

87
const BigInt& ElGamal_PrivateKey::get_int_field(std::string_view field) const
2✔
88
   {
89
   return m_private_key->get_int_field(algo_name(), field);
2✔
90
   }
91

92
secure_vector<uint8_t> ElGamal_PrivateKey::private_key_bits() const
31✔
93
   {
94
   return m_private_key->DER_encode();
31✔
95
   }
96

97
secure_vector<uint8_t> ElGamal_PrivateKey::raw_private_key_bits() const
×
98
   {
99
   return m_private_key->raw_private_key_bits();
×
100
   }
101

102
bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng,
3✔
103
                                   bool strong) const
104
   {
105
   if(!m_private_key->check_key(rng, strong))
3✔
106
      return false;
107

108
   return KeyPair::encryption_consistency_check(rng, *this, "OAEP(SHA-256)");
3✔
109
   }
110

111
namespace {
112

113
/**
114
* ElGamal encryption operation
115
*/
116
class ElGamal_Encryption_Operation final : public PK_Ops::Encryption_with_EME
×
117
   {
118
   public:
119

120
      ElGamal_Encryption_Operation(const std::shared_ptr<const DL_PublicKey>& key,
15✔
121
                                   std::string_view eme) :
15✔
122
         PK_Ops::Encryption_with_EME(eme),
123
         m_key(key)
15✔
124
         {
125
         const size_t powm_window = 4;
15✔
126
         m_monty_y_p = monty_precompute(m_key->group().monty_params_p(),
30✔
127
                                        m_key->public_key(),
15✔
128
                                        powm_window);
15✔
129
         }
15✔
130

131
      size_t ciphertext_length(size_t /*ptext_len*/) const override
8✔
132
         {
133
         return 2*m_key->group().p_bytes();
8✔
134
         }
135

136
      size_t max_ptext_input_bits() const override
31✔
137
         {
138
         return m_key->group().p_bits() - 1;
31✔
139
         }
140

141
      secure_vector<uint8_t> raw_encrypt(const uint8_t msg[], size_t msg_len,
142
                                      RandomNumberGenerator& rng) override;
143

144
   private:
145
      std::shared_ptr<const DL_PublicKey> m_key;
146
      std::shared_ptr<const Montgomery_Exponentation_State> m_monty_y_p;
147
   };
148

149
secure_vector<uint8_t>
150
ElGamal_Encryption_Operation::raw_encrypt(const uint8_t msg[], size_t msg_len,
15✔
151
                                          RandomNumberGenerator& rng)
152
   {
153
   BigInt m(msg, msg_len);
15✔
154

155
   const auto& group = m_key->group();
15✔
156

157
   if(m >= group.get_p())
15✔
158
      throw Invalid_Argument("ElGamal encryption: Input is too large");
×
159

160
   /*
161
   Some weird PGP implementations generate keys using bad parameters
162
   which result in easily breakable encryption if short exponents are
163
   used during encryption. To avoid this problem, always use full size
164
   exponents.
165

166
   See https://eprint.iacr.org/2021/923
167
   */
168
   const size_t k_bits = group.p_bits() - 1;
15✔
169
   const BigInt k(rng, k_bits, false);
15✔
170

171
   const BigInt a = group.power_g_p(k, k_bits);
15✔
172
   const BigInt b = group.multiply_mod_p(m, monty_execute(*m_monty_y_p, k, k_bits));
15✔
173

174
   return BigInt::encode_fixed_length_int_pair(a, b, group.p_bytes());
15✔
175
   }
60✔
176

177
/**
178
* ElGamal decryption operation
179
*/
180
class ElGamal_Decryption_Operation final : public PK_Ops::Decryption_with_EME
×
181
   {
182
   public:
183

184
      ElGamal_Decryption_Operation(const std::shared_ptr<const DL_PrivateKey>& key,
32✔
185
                                   std::string_view eme,
186
                                   RandomNumberGenerator& rng) :
32✔
187
         PK_Ops::Decryption_with_EME(eme),
188
         m_key(key),
64✔
189
         m_blinder(m_key->group().get_p(),
64✔
190
                   rng,
191
                   [](const BigInt& k) { return k; },
32✔
192
                   [this](const BigInt& k) { return powermod_x_p(k); })
32✔
193
         {}
32✔
194

195
      size_t plaintext_length(size_t /*ctext_len*/) const override
8✔
196
         {
197
         return m_key->group().p_bytes();
8✔
198
         }
199

200
      secure_vector<uint8_t> raw_decrypt(const uint8_t msg[], size_t msg_len) override;
201
   private:
202
      BigInt powermod_x_p(const BigInt& v) const
524✔
203
         {
204
         return m_key->group().power_b_p(v, m_key->private_key());
32✔
205
         }
206

207
      std::shared_ptr<const DL_PrivateKey> m_key;
208
      Blinder m_blinder;
209
   };
210

211
secure_vector<uint8_t>
212
ElGamal_Decryption_Operation::raw_decrypt(const uint8_t msg[], size_t msg_len)
492✔
213
   {
214
   const auto& group = m_key->group();
492✔
215

216
   const size_t p_bytes = group.p_bytes();
492✔
217

218
   if(msg_len != 2 * p_bytes)
492✔
219
      throw Invalid_Argument("ElGamal decryption: Invalid message");
×
220

221
   BigInt a(msg, p_bytes);
492✔
222
   const BigInt b(msg + p_bytes, p_bytes);
492✔
223

224
   if(a >= group.get_p() || b >= group.get_p())
492✔
225
      throw Invalid_Argument("ElGamal decryption: Invalid message");
×
226

227
   a = m_blinder.blind(a);
492✔
228

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

231
   return BigInt::encode_1363(m_blinder.unblind(r), p_bytes);
984✔
232
   }
1,476✔
233

234
}
235

236
std::unique_ptr<PK_Ops::Encryption>
237
ElGamal_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/,
33✔
238
                                        std::string_view params,
239
                                        std::string_view provider) const
240
   {
241
   if(provider == "base" || provider.empty())
39✔
242
      return std::make_unique<ElGamal_Encryption_Operation>(this->m_public_key, params);
15✔
243
   throw Provider_Not_Found(algo_name(), provider);
36✔
244
   }
245

246
std::unique_ptr<PK_Ops::Decryption>
247
ElGamal_PrivateKey::create_decryption_op(RandomNumberGenerator& rng,
101✔
248
                                         std::string_view params,
249
                                         std::string_view provider) const
250
   {
251
   if(provider == "base" || provider.empty())
124✔
252
      return std::make_unique<ElGamal_Decryption_Operation>(this->m_private_key, params, rng);
32✔
253
   throw Provider_Not_Found(algo_name(), provider);
138✔
254
   }
255

256
}
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