231df924d72190f60a3d34f074678850afda67e1
[feisty_meow.git] / nucleus / library / crypto / rsa_crypto.cpp
1 /*
2 *  Name   : RSA public key encryption
3 *  Author : Chris Koeritz
4 *  Purpose:
5 *    Supports public (and private) key encryption and decryption using the
6 *    OpenSSL package's support for RSA encryption.
7 ****
8 * Copyright (c) 2005-$now By Author.  This program is free software; you can  *
9 * redistribute it and/or modify it under the terms of the GNU General Public  *
10 * License as published by the Free Software Foundation; either version 2 of   *
11 * the License or (at your option) any later version.  This is online at:      *
12 *     http://www.fsf.org/copyleft/gpl.html                                    *
13 * Please send any updates to: fred@gruntose.com                               *
14 */
15
16 //note: rsa crypto provides a nice printing method...  RSA_print_fp(stdout, private_key, 0);
17
18 // notes from openssl docs: length to be encrypted in a chunk must be less than
19 // RSA_size(rsa) - 11 for the PKCS #1 v1.5 based padding modes, less than
20 // RSA_size(rsa) - 41 for RSA_PKCS1_OAEP_PADDING and exactly RSA_size(rsa)
21 // for RSA_NO_PADDING.
22
23 #include "rsa_crypto.h"
24 #include "ssl_init.h"
25
26 #include <basis/functions.h>
27 #include <loggers/critical_events.h>
28 #include <loggers/program_wide_logger.h>
29 #include <mathematics/chaos.h>
30 #include <structures/object_packers.h>
31 #include <structures/static_memory_gremlin.h>
32
33 #include <openssl/bn.h>
34 #include <openssl/rsa.h>
35
36 using namespace basis;
37 using namespace loggers;
38 using namespace mathematics;
39 using namespace structures;
40
41 namespace crypto {
42
43 //#define DEBUG_RSA_CRYPTO
44   // uncomment for noisier version.
45
46 #ifdef DEBUG_RSA_CRYPTO
47   #undef LOG
48   #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
49 #else
50   #undef LOG
51   #define LOG(s)
52 #endif
53
54 SAFE_STATIC(mutex, __single_stepper, )
55   // protects unsafe areas of rsa crypto from access by multiple threads at once.
56
57 rsa_crypto::rsa_crypto(int key_size)
58 : _key(NULL_POINTER)
59 {
60   FUNCDEF("ctor(int)");
61   LOG("prior to generating key");
62   _key = generate_key(key_size);  // generate_key initializes ssl for us.
63   LOG("after generating key");
64 }
65
66 rsa_crypto::rsa_crypto(const byte_array &key)
67 : _key(NULL_POINTER)
68 {
69   FUNCDEF("ctor(byte_array)");
70   static_ssl_initializer();
71   byte_array key_copy = key;
72   LOG("prior to set key");
73   set_key(key_copy);
74   LOG("after set key");
75 }
76
77 rsa_crypto::rsa_crypto(RSA *key)
78 : _key(NULL_POINTER)
79 {
80   FUNCDEF("ctor(RSA)");
81   static_ssl_initializer();
82   LOG("prior to set key");
83   set_key(key);
84   LOG("after set key");
85 }
86
87 rsa_crypto::rsa_crypto(const rsa_crypto &to_copy)
88 : root_object(),
89   _key(NULL_POINTER)
90 {
91   FUNCDEF("copy ctor");
92   static_ssl_initializer();
93   LOG("prior to set key");
94   set_key(to_copy._key);
95   LOG("after set key");
96 }
97
98 rsa_crypto::~rsa_crypto()
99 {
100   FUNCDEF("dtor");
101   LOG("prior to rsa free");
102   auto_synchronizer mutt(__single_stepper());
103   RSA_free(_key);
104   LOG("after rsa free");
105 }
106
107 const rsa_crypto &rsa_crypto::operator = (const rsa_crypto &to_copy)
108 {
109   if (this == &to_copy) return *this;
110   set_key(to_copy._key);
111   return *this;
112 }
113
114 RSA *rsa_crypto::generate_key(int key_size)
115 {
116   FUNCDEF("generate_key");
117   if (key_size < 4) key_size = 4;  // laughable lower default.
118   static_ssl_initializer();
119   LOG("into generate key");
120   auto_synchronizer mutt(__single_stepper());
121   RSA *to_return = RSA_generate_key(key_size, 65537, NULL_POINTER, NULL_POINTER);
122   if (!to_return) {
123     continuable_error(static_class_name(), func,
124         a_sprintf("failed to generate a key of %d bits.", key_size));
125   }
126   LOG("after key generated");
127   return to_return;
128 }
129
130 bool rsa_crypto::check_key(RSA *key)
131 {
132   auto_synchronizer mutt(__single_stepper());
133   return RSA_check_key(key) == 1;
134 }
135
136 bool rsa_crypto::set_key(byte_array &key)
137 {
138   FUNCDEF("set_key [byte_array]");
139   if (!key.length()) return false;
140   auto_synchronizer mutt(__single_stepper());
141   if (_key) RSA_free(_key);
142   _key = RSA_new();
143   abyte type;
144   if (!structures::detach(key, type)) return false;
145   if ( (type != 'r') && (type != 'u') ) return false;
146   // get the public key bits first.
147   byte_array n;
148   if (!structures::detach(key, n)) return false;
149   BIGNUM *the_n = BN_bin2bn(n.access(), n.length(), NULL_POINTER);
150   if (!the_n) return false;
151   byte_array e;
152   if (!structures::detach(key, e)) return false;
153   BIGNUM *the_e = BN_bin2bn(e.access(), e.length(), NULL_POINTER);
154   if (!the_e) return false;
155
156   if (type == 'u') {
157      // done with public key.
158 #ifdef NEWER_OPENSSL
159      RSA_set0_key(_key, the_n, the_e, NULL_POINTER);
160 #else
161      _key->n = the_n; _key->e = the_e;
162 #endif
163      return true;
164   }
165
166   // the rest is for a private key.
167   byte_array d;
168   if (!structures::detach(key, d)) return false;
169   BIGNUM *the_d = BN_bin2bn(d.access(), d.length(), NULL_POINTER);
170   if (!the_d) return false;
171
172   byte_array p;
173   if (!structures::detach(key, p)) return false;
174   BIGNUM *the_p = BN_bin2bn(p.access(), p.length(), NULL_POINTER);
175   if (!the_p) return false;
176   byte_array q;
177   if (!structures::detach(key, q)) return false;
178   BIGNUM *the_q = BN_bin2bn(q.access(), q.length(), NULL_POINTER);
179   if (!the_q) return false;
180   byte_array dmp1;
181   if (!structures::detach(key, dmp1)) return false;
182   BIGNUM *the_dmp1 = BN_bin2bn(dmp1.access(), dmp1.length(), NULL_POINTER);
183   if (!the_dmp1) return false;
184   byte_array dmq1;
185   if (!structures::detach(key, dmq1)) return false;
186   BIGNUM *the_dmq1 = BN_bin2bn(dmq1.access(), dmq1.length(), NULL_POINTER);
187   if (!the_dmq1) return false;
188   byte_array iqmp;
189   if (!structures::detach(key, iqmp)) return false;
190   BIGNUM *the_iqmp = BN_bin2bn(iqmp.access(), iqmp.length(), NULL_POINTER);
191   if (!the_iqmp) return false;
192
193   // we can set the n, e and d now.
194 #ifdef NEWER_OPENSSL
195   int ret = RSA_set0_key(_key, the_n, the_e, the_d);
196   if (ret != 1) return false;
197   ret = RSA_set0_factors(_key, the_p, the_q);
198   if (ret != 1) return false;
199   ret = RSA_set0_crt_params(_key, the_dmp1, the_dmq1, the_iqmp);
200   if (ret != 1) return false;
201 #else
202   _key->n = the_n; _key->e = the_e; _key->d = the_d;
203   _key->p = the_p; _key->q = the_q;
204   _key->dmp1 = the_dmp1; _key->dmq1 = the_dmq1; _key->iqmp = the_iqmp;
205 #endif
206
207   int check = RSA_check_key(_key);
208   if (check != 1) {
209     continuable_error(static_class_name(), func, "failed to check the private "
210         "portion of the key!");
211     return false;
212   }
213
214   return true;
215 }
216
217 bool rsa_crypto::set_key(RSA *key)
218 {
219   FUNCDEF("set_key [RSA]");
220   if (!key) return NULL_POINTER;
221   // test the incoming key.
222   auto_synchronizer mutt(__single_stepper());
223   int check = RSA_check_key(key);
224   if (check != 1) return false;
225   // clean out the old key.
226   if (_key) RSA_free(_key);
227   _key = RSAPrivateKey_dup(key);
228   if (!_key) {
229     continuable_error(static_class_name(), func, "failed to create a "
230         "duplicate of the key!");
231     return false;
232   }
233   return true;
234 }
235
236 bool rsa_crypto::public_key(byte_array &pubkey) const
237 {
238   FUNCDEF("public_key");
239   if (!_key) return false;
240   structures::attach(pubkey, abyte('u'));  // signal a public key.
241   // convert the two public portions into binary.
242   BIGNUM **the_n = new BIGNUM *, **the_e = new BIGNUM *, **the_d = new BIGNUM *;
243 #ifdef NEWER_OPENSSL
244   RSA_get0_key(_key, (const BIGNUM **)the_n, (const BIGNUM **)the_e, (const BIGNUM **)the_d);
245 #else
246   *the_n = _key->n; *the_e = _key->e; *the_d = _key->d;
247 #endif
248   byte_array n(BN_num_bytes(*the_n));
249   int ret = BN_bn2bin(*the_n, n.access());
250   byte_array e(BN_num_bytes(*the_e));
251   ret = BN_bn2bin(*the_e, e.access());
252   // pack those two chunks.
253   structures::attach(pubkey, n);
254   structures::attach(pubkey, e);
255   WHACK(the_n); WHACK(the_e); WHACK(the_d);
256
257   return true;
258 }
259
260 bool rsa_crypto::private_key(byte_array &privkey) const
261 {
262   FUNCDEF("private_key");
263   if (!_key) return false;
264   int posn = privkey.length();
265   bool worked = public_key(privkey);  // get the public pieces first.
266   if (!worked) return false;
267   privkey[posn] = abyte('r');  // switch public key flag to private.
268   // convert the multiple private portions into binary.
269   //const BIGNUM **the_n = NULL_POINTER, **the_e = NULL_POINTER, **the_d = NULL_POINTER;
270   BIGNUM **the_n = new BIGNUM *, **the_e = new BIGNUM *, **the_d = new BIGNUM *;
271   BIGNUM **the_p = new BIGNUM *, **the_q = new BIGNUM *;
272   BIGNUM **the_dmp1 = new BIGNUM *, **the_dmq1 = new BIGNUM *, **the_iqmp = new BIGNUM *;
273 #ifdef NEWER_OPENSSL
274   RSA_get0_key(_key, (const BIGNUM **)the_n, (const BIGNUM **)the_e, (const BIGNUM **)the_d);
275   RSA_get0_factors(_key, (const BIGNUM **)the_p, (const BIGNUM **)the_q);
276   RSA_get0_crt_params(_key, (const BIGNUM **)the_dmp1, (const BIGNUM **)the_dmq1, (const BIGNUM **)the_iqmp);
277 #else
278   *the_n = _key->n; *the_e = _key->e; *the_d = _key->d;
279   *the_p = _key->p; *the_q = _key->q;
280   *the_dmp1 = _key->dmp1; *the_dmq1 = _key->dmq1; *the_iqmp = _key->iqmp;
281 #endif
282   byte_array d(BN_num_bytes(*the_d));
283   int ret = BN_bn2bin(*the_d, d.access());
284   byte_array p(BN_num_bytes(*the_p));
285   ret = BN_bn2bin(*the_p, p.access());
286   byte_array q(BN_num_bytes(*the_q));
287   ret = BN_bn2bin(*the_q, q.access());
288   byte_array dmp1(BN_num_bytes(*the_dmp1));
289   ret = BN_bn2bin(*the_dmp1, dmp1.access());
290   byte_array dmq1(BN_num_bytes(*the_dmq1));
291   ret = BN_bn2bin(*the_dmq1, dmq1.access());
292   byte_array iqmp(BN_num_bytes(*the_iqmp));
293   ret = BN_bn2bin(*the_iqmp, iqmp.access());
294   // pack all those in now.
295   structures::attach(privkey, d);
296   structures::attach(privkey, p);
297   structures::attach(privkey, q);
298   structures::attach(privkey, dmp1);
299   structures::attach(privkey, dmq1);
300   structures::attach(privkey, iqmp);
301   return true;
302 }
303
304 bool rsa_crypto::public_encrypt(const byte_array &source,
305     byte_array &target) const
306 {
307   FUNCDEF("public_encrypt");
308   target.reset();
309   if (!source.length()) return false;
310
311   auto_synchronizer mutt(__single_stepper());
312   const int max_chunk = RSA_size(_key) - 12;
313
314   byte_array encoded(RSA_size(_key));
315   for (int i = 0; i < source.length(); i += max_chunk) {
316     int edge = i + max_chunk - 1;
317     if (edge > source.last())
318       edge = source.last();
319     int next_chunk = edge - i + 1;
320     RSA_public_encrypt(next_chunk, &source[i],
321         encoded.access(), _key, RSA_PKCS1_PADDING);
322     target += encoded;
323   }
324   return true;
325 }
326
327 bool rsa_crypto::private_decrypt(const byte_array &source,
328     byte_array &target) const
329 {
330   FUNCDEF("private_decrypt");
331   target.reset();
332   if (!source.length()) return false;
333
334   auto_synchronizer mutt(__single_stepper());
335   const int max_chunk = RSA_size(_key);
336
337   byte_array decoded(max_chunk);
338   for (int i = 0; i < source.length(); i += max_chunk) {
339     int edge = i + max_chunk - 1;
340     if (edge > source.last())
341       edge = source.last();
342     int next_chunk = edge - i + 1;
343     int dec_size = RSA_private_decrypt(next_chunk, &source[i],
344         decoded.access(), _key, RSA_PKCS1_PADDING);
345     if (dec_size < 0) return false;  // that didn't work.
346     decoded.zap(dec_size, decoded.last());
347     target += decoded;
348     decoded.reset(max_chunk);
349   }
350   return true;
351 }
352
353 bool rsa_crypto::private_encrypt(const byte_array &source,
354     byte_array &target) const
355 {
356   FUNCDEF("private_encrypt");
357   target.reset();
358   if (!source.length()) return false;
359
360   auto_synchronizer mutt(__single_stepper());
361   const int max_chunk = RSA_size(_key) - 12;
362
363   byte_array encoded(RSA_size(_key));
364   for (int i = 0; i < source.length(); i += max_chunk) {
365     int edge = i + max_chunk - 1;
366     if (edge > source.last())
367       edge = source.last();
368     int next_chunk = edge - i + 1;
369     RSA_private_encrypt(next_chunk, &source[i],
370         encoded.access(), _key, RSA_PKCS1_PADDING);
371     target += encoded;
372   }
373   return true;
374 }
375
376 bool rsa_crypto::public_decrypt(const byte_array &source,
377     byte_array &target) const
378 {
379   FUNCDEF("public_decrypt");
380   target.reset();
381   if (!source.length()) return false;
382
383   auto_synchronizer mutt(__single_stepper());
384   const int max_chunk = RSA_size(_key);
385
386   byte_array decoded(max_chunk);
387   for (int i = 0; i < source.length(); i += max_chunk) {
388     int edge = i + max_chunk - 1;
389     if (edge > source.last())
390       edge = source.last();
391     int next_chunk = edge - i + 1;
392     int dec_size = RSA_public_decrypt(next_chunk, &source[i],
393         decoded.access(), _key, RSA_PKCS1_PADDING);
394     if (dec_size < 0) return false;  // that didn't work.
395     decoded.zap(dec_size, decoded.last());
396     target += decoded;
397     decoded.reset(max_chunk);
398   }
399   return true;
400 }
401
402 } //namespace.
403