Merge remote-tracking branch 'IOMultiplexer/v2'
[NextIRCd.git] / src / crypt_rsa.c
1 /* crypt_rsa.c - NextIRCd
2  * Copyright (C) 2012-2013  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "../config.h"
18 #include "crypt_rsa.h"
19
20 #include <stdio.h>
21 #include <malloc.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 /*
26 // GnuTLS Backend not working because of gnutls_pubkey_encrypt_data doesn't exists prior to GnuTLS 3.0
27 // still searching for a replacement...
28
29 #if defined(HAVE_GNUTLS_GNUTLS_H)
30 #include <gnutls/gnutls.h>
31 #include <gnutls/x509.h>
32 #include <gnutls/abstract.h>
33
34 struct crypt_rsa_pubkey {
35         unsigned int free_crt : 1;
36         unsigned int free_pubkey : 1;
37         gnutls_x509_crt_t crt;
38         gnutls_pubkey_t pubkey;
39 };
40
41 struct crypt_rsa_privkey {
42         unsigned int free_key : 1;
43         unsigned int free_privkey : 1;
44         gnutls_x509_privkey_t key;
45         gnutls_privkey_t privkey;
46 };
47
48 void crypt_rsa_init() {
49         gnutls_global_init();
50 }
51
52 void crypt_rsa_deinit() {
53         gnutls_global_deinit();
54 }
55
56 struct crypt_rsa_pubkey *crypt_rsa_load_pubkey(const char *key) {
57         struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
58         int ret;
59         const gnutls_datum_t key_dat = {(void *)key, strlen(key)};
60         
61         if(!pubkey)
62                 return NULL;
63         
64         ret = gnutls_x509_crt_init(&pubkey->crt);
65         if(ret < 0)
66                 goto crypt_rsa_load_pubkey_fail;
67         pubkey->free_crt = 1;
68         
69         ret = gnutls_x509_crt_import(pubkey->crt, &key_dat, GNUTLS_X509_FMT_PEM);
70         if (ret < 0)
71                 goto crypt_rsa_load_pubkey_fail;
72         
73         ret = gnutls_pubkey_init(&pubkey->pubkey);
74         if(ret < 0)
75                 goto crypt_rsa_load_pubkey_fail;
76         pubkey->free_pubkey = 1;
77         
78         ret = gnutls_pubkey_import_x509(pubkey->pubkey, pubkey->crt, 0);
79         if(ret < 0)
80                 goto crypt_rsa_load_pubkey_fail;
81         
82         return pubkey;
83         crypt_rsa_load_pubkey_fail:
84         crypt_rsa_unload_pubkey(pubkey);
85         return NULL;
86 }
87
88 void crypt_rsa_unload_pubkey(struct crypt_rsa_pubkey *pubkey) {
89         if(pubkey->free_crt)
90                 gnutls_x509_crt_deinit(pubkey->crt);
91         if(pubkey->free_pubkey)
92                 gnutls_pubkey_deinit(pubkey->pubkey);
93         free(pubkey);
94 }
95
96 char *crypt_rsa_export_pubkey(struct crypt_rsa_pubkey *pubkey) {
97         size_t size = 1024;
98         char *buffer = malloc(size);
99         int ret;
100         
101         ret = gnutls_pubkey_export(pubkey->pubkey, GNUTLS_X509_FMT_PEM, buffer, &size);
102         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
103                 buffer = realloc(buffer, size);
104                 ret = gnutls_pubkey_export(pubkey->pubkey, GNUTLS_X509_FMT_PEM, buffer, &size);
105         }
106         if(ret < 0) {
107                 free(buffer);
108                 return NULL;
109         }
110         return buffer;
111 }
112
113 struct crypt_rsa_privkey *crypt_rsa_load_privkey(const char *key) {
114         struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
115         int ret;
116         
117         const gnutls_datum_t key_dat = {(void *)key, strlen(key)};
118         
119         ret = gnutls_x509_privkey_init(&privkey->key);
120         if(ret < 0)
121                 goto crypt_rsa_load_privkey_fail;
122         privkey->free_key = 1;
123         
124         ret = gnutls_x509_privkey_import(privkey->key, &key_dat, GNUTLS_X509_FMT_PEM);
125         if (ret < 0)
126                 goto crypt_rsa_load_privkey_fail;
127         
128         ret = gnutls_privkey_init(&privkey->privkey);
129         if(ret < 0)
130                 goto crypt_rsa_load_privkey_fail;
131         privkey->free_privkey = 1;
132         
133         ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0);
134         if(ret < 0)
135                 goto crypt_rsa_load_privkey_fail;
136         
137         return privkey;
138         crypt_rsa_load_privkey_fail:
139         crypt_rsa_unload_privkey(privkey);
140         return NULL;
141 }
142
143 struct crypt_rsa_privkey *crypt_rsa_generate_privkey(const int keysize) {
144         struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
145         int ret;
146         
147         ret = gnutls_x509_privkey_init(&privkey->key);
148         if(ret < 0)
149                 goto crypt_rsa_generate_privkey_fail;
150         privkey->free_key = 1;
151         
152         ret = gnutls_x509_privkey_generate(privkey->key, GNUTLS_PK_RSA, keysize, 0);
153         if (ret < 0)
154                 goto crypt_rsa_generate_privkey_fail;
155         
156         ret = gnutls_privkey_init(&privkey->privkey);
157         if(ret < 0)
158                 goto crypt_rsa_generate_privkey_fail;
159         privkey->free_privkey = 1;
160         
161         ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0);
162         if(ret < 0)
163                 goto crypt_rsa_generate_privkey_fail;
164         
165         return privkey;
166         crypt_rsa_generate_privkey_fail:
167         crypt_rsa_unload_privkey(privkey);
168         return NULL;
169 }
170
171 char *crypt_rsa_export_privkey(struct crypt_rsa_privkey *privkey, int pubkey) {
172         size_t size = 1024;
173         char *buffer = malloc(size);
174         int ret;
175         
176         if(pubkey) {
177                 gnutls_pubkey_t pkey;
178                 ret = gnutls_pubkey_init(&pkey);
179                 if(ret < 0) {
180                         free(buffer);
181                         return NULL;
182                 }
183                 ret = gnutls_pubkey_import_privkey(pkey, privkey->privkey, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
184                 if(ret < 0) {
185                         free(buffer);
186                         gnutls_pubkey_deinit(pkey);
187                         return NULL;
188                 }
189                 ret = gnutls_pubkey_export(pkey, GNUTLS_X509_FMT_PEM, buffer, &size);
190                 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
191                         buffer = realloc(buffer, size);
192                         ret = gnutls_pubkey_export(pkey, GNUTLS_X509_FMT_PEM, buffer, &size);
193                 }
194                 gnutls_pubkey_deinit(pkey);
195         } else {
196                 ret = gnutls_x509_privkey_export(privkey->key, GNUTLS_X509_FMT_PEM, buffer, &size);
197                 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
198                         buffer = realloc(buffer, size);
199                         ret = gnutls_x509_privkey_export(privkey->key, GNUTLS_X509_FMT_PEM, buffer, &size);
200                 }
201         }
202         if(ret < 0) {
203                 free(buffer);
204                 return NULL;
205         }
206         return buffer;
207 }
208
209 void crypt_rsa_unload_privkey(struct crypt_rsa_privkey *privkey) {
210         if(privkey->free_key)
211                 gnutls_x509_privkey_deinit(privkey->key);
212         if(privkey->free_privkey)
213                 gnutls_privkey_deinit(privkey->privkey);
214         free(privkey);
215 }
216
217 struct crypt_rsa_pubkey *crypt_rsa_get_pubkey(struct crypt_rsa_privkey *privkey) {
218         struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
219         if(!pubkey)
220                 return NULL;
221         int ret;
222         
223         ret = gnutls_pubkey_init(&pubkey->pubkey);
224         if(ret < 0)
225                 goto crypt_rsa_get_pubkey_fail;
226         pubkey->free_pubkey = 1;
227         
228         ret = gnutls_pubkey_import_privkey(pubkey->pubkey, privkey->privkey, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
229         if(ret < 0)
230                 goto crypt_rsa_get_pubkey_fail;
231         
232         return pubkey;
233         crypt_rsa_get_pubkey_fail:
234         crypt_rsa_unload_pubkey(pubkey);
235         return NULL;
236 }
237
238 int crypt_rsa_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char **encrypted) {
239         const gnutls_datum_t data_dat = {(void *)data, datalen};
240         gnutls_datum_t out;
241         
242         int ret = gnutls_pubkey_encrypt_data(pubkey->pubkey, 0, &data_dat, &out);
243         if(ret < 0)
244                 return ret;
245         
246         *encrypted = out.data;
247         return out.size;
248 }
249
250 int crypt_rsa_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char **data) {
251         const gnutls_datum_t enc_dat = {(void *)encrypted, enclen};
252         gnutls_datum_t out;
253         
254         int ret = gnutls_privkey_decrypt_data(privkey->privkey, 0, &enc_dat, &out);
255         if(ret < 0)
256                 return ret;
257         
258         *data = out.data;
259         return out.size;
260 }
261
262 int crypt_rsa_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) {
263         //int size = (pubkey->pubkey->bits / 8) - 12;
264         //todo!
265         int size = 1024;
266         return size;
267 }
268
269 void crypt_rsa_encrypt_free(char *encrypted) {
270         gnutls_free(encrypted);
271 }
272
273 void crypt_rsa_decrypt_free(char *data) {
274         gnutls_free(data);
275 }
276
277 #elif defined(HAVE_OPENSSL_SSL_H)
278 */
279
280 #include <openssl/pem.h>
281 #include <openssl/ssl.h>
282 #include <openssl/rsa.h>
283 #include <openssl/evp.h>
284 #include <openssl/bio.h>
285 #include <openssl/err.h>
286
287 struct crypt_rsa_pubkey {
288         RSA *rsa;
289 };
290
291 struct crypt_rsa_privkey {
292         RSA *rsa;
293 };
294
295 void crypt_rsa_init() {
296         
297 }
298
299 void crypt_rsa_deinit() {
300         
301 }
302
303 RSA *createRSA(unsigned char *key, int public) {
304     RSA *rsa= NULL;
305     BIO *keybio ;
306     keybio = BIO_new_mem_buf(key, -1);
307     if(!keybio)
308         return NULL;
309     if(public)
310         rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
311     else
312         rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
313     BIO_free(keybio);
314     return rsa;
315 }
316
317 struct crypt_rsa_pubkey *crypt_rsa_load_pubkey(const char *key) {
318         struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
319         if(!pubkey)
320                 return NULL;
321         
322         RSA *rsa = createRSA((unsigned char *) key, 1);
323         
324         if(!rsa) {
325                 free(pubkey);
326                 return NULL;
327         }
328         
329         pubkey->rsa = rsa;
330         return pubkey;
331 }
332
333 void crypt_rsa_unload_pubkey(struct crypt_rsa_pubkey *pubkey) {
334         RSA_free(pubkey->rsa);
335         free(pubkey);
336 }
337
338 char *crypt_rsa_export_pubkey(struct crypt_rsa_pubkey *pubkey) {
339         BIO *bio = BIO_new(BIO_s_mem());
340         PEM_write_bio_RSA_PUBKEY(bio, pubkey->rsa);
341         
342         int keylen = BIO_pending(bio);
343         char *key = calloc(1, keylen+1);
344         BIO_read(bio, key, keylen);
345         
346         BIO_free_all(bio);
347         return key;
348 }
349
350 struct crypt_rsa_privkey *crypt_rsa_load_privkey(const char *key) {
351         struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
352         if(!privkey)
353                 return NULL;
354         
355         RSA *rsa = createRSA((unsigned char *) key, 0);
356         
357         if(!rsa) {
358                 free(privkey);
359                 return NULL;
360         }
361         
362         privkey->rsa = rsa;
363         return privkey;
364 }
365
366 struct crypt_rsa_privkey *crypt_rsa_generate_privkey(const int keysize) {
367         struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
368         if(!privkey)
369                 return NULL;
370                 
371         BIGNUM *e = BN_new();
372         RSA *rsa = RSA_new();
373         
374         BN_set_word(e, 65537);
375         if (!RSA_generate_key_ex(rsa, keysize, e, NULL)) {
376                 BN_free(e);
377                 RSA_free(rsa);
378                 free(privkey);
379                 return NULL;
380         }
381         
382         privkey->rsa = rsa;
383         return privkey;
384 }
385
386 char *crypt_rsa_export_privkey(struct crypt_rsa_privkey *privkey, int pubkey) {
387         BIO *bio = BIO_new(BIO_s_mem());
388         if(pubkey)
389                 PEM_write_bio_RSA_PUBKEY(bio, privkey->rsa);
390         else
391                 PEM_write_bio_RSAPrivateKey(bio, privkey->rsa, NULL, NULL, 0, NULL, NULL);
392         
393         int keylen = BIO_pending(bio);
394         char *key = calloc(1, keylen+1);
395         BIO_read(bio, key, keylen);
396         
397         BIO_free_all(bio);
398         return key;
399 }
400
401 void crypt_rsa_unload_privkey(struct crypt_rsa_privkey *privkey) {
402         RSA_free(privkey->rsa);
403         free(privkey);
404 }
405
406 struct crypt_rsa_pubkey *crypt_rsa_get_pubkey(struct crypt_rsa_privkey *privkey) {
407         struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
408         if(!pubkey)
409                 return NULL;
410         
411         RSA *rsa = RSA_new();
412         memcpy(rsa, privkey->rsa, sizeof(*rsa));
413         
414         pubkey->rsa = rsa;
415         return pubkey;
416 }
417
418 int crypt_rsa_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char **encrypted) {
419         if(!pubkey)
420                 return 0;
421         if(datalen > crypt_rsa_encrypt_maxlen(pubkey))
422                 return 0;
423         *encrypted = malloc(RSA_size(pubkey->rsa));
424         if(!*encrypted)
425                 return 0;
426         int ret = RSA_public_encrypt(datalen, data, *encrypted, pubkey->rsa, RSA_PKCS1_PADDING);
427         if(ret <= 0)
428                 free(*encrypted);
429         return ret;
430 }
431
432 int crypt_rsa_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char **data) {
433         if(!privkey)
434                 return 0;
435         if(enclen > RSA_size(privkey->rsa))
436                 return 0;
437         *data = malloc(RSA_size(privkey->rsa));
438         if(!*data)
439                 return 0;
440         int ret = RSA_private_decrypt(enclen, encrypted, *data, privkey->rsa, RSA_PKCS1_PADDING);
441         if(ret <= 0)
442                 free(*data);
443         return ret;
444 }
445
446 int crypt_rsa_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) {
447         return RSA_size(pubkey->rsa) - 12;
448 }
449
450 void crypt_rsa_encrypt_free(char *encrypted) {
451         free(encrypted);
452 }
453
454 void crypt_rsa_decrypt_free(char *data) {
455         free(data);
456 }
457
458 //#endif