Botan  1.10.9
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*
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 
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 
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 
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 
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 }
BigInt n
Definition: numthry.cpp:26
PK_Ops::Encryption * get_encryption_op(const Public_Key &key) const
Definition: gnump_pk.cpp:317
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
static SecureVector< byte > encode(const BigInt &n, Base base=Binary)
Definition: big_code.cpp:64
unsigned char byte
Definition: types.h:22
RandomNumberGenerator * rng
Definition: global_rng.cpp:165
GMP_MPZ mod
Definition: gmp_powm.cpp:29
PK_Ops::Verification * get_verify_op(const Public_Key &key) const
Definition: gnump_pk.cpp:301
PK_Ops::Signature * get_signature_op(const Private_Key &key) const
Definition: gnump_pk.cpp:285
EVP_CIPHER_CTX decrypt
Definition: ossl_bc.cpp:43
PK_Ops::Decryption * get_decryption_op(const Private_Key &key) const
Definition: gnump_pk.cpp:328
EVP_CIPHER_CTX encrypt
Definition: ossl_bc.cpp:43
BigInt r
Definition: numthry.cpp:26
static SecureVector< byte > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:78
PK_Ops::Key_Agreement * get_key_agreement_op(const Private_Key &key) const
Definition: gnump_pk.cpp:274
size_t s
Definition: numthry.cpp:27