Botan: src/engine/gnump/gnump_pk.cpp Source File

Botan 1.10.17

gnump_pk.cpp
Go to the documentation of this file.
1 /*
2 * GnuMP PK operations
3 * (C) 1999-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7
8 #include <botan/internal/gnump_engine.h>
9 #include <botan/internal/gmp_wrap.h>
10 #include <gmp.h>
11
12 /* GnuMP 5.0 and later have a side-channel resistent powm */
13 #if defined(HAVE_MPZ_POWM_SEC)
14 #undef mpz_powm
15 #define mpz_powm mpz_powm_sec
16 #endif
17
18 #if defined(BOTAN_HAS_RSA)
19 #include <botan/rsa.h>
20 #endif
21
22 #if defined(BOTAN_HAS_DSA)
23 #include <botan/dsa.h>
24 #endif
25
26 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
27 #include <botan/dh.h>
28 #endif
29
30 namespace Botan {
31
32 namespace {
33
34 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
35 class GMP_DH_KA_Operation : public PK_Ops::Key_Agreement
36 {
37 public:
38 GMP_DH_KA_Operation(const DH_PrivateKey& dh) :
39 x(dh.get_x()), p(dh.group_p()) {}
40
41 SecureVector<byte> agree(const byte w[], size_t w_len)
42 {
43 GMP_MPZ z(w, w_len);
44 mpz_powm(z.value, z.value, x.value, p.value);
45 return z.to_bytes();
46 }
47
48 private:
49 GMP_MPZ x, p;
50 };
51 #endif
52
53 #if defined(BOTAN_HAS_DSA)
54
55 class GMP_DSA_Signature_Operation : public PK_Ops::Signature
56 {
57 public:
58 GMP_DSA_Signature_Operation(const DSA_PrivateKey& dsa) :
59 x(dsa.get_x()),
60 p(dsa.group_p()),
61 q(dsa.group_q()),
62 g(dsa.group_g()),
63 q_bits(dsa.group_q().bits()) {}
64
65 size_t message_parts() const { return 2; }
66 size_t message_part_size() const { return (q_bits + 7) / 8; }
67 size_t max_input_bits() const { return q_bits; }
68
69 SecureVector<byte> sign(const byte msg[], size_t msg_len,
70 RandomNumberGenerator& rng);
71 private:
72 const GMP_MPZ x, p, q, g;
73 size_t q_bits;
74 };
75
76 SecureVector<byte>
77 GMP_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
78 RandomNumberGenerator& rng)
79 {
80 const size_t q_bytes = (q_bits + 7) / 8;
81
82 rng.add_entropy(msg, msg_len);
83
84 BigInt k_bn;
85 do
86 k_bn.randomize(rng, q_bits);
87 while(k_bn >= q.to_bigint());
88
89 GMP_MPZ i(msg, msg_len);
90 GMP_MPZ k(k_bn);
91
92 GMP_MPZ r;
93 mpz_powm(r.value, g.value, k.value, p.value);
94 mpz_mod(r.value, r.value, q.value);
95
96 mpz_invert(k.value, k.value, q.value);
97
98 GMP_MPZ s;
99 mpz_mul(s.value, x.value, r.value);
100 mpz_add(s.value, s.value, i.value);
101 mpz_mul(s.value, s.value, k.value);
102 mpz_mod(s.value, s.value, q.value);
103
104 if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0)
105 throw Internal_Error("GMP_DSA_Op::sign: r or s was zero");
106
107 SecureVector<byte> output(2*q_bytes);
108 r.encode(output, q_bytes);
109 s.encode(output + q_bytes, q_bytes);
110 return output;
111 }
112
113 class GMP_DSA_Verification_Operation : public PK_Ops::Verification
114 {
115 public:
116 GMP_DSA_Verification_Operation(const DSA_PublicKey& dsa) :
117 y(dsa.get_y()),
118 p(dsa.group_p()),
119 q(dsa.group_q()),
120 g(dsa.group_g()),
121 q_bits(dsa.group_q().bits()) {}
122
123 size_t message_parts() const { return 2; }
124 size_t message_part_size() const { return (q_bits + 7) / 8; }
125 size_t max_input_bits() const { return q_bits; }
126
127 bool with_recovery() const { return false; }
128
129 bool verify(const byte msg[], size_t msg_len,
130 const byte sig[], size_t sig_len);
131 private:
132 const GMP_MPZ y, p, q, g;
133 size_t q_bits;
134 };
135
136 bool GMP_DSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
137 const byte sig[], size_t sig_len)
138 {
139 const size_t q_bytes = q.bytes();
140
141 if(sig_len != 2*q_bytes || msg_len > q_bytes)
142 return false;
143
144 GMP_MPZ r(sig, q_bytes);
145 GMP_MPZ s(sig + q_bytes, q_bytes);
146 GMP_MPZ i(msg, msg_len);
147
148 if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0)
149 return false;
150 if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0)
151 return false;
152
153 if(mpz_invert(s.value, s.value, q.value) == 0)
154 return false;
155
156 GMP_MPZ si;
157 mpz_mul(si.value, s.value, i.value);
158 mpz_mod(si.value, si.value, q.value);
159 mpz_powm(si.value, g.value, si.value, p.value);
160
161 GMP_MPZ sr;
162 mpz_mul(sr.value, s.value, r.value);
163 mpz_mod(sr.value, sr.value, q.value);
164 mpz_powm(sr.value, y.value, sr.value, p.value);
165
166 mpz_mul(si.value, si.value, sr.value);
167 mpz_mod(si.value, si.value, p.value);
168 mpz_mod(si.value, si.value, q.value);
169
170 if(mpz_cmp(si.value, r.value) == 0)
171 return true;
172 return false;
173 }
174
175 #endif
176
177 #if defined(BOTAN_HAS_RSA)
178
179 class GMP_RSA_Private_Operation : public PK_Ops::Signature,
180 public PK_Ops::Decryption
181 {
182 public:
183 GMP_RSA_Private_Operation(const RSA_PrivateKey& rsa) :
184 mod(rsa.get_n()),
185 p(rsa.get_p()),
186 q(rsa.get_q()),
187 d1(rsa.get_d1()),
188 d2(rsa.get_d2()),
189 c(rsa.get_c()),
190 n_bits(rsa.get_n().bits())
191 {}
192
193 size_t max_input_bits() const { return (n_bits - 1); }
194
195 SecureVector<byte> sign(const byte msg[], size_t msg_len,
196 RandomNumberGenerator&)
197 {
198 BigInt m(msg, msg_len);
199 BigInt x = private_op(m);
200 return BigInt::encode_1363(x, (n_bits + 7) / 8);
201 }
202
203 SecureVector<byte> decrypt(const byte msg[], size_t msg_len)
204 {
205 BigInt m(msg, msg_len);
206 return BigInt::encode(private_op(m));
207 }
208
209 private:
210 BigInt private_op(const BigInt& m) const;
211
212 GMP_MPZ mod, p, q, d1, d2, c;
213 size_t n_bits;
214 };
215
216 BigInt GMP_RSA_Private_Operation::private_op(const BigInt& m) const
217 {
218 GMP_MPZ j1, j2, h(m);
219
220 mpz_powm(j1.value, h.value, d1.value, p.value);
221 mpz_powm(j2.value, h.value, d2.value, q.value);
222 mpz_sub(h.value, j1.value, j2.value);
223 mpz_mul(h.value, h.value, c.value);
224 mpz_mod(h.value, h.value, p.value);
225 mpz_mul(h.value, h.value, q.value);
226 mpz_add(h.value, h.value, j2.value);
227 return h.to_bigint();
228 }
229
230 class GMP_RSA_Public_Operation : public PK_Ops::Verification,
231 public PK_Ops::Encryption
232 {
233 public:
234 GMP_RSA_Public_Operation(const RSA_PublicKey& rsa) :
235 n(rsa.get_n()), e(rsa.get_e()), mod(rsa.get_n())
236 {}
237
238 size_t max_input_bits() const { return (n.bits() - 1); }
239 bool with_recovery() const { return true; }
240
241 SecureVector<byte> encrypt(const byte msg[], size_t msg_len,
242 RandomNumberGenerator&)
243 {
244 BigInt m(msg, msg_len);
245 return BigInt::encode_1363(public_op(m), n.bytes());
246 }
247
248 SecureVector<byte> verify_mr(const byte msg[], size_t msg_len)
249 {
250 BigInt m(msg, msg_len);
251 return BigInt::encode(public_op(m));
252 }
253
254 private:
255 BigInt public_op(const BigInt& m) const
256 {
257 if(m >= n)
258 throw Invalid_Argument("RSA public op - input is too large");
259
260 GMP_MPZ m_gmp(m);
261 mpz_powm(m_gmp.value, m_gmp.value, e.value, mod.value);
262 return m_gmp.to_bigint();
263 }
264
265 const BigInt& n;
266 const GMP_MPZ e, mod;
267 };
268
269 #endif
270
271 }
272
273 PK_Ops::Key_Agreement*
274 GMP_Engine::get_key_agreement_op(const Private_Key& key) const
275 {
276 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
277 if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key))
278 return new GMP_DH_KA_Operation(*dh);
279 #endif
280
281 return 0;
282 }
283
284 PK_Ops::Signature*
285 GMP_Engine::get_signature_op(const Private_Key& key) const
286 {
287 #if defined(BOTAN_HAS_RSA)
288 if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key))
289 return new GMP_RSA_Private_Operation(*s);
290 #endif
291
292 #if defined(BOTAN_HAS_DSA)
293 if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key))
294 return new GMP_DSA_Signature_Operation(*s);
295 #endif
296
297 return 0;
298 }
299
300 PK_Ops::Verification*
301 GMP_Engine::get_verify_op(const Public_Key& key) const
302 {
303 #if defined(BOTAN_HAS_RSA)
304 if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key))
305 return new GMP_RSA_Public_Operation(*s);
306 #endif
307
308 #if defined(BOTAN_HAS_DSA)
309 if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key))
310 return new GMP_DSA_Verification_Operation(*s);
311 #endif
312
313 return 0;
314 }
315
316 PK_Ops::Encryption*
317 GMP_Engine::get_encryption_op(const Public_Key& key) const
318 {
319 #if defined(BOTAN_HAS_RSA)
320 if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key))
321 return new GMP_RSA_Public_Operation(*s);
322 #endif
323
324 return 0;
325 }
326
327 PK_Ops::Decryption*
328 GMP_Engine::get_decryption_op(const Private_Key& key) const
329 {
330 #if defined(BOTAN_HAS_RSA)
331 if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key))
332 return new GMP_RSA_Private_Operation(*s);
333 #endif
334
335 return 0;
336 }
337
338 }
Botan::RandomNumberGenerator::add_entropy
virtual void add_entropy(const byte in[], size_t length)=0
Botan::GMP_Engine::get_key_agreement_op
PK_Ops::Key_Agreement * get_key_agreement_op(const Private_Key &key) const
Definition: gnump_pk.cpp:274
Botan::Private_Key
Definition: pk_keys.h:86
Botan::GMP_Engine::get_signature_op
PK_Ops::Signature * get_signature_op(const Private_Key &key) const
Definition: gnump_pk.cpp:285
Botan::PK_Ops::Signature
Definition: pk_ops.h:49
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::BigInt::encode
static SecureVector< byte > encode(const BigInt &n, Base base=Binary)
Definition: big_code.cpp:64
Botan::GMP_Engine::get_verify_op
PK_Ops::Verification * get_verify_op(const Public_Key &key) const
Definition: gnump_pk.cpp:301
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::DSA_PrivateKey
Definition: dsa.h:45
Botan::GMP_Engine::get_encryption_op
PK_Ops::Encryption * get_encryption_op(const Public_Key &key) const
Definition: gnump_pk.cpp:317
Botan::RSA_PrivateKey
Definition: rsa.h:47
Botan
Definition: algo_base.h:14
Botan::Public_Key
Definition: pk_keys.h:21
Botan::DSA_PublicKey
Definition: dsa.h:21
Botan::GMP_Engine::get_decryption_op
PK_Ops::Decryption * get_decryption_op(const Private_Key &key) const
Definition: gnump_pk.cpp:328
Botan::PK_Ops::Decryption
Definition: pk_ops.h:35
Botan::DH_PrivateKey
Definition: dh.h:48
Botan::PK_Ops::Encryption
Definition: pk_ops.h:21
Botan::BigInt::encode_1363
static SecureVector< byte > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:78
Botan::PK_Ops::Verification
Definition: pk_ops.h:85
Botan::RSA_PublicKey
Definition: rsa.h:21