54416397b303964578553b500cb2a3a69a2bda16
[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(NIL)
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(NIL)
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_st *key)
78 : _key(NIL)
79 {
80   FUNCDEF("ctor(rsa_st)");
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(NIL)
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_st *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("prior to generate key");
120   auto_synchronizer mutt(__single_stepper());
121   rsa_st *to_return = RSA_generate_key(key_size, 65537, NIL, NIL);
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 generate key");
127   return to_return;
128 }
129
130 bool rsa_crypto::check_key(rsa_st *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   _key->n = BN_bin2bn(n.access(), n.length(), NIL);
150   if (!_key->n) return false;
151   byte_array e;
152   if (!structures::detach(key, e)) return false;
153   _key->e = BN_bin2bn(e.access(), e.length(), NIL);
154   if (!_key->e) return false;
155   if (type == 'u') return true;  // done with public key.
156
157   // the rest is for a private key.
158   byte_array d;
159   if (!structures::detach(key, d)) return false;
160   _key->d = BN_bin2bn(d.access(), d.length(), NIL);
161   if (!_key->d) return false;
162   byte_array p;
163   if (!structures::detach(key, p)) return false;
164   _key->p = BN_bin2bn(p.access(), p.length(), NIL);
165   if (!_key->p) return false;
166   byte_array q;
167   if (!structures::detach(key, q)) return false;
168   _key->q = BN_bin2bn(q.access(), q.length(), NIL);
169   if (!_key->q) return false;
170   byte_array dmp1;
171   if (!structures::detach(key, dmp1)) return false;
172   _key->dmp1 = BN_bin2bn(dmp1.access(), dmp1.length(), NIL);
173   if (!_key->dmp1) return false;
174   byte_array dmq1;
175   if (!structures::detach(key, dmq1)) return false;
176   _key->dmq1 = BN_bin2bn(dmq1.access(), dmq1.length(), NIL);
177   if (!_key->dmq1) return false;
178   byte_array iqmp;
179   if (!structures::detach(key, iqmp)) return false;
180   _key->iqmp = BN_bin2bn(iqmp.access(), iqmp.length(), NIL);
181   if (!_key->iqmp) return false;
182   int check = RSA_check_key(_key);
183   if (check != 1) {
184     continuable_error(static_class_name(), func, "failed to check the private "
185         "portion of the key!");
186     return false;
187   }
188
189   return true;
190 }
191
192 bool rsa_crypto::set_key(rsa_st *key)
193 {
194   FUNCDEF("set_key [rsa_st]");
195   if (!key) return NIL;
196   // test the incoming key.
197   auto_synchronizer mutt(__single_stepper());
198   int check = RSA_check_key(key);
199   if (check != 1) return false;
200   // clean out the old key.
201   if (_key) RSA_free(_key);
202   _key = RSAPrivateKey_dup(key);
203   if (!_key) {
204     continuable_error(static_class_name(), func, "failed to create a "
205         "duplicate of the key!");
206     return false;
207   }
208   return true;
209 }
210
211 bool rsa_crypto::public_key(byte_array &pubkey) const
212 {
213   FUNCDEF("public_key");
214   if (!_key) return false;
215   structures::attach(pubkey, abyte('u'));  // signal a public key.
216   // convert the two public portions into binary.
217   byte_array n(BN_num_bytes(_key->n));
218   int ret = BN_bn2bin(_key->n, n.access());
219   byte_array e(BN_num_bytes(_key->e));
220   ret = BN_bn2bin(_key->e, e.access());
221   // pack those two chunks.
222   structures::attach(pubkey, n);
223   structures::attach(pubkey, e);
224   return true;
225 }
226
227 bool rsa_crypto::private_key(byte_array &privkey) const
228 {
229   FUNCDEF("private_key");
230   if (!_key) return false;
231   int posn = privkey.length();
232   bool worked = public_key(privkey);  // get the public pieces first.
233   if (!worked) return false;
234   privkey[posn] = abyte('r');  // switch public key flag to private.
235   // convert the multiple private portions into binary.
236   byte_array d(BN_num_bytes(_key->d));
237   int ret = BN_bn2bin(_key->d, d.access());
238   byte_array p(BN_num_bytes(_key->p));
239   ret = BN_bn2bin(_key->p, p.access());
240   byte_array q(BN_num_bytes(_key->q));
241   ret = BN_bn2bin(_key->q, q.access());
242   byte_array dmp1(BN_num_bytes(_key->dmp1));
243   ret = BN_bn2bin(_key->dmp1, dmp1.access());
244   byte_array dmq1(BN_num_bytes(_key->dmq1));
245   ret = BN_bn2bin(_key->dmq1, dmq1.access());
246   byte_array iqmp(BN_num_bytes(_key->iqmp));
247   ret = BN_bn2bin(_key->iqmp, iqmp.access());
248   // pack all those in now.
249   structures::attach(privkey, d);
250   structures::attach(privkey, p);
251   structures::attach(privkey, q);
252   structures::attach(privkey, dmp1);
253   structures::attach(privkey, dmq1);
254   structures::attach(privkey, iqmp);
255   return true;
256 }
257
258 bool rsa_crypto::public_encrypt(const byte_array &source,
259     byte_array &target) const
260 {
261   FUNCDEF("public_encrypt");
262   target.reset();
263   if (!source.length()) return false;
264
265   auto_synchronizer mutt(__single_stepper());
266   const int max_chunk = RSA_size(_key) - 12;
267
268   byte_array encoded(RSA_size(_key));
269   for (int i = 0; i < source.length(); i += max_chunk) {
270     int edge = i + max_chunk - 1;
271     if (edge > source.last())
272       edge = source.last();
273     int next_chunk = edge - i + 1;
274     RSA_public_encrypt(next_chunk, &source[i],
275         encoded.access(), _key, RSA_PKCS1_PADDING);
276     target += encoded;
277   }
278   return true;
279 }
280
281 bool rsa_crypto::private_decrypt(const byte_array &source,
282     byte_array &target) const
283 {
284   FUNCDEF("private_decrypt");
285   target.reset();
286   if (!source.length()) return false;
287
288   auto_synchronizer mutt(__single_stepper());
289   const int max_chunk = RSA_size(_key);
290
291   byte_array decoded(max_chunk);
292   for (int i = 0; i < source.length(); i += max_chunk) {
293     int edge = i + max_chunk - 1;
294     if (edge > source.last())
295       edge = source.last();
296     int next_chunk = edge - i + 1;
297     int dec_size = RSA_private_decrypt(next_chunk, &source[i],
298         decoded.access(), _key, RSA_PKCS1_PADDING);
299     if (dec_size < 0) return false;  // that didn't work.
300     decoded.zap(dec_size, decoded.last());
301     target += decoded;
302     decoded.reset(max_chunk);
303   }
304   return true;
305 }
306
307 bool rsa_crypto::private_encrypt(const byte_array &source,
308     byte_array &target) const
309 {
310   FUNCDEF("private_encrypt");
311   target.reset();
312   if (!source.length()) return false;
313
314   auto_synchronizer mutt(__single_stepper());
315   const int max_chunk = RSA_size(_key) - 12;
316
317   byte_array encoded(RSA_size(_key));
318   for (int i = 0; i < source.length(); i += max_chunk) {
319     int edge = i + max_chunk - 1;
320     if (edge > source.last())
321       edge = source.last();
322     int next_chunk = edge - i + 1;
323     RSA_private_encrypt(next_chunk, &source[i],
324         encoded.access(), _key, RSA_PKCS1_PADDING);
325     target += encoded;
326   }
327   return true;
328 }
329
330 bool rsa_crypto::public_decrypt(const byte_array &source,
331     byte_array &target) const
332 {
333   FUNCDEF("public_decrypt");
334   target.reset();
335   if (!source.length()) return false;
336
337   auto_synchronizer mutt(__single_stepper());
338   const int max_chunk = RSA_size(_key);
339
340   byte_array decoded(max_chunk);
341   for (int i = 0; i < source.length(); i += max_chunk) {
342     int edge = i + max_chunk - 1;
343     if (edge > source.last())
344       edge = source.last();
345     int next_chunk = edge - i + 1;
346     int dec_size = RSA_public_decrypt(next_chunk, &source[i],
347         decoded.access(), _key, RSA_PKCS1_PADDING);
348     if (dec_size < 0) return false;  // that didn't work.
349     decoded.zap(dec_size, decoded.last());
350     target += decoded;
351     decoded.reset(max_chunk);
352   }
353   return true;
354 }
355
356 } //namespace.
357