~ubuntu-branches/debian/sid/botan/sid

« back to all changes in this revision

Viewing changes to modules/eng_gmp/eng_gmp.cpp

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2018-03-01 22:23:25 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20180301222325-7p7vc45gu3hta34d
Tags: 2.4.0-2
* Don't remove .doctrees from the manual if it doesn't exist.
* Don't specify parallel to debhelper.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*************************************************
2
 
* GMP Engine Source File                         *
3
 
* (C) 1999-2007 The Botan Project                *
4
 
*************************************************/
5
 
 
6
 
#include <botan/eng_gmp.h>
7
 
#include <botan/gmp_wrap.h>
8
 
#include <gmp.h>
9
 
 
10
 
namespace Botan {
11
 
 
12
 
namespace {
13
 
 
14
 
/*************************************************
15
 
* GMP IF Operation                               *
16
 
*************************************************/
17
 
class GMP_IF_Op : public IF_Operation
18
 
   {
19
 
   public:
20
 
      BigInt public_op(const BigInt&) const;
21
 
      BigInt private_op(const BigInt&) const;
22
 
 
23
 
      IF_Operation* clone() const { return new GMP_IF_Op(*this); }
24
 
 
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) {}
29
 
   private:
30
 
      const GMP_MPZ e, n, p, q, d1, d2, c;
31
 
   };
32
 
 
33
 
/*************************************************
34
 
* GMP IF Public Operation                        *
35
 
*************************************************/
36
 
BigInt GMP_IF_Op::public_op(const BigInt& i_bn) const
37
 
   {
38
 
   GMP_MPZ i(i_bn);
39
 
   mpz_powm(i.value, i.value, e.value, n.value);
40
 
   return i.to_bigint();
41
 
   }
42
 
 
43
 
/*************************************************
44
 
* GMP IF Private Operation                       *
45
 
*************************************************/
46
 
BigInt GMP_IF_Op::private_op(const BigInt& i_bn) const
47
 
   {
48
 
   if(mpz_cmp_ui(p.value, 0) == 0)
49
 
      throw Internal_Error("GMP_IF_Op::private_op: No private key");
50
 
 
51
 
   GMP_MPZ j1, j2, h(i_bn);
52
 
 
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);
60
 
   return h.to_bigint();
61
 
   }
62
 
 
63
 
/*************************************************
64
 
* GMP DSA Operation                              *
65
 
*************************************************/
66
 
class GMP_DSA_Op : public DSA_Operation
67
 
   {
68
 
   public:
69
 
      bool verify(const byte[], u32bit, const byte[], u32bit) const;
70
 
      SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
71
 
 
72
 
      DSA_Operation* clone() const { return new GMP_DSA_Op(*this); }
73
 
 
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()) {}
76
 
   private:
77
 
      const GMP_MPZ x, y, p, q, g;
78
 
   };
79
 
 
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
85
 
   {
86
 
   const u32bit q_bytes = q.bytes();
87
 
 
88
 
   if(sig_len != 2*q_bytes || msg_len > q_bytes)
89
 
      return false;
90
 
 
91
 
   GMP_MPZ r(sig, q_bytes);
92
 
   GMP_MPZ s(sig + q_bytes, q_bytes);
93
 
   GMP_MPZ i(msg, msg_len);
94
 
 
95
 
   if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0)
96
 
      return false;
97
 
   if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0)
98
 
      return false;
99
 
 
100
 
   if(mpz_invert(s.value, s.value, q.value) == 0)
101
 
      return false;
102
 
 
103
 
   GMP_MPZ si;
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);
107
 
 
108
 
   GMP_MPZ sr;
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);
112
 
 
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);
116
 
 
117
 
   if(mpz_cmp(si.value, r.value) == 0)
118
 
      return true;
119
 
   return false;
120
 
   }
121
 
 
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
127
 
   {
128
 
   if(mpz_cmp_ui(x.value, 0) == 0)
129
 
      throw Internal_Error("GMP_DSA_Op::sign: No private key");
130
 
 
131
 
   GMP_MPZ i(in, length);
132
 
   GMP_MPZ k(k_bn);
133
 
 
134
 
   GMP_MPZ r;
135
 
   mpz_powm(r.value, g.value, k.value, p.value);
136
 
   mpz_mod(r.value, r.value, q.value);
137
 
 
138
 
   mpz_invert(k.value, k.value, q.value);
139
 
 
140
 
   GMP_MPZ s;
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);
145
 
 
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");
148
 
 
149
 
   const u32bit q_bytes = q.bytes();
150
 
 
151
 
   SecureVector<byte> output(2*q_bytes);
152
 
   r.encode(output, q_bytes);
153
 
   s.encode(output + q_bytes, q_bytes);
154
 
   return output;
155
 
   }
156
 
 
157
 
/*************************************************
158
 
* GMP NR Operation                               *
159
 
*************************************************/
160
 
class GMP_NR_Op : public NR_Operation
161
 
   {
162
 
   public:
163
 
      SecureVector<byte> verify(const byte[], u32bit) const;
164
 
      SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
165
 
 
166
 
      NR_Operation* clone() const { return new GMP_NR_Op(*this); }
167
 
 
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()) {}
170
 
   private:
171
 
      const GMP_MPZ x, y, p, q, g;
172
 
   };
173
 
 
174
 
/*************************************************
175
 
* GMP NR Verify Operation                        *
176
 
*************************************************/
177
 
