1
/*************************************************
2
* GMP Engine Source File *
3
* (C) 1999-2007 The Botan Project *
4
*************************************************/
6
#include <botan/eng_gmp.h>
7
#include <botan/gmp_wrap.h>
14
/*************************************************
16
*************************************************/
17
class GMP_IF_Op : public IF_Operation
20
BigInt public_op(const BigInt&) const;
21
BigInt private_op(const BigInt&) const;
23
IF_Operation* clone() const { return new GMP_IF_Op(*this); }
25
GMP_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&,
26
const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn,
27
const BigInt& d2_bn, const BigInt& c_bn) :
28
e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {}
30
const GMP_MPZ e, n, p, q, d1, d2, c;
33
/*************************************************
34
* GMP IF Public Operation *
35
*************************************************/
36
BigInt GMP_IF_Op::public_op(const BigInt& i_bn) const
39
mpz_powm(i.value, i.value, e.value, n.value);
43
/*************************************************
44
* GMP IF Private Operation *
45
*************************************************/
46
BigInt GMP_IF_Op::private_op(const BigInt& i_bn) const
48
if(mpz_cmp_ui(p.value, 0) == 0)
49
throw Internal_Error("GMP_IF_Op::private_op: No private key");
51
GMP_MPZ j1, j2, h(i_bn);
53
mpz_powm(j1.value, h.value, d1.value, p.value);
54
mpz_powm(j2.value, h.value, d2.value, q.value);
55
mpz_sub(h.value, j1.value, j2.value);
56
mpz_mul(h.value, h.value, c.value);
57
mpz_mod(h.value, h.value, p.value);
58
mpz_mul(h.value, h.value, q.value);
59
mpz_add(h.value, h.value, j2.value);
63
/*************************************************
65
*************************************************/
66
class GMP_DSA_Op : public DSA_Operation
69
bool verify(const byte[], u32bit, const byte[], u32bit) const;
70
SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
72
DSA_Operation* clone() const { return new GMP_DSA_Op(*this); }
74
GMP_DSA_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
75
x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
77
const GMP_MPZ x, y, p, q, g;
80
/*************************************************
81
* GMP DSA Verify Operation *
82
*************************************************/
83
bool GMP_DSA_Op::verify(const byte msg[], u32bit msg_len,
84
const byte sig[], u32bit sig_len) const
86
const u32bit q_bytes = q.bytes();
88
if(sig_len != 2*q_bytes || msg_len > q_bytes)
91
GMP_MPZ r(sig, q_bytes);
92
GMP_MPZ s(sig + q_bytes, q_bytes);
93
GMP_MPZ i(msg, msg_len);
95
if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0)
97
if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0)
100
if(mpz_invert(s.value, s.value, q.value) == 0)
104
mpz_mul(si.value, s.value, i.value);
105
mpz_mod(si.value, si.value, q.value);
106
mpz_powm(si.value, g.value, si.value, p.value);
109
mpz_mul(sr.value, s.value, r.value);
110
mpz_mod(sr.value, sr.value, q.value);
111
mpz_powm(sr.value, y.value, sr.value, p.value);
113
mpz_mul(si.value, si.value, sr.value);
114
mpz_mod(si.value, si.value, p.value);
115
mpz_mod(si.value, si.value, q.value);
117
if(mpz_cmp(si.value, r.value) == 0)
122
/*************************************************
123
* GMP DSA Sign Operation *
124
*************************************************/
125
SecureVector<byte> GMP_DSA_Op::sign(const byte in[], u32bit length,
126
const BigInt& k_bn) const
128
if(mpz_cmp_ui(x.value, 0) == 0)
129
throw Internal_Error("GMP_DSA_Op::sign: No private key");
131
GMP_MPZ i(in, length);
135
mpz_powm(r.value, g.value, k.value, p.value);
136
mpz_mod(r.value, r.value, q.value);
138
mpz_invert(k.value, k.value, q.value);
141
mpz_mul(s.value, x.value, r.value);
142
mpz_add(s.value, s.value, i.value);
143
mpz_mul(s.value, s.value, k.value);
144
mpz_mod(s.value, s.value, q.value);
146
if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0)
147
throw Internal_Error("GMP_DSA_Op::sign: r or s was zero");
149
const u32bit q_bytes = q.bytes();
151
SecureVector<byte> output(2*q_bytes);
152
r.encode(output, q_bytes);
153
s.encode(output + q_bytes, q_bytes);
157
/*************************************************
159
*************************************************/
160
class GMP_NR_Op : public NR_Operation
163
SecureVector<byte> verify(const byte[], u32bit) const;
164
SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
166
NR_Operation* clone() const { return new GMP_NR_Op(*this); }
168
GMP_NR_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
169
x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
171
const GMP_MPZ x, y, p, q, g;
174
/*************************************************
175
* GMP NR Verify Operation *
176
*************************************************/
177
SecureVector<byte> GMP_NR_Op::verify(const byte sig[], u32bit sig_len) const
179
const u32bit q_bytes = q.bytes();
181
if(sig_len != 2*q_bytes)
184
GMP_MPZ c(sig, q_bytes);
185
GMP_MPZ d(sig + q_bytes, q_bytes);
187
if(mpz_cmp_ui(c.value, 0) <= 0 || mpz_cmp(c.value, q.value) >= 0 ||
188
mpz_cmp(d.value, q.value) >= 0)
189
throw Invalid_Argument("GMP_NR_Op::verify: Invalid signature");
192
mpz_powm(i1.value, g.value, d.value, p.value);
193
mpz_powm(i2.value, y.value, c.value, p.value);
194
mpz_mul(i1.value, i1.value, i2.value);
195
mpz_mod(i1.value, i1.value, p.value);
196
mpz_sub(i1.value, c.value, i1.value);
197
mpz_mod(i1.value, i1.value, q.value);
198
return BigInt::encode(i1.to_bigint());
201
/*************************************************
202
* GMP NR Sign Operation *
203
*************************************************/
204
SecureVector<byte> GMP_NR_Op::sign(const byte in[], u32bit length,
205
const BigInt& k_bn) const
207
if(mpz_cmp_ui(x.value, 0) == 0)
208
throw Internal_Error("GMP_NR_Op::sign: No private key");
210
GMP_MPZ f(in, length);
213
if(mpz_cmp(f.value, q.value) >= 0)
214
throw Invalid_Argument("GMP_NR_Op::sign: Input is out of range");
217
mpz_powm(c.value, g.value, k.value, p.value);
218
mpz_add(c.value, c.value, f.value);
219
mpz_mod(c.value, c.value, q.value);
220
mpz_mul(d.value, x.value, c.value);
221
mpz_sub(d.value, k.value, d.value);
222
mpz_mod(d.value, d.value, q.value);
224
if(mpz_cmp_ui(c.value, 0) == 0)
225
throw Internal_Error("Default_NR_Op::sign: c was zero");
227
const u32bit q_bytes = q.bytes();
228
SecureVector<byte> output(2*q_bytes);
229
c.encode(output, q_bytes);
230
d.encode(output + q_bytes, q_bytes);
234
/*************************************************
235
* GMP ElGamal Operation *
236
*************************************************/
237
class GMP_ELG_Op : public ELG_Operation
240
SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
241
BigInt decrypt(const BigInt&, const BigInt&) const;
243
ELG_Operation* clone() const { return new GMP_ELG_Op(*this); }
245
GMP_ELG_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
246
x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
251
/*************************************************
252
* GMP ElGamal Encrypt Operation *
253
*************************************************/
254
SecureVector<byte> GMP_ELG_Op::encrypt(const byte in[], u32bit length,
255
const BigInt& k_bn) const
257
GMP_MPZ i(in, length);
259
if(mpz_cmp(i.value, p.value) >= 0)
260
throw Invalid_Argument("GMP_ELG_Op: Input is too large");
262
GMP_MPZ a, b, k(k_bn);
264
mpz_powm(a.value, g.value, k.value, p.value);
265
mpz_powm(b.value, y.value, k.value, p.value);
266
mpz_mul(b.value, b.value, i.value);
267
mpz_mod(b.value, b.value, p.value);
269
const u32bit p_bytes = p.bytes();
270
SecureVector<byte> output(2*p_bytes);
271
a.encode(output, p_bytes);
272
b.encode(output + p_bytes, p_bytes);
276
/*************************************************
277
* GMP ElGamal Decrypt Operation *
278
*************************************************/
279
BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
281
if(mpz_cmp_ui(x.value, 0) == 0)
282
throw Internal_Error("GMP_ELG_Op::decrypt: No private key");
284
GMP_MPZ a(a_bn), b(b_bn);
286
if(mpz_cmp(a.value, p.value) >= 0 || mpz_cmp(b.value, p.value) >= 0)
287
throw Invalid_Argument("GMP_ELG_Op: Invalid message");
289
mpz_powm(a.value, a.value, x.value, p.value);
290
mpz_invert(a.value, a.value, p.value);
291
mpz_mul(a.value, a.value, b.value);
292
mpz_mod(a.value, a.value, p.value);
293
return a.to_bigint();
296
/*************************************************
298
*************************************************/
299
class GMP_DH_Op : public DH_Operation
302
BigInt agree(const BigInt& i) const;
303
DH_Operation* clone() const { return new GMP_DH_Op(*this); }
305
GMP_DH_Op(const DL_Group& group, const BigInt& x_bn) :
306
x(x_bn), p(group.get_p()) {}
311
/*************************************************
312
* GMP DH Key Agreement Operation *
313
*************************************************/
314
BigInt GMP_DH_Op::agree(const BigInt& i_bn) const
317
mpz_powm(i.value, i.value, x.value, p.value);
318
return i.to_bigint();
323
/*************************************************
324
* GMP_Engine Constructor *
325
*************************************************/
326
GMP_Engine::GMP_Engine()
331
/*************************************************
333
*************************************************/
334
IF_Operation* GMP_Engine::if_op(const BigInt& e, const BigInt& n,
335
const BigInt& d, const BigInt& p,
336
const BigInt& q, const BigInt& d1,
337
const BigInt& d2, const BigInt& c) const
339
return new GMP_IF_Op(e, n, d, p, q, d1, d2, c);
342
/*************************************************
344
*************************************************/
345
DSA_Operation* GMP_Engine::dsa_op(const DL_Group& group, const BigInt& y,
346
const BigInt& x) const
348
return new GMP_DSA_Op(group, y, x);
351
/*************************************************
353
*************************************************/
354
NR_Operation* GMP_Engine::nr_op(const DL_Group& group, const BigInt& y,
355
const BigInt& x) const
357
return new GMP_NR_Op(group, y, x);
360
/*************************************************
361
* Acquire an ElGamal op *
362
*************************************************/
363
ELG_Operation* GMP_Engine::elg_op(const DL_Group& group, const BigInt& y,
364
const BigInt& x) const
366
return new GMP_ELG_Op(group, y, x);
369
/*************************************************
371
*************************************************/
372
DH_Operation* GMP_Engine::dh_op(const DL_Group& group, const BigInt& x) const
374
return new GMP_DH_Op(group, x);