Coverage Report

Created: 2020-10-17 06:46

/src/botan/src/lib/pubkey/elgamal/elgamal.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* ElGamal
3
* (C) 1999-2007,2018,2019 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/elgamal.h>
9
#include <botan/internal/pk_ops_impl.h>
10
#include <botan/internal/monty_exp.h>
11
#include <botan/keypair.h>
12
#include <botan/blinding.h>
13
14
namespace Botan {
15
16
/*
17
* ElGamal_PublicKey Constructor
18
*/
19
ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& group, const BigInt& y) :
20
   DL_Scheme_PublicKey(group, y)
21
0
   {
22
0
   }
Unexecuted instantiation: Botan::ElGamal_PublicKey::ElGamal_PublicKey(Botan::DL_Group const&, Botan::BigInt const&)
Unexecuted instantiation: Botan::ElGamal_PublicKey::ElGamal_PublicKey(Botan::DL_Group const&, Botan::BigInt const&)
23
24
/*
25
* ElGamal_PrivateKey Constructor
26
*/
27
ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng,
28
                                       const DL_Group& group,
29
                                       const BigInt& x)
30
0
   {
31
0
   m_x = x;
32
0
   m_group = group;
33
0
34
0
   if(m_x.is_zero())
35
0
      {
36
0
      const size_t exp_bits = m_group.exponent_bits();
37
0
      m_x.randomize(rng, exp_bits);
38
0
      m_y = m_group.power_g_p(m_x, exp_bits);
39
0
      }
40
0
   else
41
0
      {
42
0
      m_y = m_group.power_g_p(m_x, m_group.p_bits());
43
0
      }
44
0
   }
Unexecuted instantiation: Botan::ElGamal_PrivateKey::ElGamal_PrivateKey(Botan::RandomNumberGenerator&, Botan::DL_Group const&, Botan::BigInt const&)
Unexecuted instantiation: Botan::ElGamal_PrivateKey::ElGamal_PrivateKey(Botan::RandomNumberGenerator&, Botan::DL_Group const&, Botan::BigInt const&)
45
46
ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
47
                                       const secure_vector<uint8_t>& key_bits) :
48
   DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
49
0
   {
50
0
   m_y = m_group.power_g_p(m_x, m_group.p_bits());
51
0
   }
Unexecuted instantiation: Botan::ElGamal_PrivateKey::ElGamal_PrivateKey(Botan::AlgorithmIdentifier const&, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&)
Unexecuted instantiation: Botan::ElGamal_PrivateKey::ElGamal_PrivateKey(Botan::AlgorithmIdentifier const&, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&)
52
53
/*
54
* Check Private ElGamal Parameters
55
*/
56
bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng,
57
                                   bool strong) const
58
0
   {
59
0
   if(!DL_Scheme_PrivateKey::check_key(rng, strong))
60
0
      return false;
61
0
62
0
   if(!strong)
63
0
      return true;
64
0
65
0
   return KeyPair::encryption_consistency_check(rng, *this, "OAEP(SHA-256)");
66
0
   }
67
68
namespace {
69
70
/**
71
* ElGamal encryption operation
72
*/
73
class ElGamal_Encryption_Operation final : public PK_Ops::Encryption_with_EME
74
   {
75
   public:
76
77
0
      size_t ciphertext_length(size_t) const override { return 2*m_group.p_bytes(); }
78
79
0
      size_t max_raw_input_bits() const override { return m_group.p_bits() - 1; }
80
81
      ElGamal_Encryption_Operation(const ElGamal_PublicKey& key, const std::string& eme);
82
83
      secure_vector<uint8_t> raw_encrypt(const uint8_t msg[], size_t msg_len,
84
                                      RandomNumberGenerator& rng) override;
85
86
   private:
87
      const DL_Group m_group;
88
      std::shared_ptr<const Montgomery_Exponentation_State> m_monty_y_p;
89
   };
90
91
ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key,
92
                                                           const std::string& eme) :
93
   PK_Ops::Encryption_with_EME(eme),
94
   m_group(key.get_group())
95
0
   {
96
0
   const size_t powm_window = 4;
97
0
   m_monty_y_p = monty_precompute(key.get_group().monty_params_p(),
98
0
                                  key.get_y(),
99
0
                                  powm_window);
100
0
   }
101
102
secure_vector<uint8_t>
103
ElGamal_Encryption_Operation::raw_encrypt(const uint8_t msg[], size_t msg_len,
104
                                          RandomNumberGenerator& rng)