SecureVector<byte> GMP_NR_Op::verify(const byte sig[], u32bit sig_len) const
178
 
   {
179
 
   const u32bit q_bytes = q.bytes();
180
 
 
181
 
   if(sig_len != 2*q_bytes)
182
 
      return false;
183
 
 
184
 
   GMP_MPZ c(sig, q_bytes);
185
 
   GMP_MPZ d(sig + q_bytes, q_bytes);
186
 
 
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");
190
 
 
191
 
   GMP_MPZ i1, i2;
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());
199
 
   }
200
 
 
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
206
 
   {
207
 
   if(mpz_cmp_ui(x.value, 0) == 0)
208
 
      throw Internal_Error("GMP_NR_Op::sign: No private key");
209
 
 
210
 
   GMP_MPZ f(in, length);
211
 
   GMP_MPZ k(k_bn);
212
 
 
213
 
   if(mpz_cmp(f.value, q.value) >= 0)
214
 
      throw Invalid_Argument("GMP_NR_Op::sign: Input is out of range");
215
 
 
216
 
   GMP_MPZ c, d;
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);
223
 
 
224
 
   if(mpz_cmp_ui(c.value, 0) == 0)
225
 
      throw Internal_Error("Default_NR_Op::sign: c was zero");
226
 
 
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);
231
 
   return output;
232
 
   }
233
 
 
234
 
/*************************************************
235
 
* GMP ElGamal Operation                          *
236
 
*************************************************/
237
 
class GMP_ELG_Op : public ELG_Operation
238
 
   {
239
 
   public:
240
 
      SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
241
 
      BigInt decrypt(const BigInt&, const BigInt&) const;
242
 
 
243
 
      ELG_Operation* clone() const { return new GMP_ELG_Op(*this); }
244
 
 
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()) {}
247
 
   private:
248
 
      GMP_MPZ x, y, g, p;
249
 
   };
250
 
 
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
256
 
   {
257
 
   GMP_MPZ i(in, length);
258
 
 
259
 
   if(mpz_cmp(i.value, p.value) >= 0)
260
 
      throw Invalid_Argument("GMP_ELG_Op: Input is too large");
261
 
 
262
 
   GMP_MPZ a, b, k(k_bn);
263
 
 
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);
268
 
 
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);
273
 
   return output;
274
 
   }
275
 
 
276
 
/*************************************************
277
 
* GMP ElGamal Decrypt Operation                  *
278
 
*************************************************/
279
 
BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
280
 
   {
281
 
   if(mpz_cmp_ui(x.value, 0) == 0)
282
 
      throw Internal_Error("GMP_ELG_Op::decrypt: No private key");
283
 
 
284
 
   GMP_MPZ a(a_bn), b(b_bn);
285
 
 
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");
288
 
 
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();
294
 
   }
295
 
 
296
 
/*************************************************
297
 
* GMP DH Operation                               *
298
 
*************************************************/
299
 
class GMP_DH_Op : public DH_Operation
300
 
   {
301
 
   public:
302
 
      BigInt agree(const BigInt& i) const;
303
 
      DH_Operation* clone() const { return new GMP_DH_Op(*this); }
304
 
 
305
 
      GMP_DH_Op(const DL_Group& group, const BigInt& x_bn) :
306
 
         x(x_bn), p(group.get_p()) {}
307
 
   private:
308
 
      GMP_MPZ x, p;
309
 
   };
310
 
 
311
 
/*************************************************
312
 
* GMP DH Key Agreement Operation                 *
313
 
*************************************************/
314
 
BigInt GMP_DH_Op::agree(const BigInt& i_bn) const
315
 
   {
316
 
   GMP_MPZ i(i_bn);
317
 
   mpz_powm(i.value, i.value, x.value, p.value);
318
 
   return i.to_bigint();
319
 
   }
320
 
 
321
 
}
322
 
 
323
 
/*************************************************
324
 
* GMP_Engine Constructor                         *
325
 
*************************************************/
326
 
GMP_Engine::GMP_Engine()
327
 
   {
328
 
   set_memory_hooks();
329
 
   }
330
 
 
331
 
/*************************************************
332
 
* Acquire an IF op                               *
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
338
 
   {
339
 
   return new GMP_IF_Op(e, n, d, p, q, d1, d2, c);
340
 
   }
341
 
 
342
 
/*************************************************
343
 
* Acquire a DSA op                               *
344
 
*************************************************/
345
 
DSA_Operation* GMP_Engine::dsa_op(const DL_Group& group, const BigInt& y,
346
 
                                  const BigInt& x) const
347
 
   {
348
 
   return new GMP_DSA_Op(group, y, x);
349
 
   }
350
 
 
351
 
/*************************************************
352
 
* Acquire a NR op                                *
353
 
*************************************************/
354
 
NR_Operation* GMP_Engine::nr_op(const DL_Group& group, const BigInt& y,
355
 
                                const BigInt& x) const
356
 
   {
357
 
   return new GMP_NR_Op(group, y, x);
358
 
   }
359
 
 
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
365
 
   {
366
 
   return new GMP_ELG_Op(group, y, x);
367
 
   }
368
 
 
369
 
/*************************************************
370
 
* Acquire a DH op                                *
371
 
*************************************************/
372
 
DH_Operation* GMP_Engine::dh_op(const DL_Group& group, const BigInt& x) const
373
 
   {
374
 
   return new GMP_DH_Op(group, x);
375
 
   }
376
 
 
377
 
}