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

randombit / botan / 23486908132

24 Mar 2026 10:53AM UTC coverage: 89.449% (-2.4%) from 91.889%
23486908132

push

github

web-flow
Merge pull request #5479 from randombit/jack/aria-hwaes

Add ARIA implementation using hardware AES instructions

105058 of 117450 relevant lines covered (89.45%)

11951797.05 hits per line

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

91.18
/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/buffer_stuffer.h>
12
#include <botan/internal/dl_scheme.h>
13
#include <botan/internal/keypair.h>
14
#include <botan/internal/monty_exp.h>
15
#include <botan/internal/pk_ops_impl.h>
16

17
namespace Botan {
18

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

95
#if defined(BOTAN_HAS_OAEP) && defined(BOTAN_HAS_SHA_256)
96
   const std::string padding = "OAEP(SHA-256)";
3✔
97
#else
98
   const std::string padding = "Raw";
99
#endif
100

101
   return KeyPair::encryption_consistency_check(rng, *this, padding);
3✔
102
}
3✔
103

104
namespace {
105

106
/**
107
* ElGamal encryption operation
108
*/
109
class ElGamal_Encryption_Operation final : public PK_Ops::Encryption_with_Padding {
×
110
   public:
111
      ElGamal_Encryption_Operation(const std::shared_ptr<const DL_PublicKey>& key, std::string_view padding) :
26✔
112
            PK_Ops::Encryption_with_Padding(padding), m_key(key) {
26✔
113
         const size_t powm_window = 4;
26✔
114
         m_monty_y_p = monty_precompute(m_key->group()._monty_params_p(), m_key->public_key(), powm_window);
26✔
115
      }
26✔
116

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

119
      size_t max_ptext_input_bits() const override { return m_key->group().p_bits() - 1; }
42✔
120

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

123
   private:
124
      std::shared_ptr<const DL_PublicKey> m_key;
125
      std::shared_ptr<const Montgomery_Exponentiation_State> m_monty_y_p;
126
};
127

128
std::vector<uint8_t> ElGamal_Encryption_Operation::raw_encrypt(std::span<const uint8_t> ptext,
26✔
129
                                                               RandomNumberGenerator& rng) {
130
   const BigInt m(ptext);
26✔
131

132
   const auto& group = m_key->group();
26✔
133

134
   if(m >= group.get_p()) {
26✔
135
      throw Invalid_Argument("ElGamal encryption: Input is too large");
×
136
   }
137

138
   /*
139
   Some weird PGP implementations generate keys using bad parameters
140
   which result in easily breakable encryption if short exponents are
141
   used during encryption. To avoid this problem, always use full size
142
   exponents.
143

144
   See https://eprint.iacr.org/2021/923
145
   */
146
   const size_t k_bits = group.p_bits() - 1;
26✔
147
   const BigInt k(rng, k_bits, false);
26✔
148

149
   const BigInt a = group.power_g_p(k, k_bits);
26✔
150
   const BigInt b = group.multiply_mod_p(m, monty_execute(*m_monty_y_p, k, k_bits).value());
26✔
151

152
   const size_t p_bytes = group.p_bytes();
26✔
153
   std::vector<uint8_t> ctext(2 * p_bytes);
26✔
154
   BufferStuffer stuffer(ctext);
26✔
155
   a.serialize_to(stuffer.next(p_bytes));
26✔
156
   b.serialize_to(stuffer.next(p_bytes));
26✔
157
   return ctext;
26✔
158
}
26✔
159

160
/**
161
* ElGamal decryption operation
162
*/
163
class ElGamal_Decryption_Operation final : public PK_Ops::Decryption_with_Padding {
×
164
   public:
165
      ElGamal_Decryption_Operation(const std::shared_ptr<const DL_PrivateKey>& key,
43✔
166
                                   std::string_view padding,
167
                                   RandomNumberGenerator& rng) :
43✔
168
            PK_Ops::Decryption_with_Padding(padding),
169
            m_key(key),
86✔
170
            m_blinder(
86✔
171
               m_key->group()._reducer_mod_p(),
43✔
172
               rng,
173
               [](const BigInt& k) { return k; },
43✔
174
               [this](const BigInt& k) { return powermod_x_p(k); }) {}
86✔
175

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

178
      secure_vector<uint8_t> raw_decrypt(std::span<const uint8_t> ctext) override;
179

180
   private:
181
      BigInt powermod_x_p(const BigInt& v) const { return m_key->group().power_b_p(v, m_key->private_key()); }
43✔
182

183
      std::shared_ptr<const DL_PrivateKey> m_key;
184
      Blinder m_blinder;
185
};
186

187
secure_vector<uint8_t> ElGamal_Decryption_Operation::raw_decrypt(std::span<const uint8_t> ctext) {
535✔
188
   const auto& group = m_key->group();
535✔
189

190
   const size_t p_bytes = group.p_bytes();
535✔
191

192
   if(ctext.size() != 2 * p_bytes) {
535✔
193
      throw Invalid_Argument("ElGamal decryption: Invalid message");
×
194
   }
195

196
   BigInt a(ctext.first(p_bytes));
535✔
197
   const BigInt b(ctext.last(p_bytes));
535✔
198

199
   if(a >= group.get_p() || b >= group.get_p()) {
535✔
200
      throw Invalid_Argument("ElGamal decryption: Invalid message");
×
201
   }
202

203
   a = m_blinder.blind(a);
535✔
204

205
   const BigInt r = group.multiply_mod_p(group.inverse_mod_p(powermod_x_p(a)), b);
535✔
206

207
   return m_blinder.unblind(r).serialize<secure_vector<uint8_t>>(p_bytes);
1,070✔
208
}
535✔
209

210
}  // namespace
211

212
std::unique_ptr<PK_Ops::Encryption> ElGamal_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/,
44✔
213
                                                                            std::string_view params,
214
                                                                            std::string_view provider) const {
215
   if(provider == "base" || provider.empty()) {
50✔
216
      return std::make_unique<ElGamal_Encryption_Operation>(this->m_public_key, params);
26✔
217
   }
218
   throw Provider_Not_Found(algo_name(), provider);
36✔
219
}
220

221
std::unique_ptr<PK_Ops::Decryption> ElGamal_PrivateKey::create_decryption_op(RandomNumberGenerator& rng,
112✔
222
                                                                             std::string_view params,
223
                                                                             std::string_view provider) const {
224
   if(provider == "base" || provider.empty()) {
135✔
225
      return std::make_unique<ElGamal_Decryption_Operation>(this->m_private_key, params, rng);
43✔
226
   }
227
   throw Provider_Not_Found(algo_name(), provider);
138✔
228
}
229

230
}  // 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

© 2026 Coveralls, Inc