105
0
   {
106
0
   BigInt m(msg, msg_len);
107
0
108
0
   if(m >= m_group.get_p())
109
0
      throw Invalid_Argument("ElGamal encryption: Input is too large");
110
0
111
0
   const size_t k_bits = m_group.exponent_bits();
112
0
   const BigInt k(rng, k_bits);
113
0
114
0
   const BigInt a = m_group.power_g_p(k, k_bits);
115
0
   const BigInt b = m_group.multiply_mod_p(m, monty_execute(*m_monty_y_p, k, k_bits));
116
0
117
0
   return BigInt::encode_fixed_length_int_pair(a, b, m_group.p_bytes());
118
0
   }
119
120
/**
121
* ElGamal decryption operation
122
*/
123
class ElGamal_Decryption_Operation final : public PK_Ops::Decryption_with_EME
124
   {
125
   public:
126
127
      ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key,
128
                                   const std::string& eme,
129
                                   RandomNumberGenerator& rng);
130
131
0
      size_t plaintext_length(size_t) const override { return m_group.p_bytes(); }
132
133
      secure_vector<uint8_t> raw_decrypt(const uint8_t msg[], size_t msg_len) override;
134
   private:
135
      BigInt powermod_x_p(const BigInt& v) const
136
0
         {
137
0
         const size_t powm_window = 4;
138
0
         auto powm_v_p = monty_precompute(m_monty_p, v, powm_window);
139
0
         return monty_execute(*powm_v_p, m_x, m_x_bits);
140
0
         }
141
142
      const DL_Group m_group;
143
      const BigInt& m_x;
144
      const size_t m_x_bits;
145
      std::shared_ptr<const Montgomery_Params> m_monty_p;
146
      Blinder m_blinder;
147
   };
148
149
ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key,
150
                                                           const std::string& eme,
151
                                                           RandomNumberGenerator& rng) :
152
   PK_Ops::Decryption_with_EME(eme),
153
   m_group(key.get_group()),
154
   m_x(key.get_x()),
155
   m_x_bits(m_x.bits()),
156
   m_monty_p(key.get_group().monty_params_p()),
157
   m_blinder(m_group.get_p(),
158
             rng,
159
0
             [](const BigInt& k) { return k; },
160
0
             [this](const BigInt& k) { return powermod_x_p(k); })
161
0
   {
162
0
   }
163
164
secure_vector<uint8_t>
165
ElGamal_Decryption_Operation::raw_decrypt(const uint8_t msg[], size_t msg_len)
166
0
   {
167
0
   const size_t p_bytes = m_group.p_bytes();
168
0
169
0
   if(msg_len != 2 * p_bytes)
170
0
      throw Invalid_Argument("ElGamal decryption: Invalid message");
171
0
172
0
   BigInt a(msg, p_bytes);
173
0
   const BigInt b(msg + p_bytes, p_bytes);
174
0
175
0
   if(a >= m_group.get_p() || b >= m_group.get_p())
176
0
      throw Invalid_Argument("ElGamal decryption: Invalid message");
177
0
178
0
   a = m_blinder.blind(a);
179
0
180
0
   const BigInt r = m_group.multiply_mod_p(m_group.inverse_mod_p(powermod_x_p(a)), b);
181
0
182
0
   return BigInt::encode_1363(m_blinder.unblind(r), p_bytes);
183
0
   }
184
185
}
186
187
std::unique_ptr<PK_Ops::Encryption>
188
ElGamal_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/,
189
                                        const std::string& params,
190
                                        const std::string& provider) const
191
0
   {
192
0
   if(provider == "base" || provider.empty())
193
0
      return std::unique_ptr<PK_Ops::Encryption>(new ElGamal_Encryption_Operation(*this, params));
194
0
   throw Provider_Not_Found(algo_name(), provider);
195
0
   }
196
197
std::unique_ptr<PK_Ops::Decryption>
198
ElGamal_PrivateKey::create_decryption_op(RandomNumberGenerator& rng,
199
                                         const std::string& params,
200
                                         const std::string& provider) const
201
0
   {
202
0
   if(provider == "base" || provider.empty())
203
0
      return std::unique_ptr<PK_Ops::Decryption>(new ElGamal_Decryption_Operation(*this, params, rng));
204
0
   throw Provider_Not_Found(algo_name(), provider);
205
0
   }
206
207
}