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 int main(char *argv[], int argc) {
27         crypt_init();
28         
29         struct crypt_rsa_privkey *privkey;
30         FILE *fp;
31         if(fp = fopen("privkey.pem", "r")) {
32                 char buffer[4096];
33                 fread(buffer, sizeof(buffer), 1, fp);
34                 fclose(fp);
35                 
36                 privkey = crypt_load_privkey(buffer);
37         } else {
38                 privkey = crypt_generate_privkey(2048);
39                 
40                 fp = fopen("privkey.pem", "w");
41                 char *buffer = crypt_export_privkey(privkey, 0);
42                 fprintf(fp, "%s", buffer);
43                 free(buffer);
44                 fclose(fp);
45         }
46         
47         struct crypt_rsa_pubkey *pubkey = crypt_get_pubkey(privkey);
48         char plain[] = "Test String!!!";
49         char *crypted = NULL;
50         int len = crypt_encrypt_data(pubkey, plain, sizeof(plain), &crypted);
51         
52         printf("Crypt Len: %d\n", len);
53         printf("Crypt: ");
54         int i;
55         for(i = 0; i < len; i++) {
56                 printf(" %02X", ((unsigned int)crypted[i] & 0xFF));
57         }
58         printf("\n");
59         
60         char *decrypted = NULL;
61         len = crypt_decrypt_data(privkey, crypted, len, &decrypted);
62         printf("Decrypt Len: %d\n", len);
63         printf("Decrypt: %s\n", decrypted);
64 }
65
66
67
68 /*
69 // GnuTLS Backend not working because of gnutls_pubkey_encrypt_data doesn't exists prior to GnuTLS 3.0
70 // still searching for a replacement...
71
72 #if defined(HAVE_GNUTLS_GNUTLS_H)
73 #include <gnutls/gnutls.h>
74 #include <gnutls/x509.h>
75 #include <gnutls/abstract.h>
76
77 struct crypt_rsa_pubkey {
78         unsigned int free_crt : 1;
79         unsigned int free_pubkey : 1;
80         gnutls_x509_crt_t crt;
81         gnutls_pubkey_t pubkey;
82 };
83
84 struct crypt_rsa_privkey {
85         unsigned int free_key : 1;
86         unsigned int free_privkey : 1;
87         gnutls_x509_privkey_t key;
88         gnutls_privkey_t privkey;
89 };
90
91 void crypt_rsa_init() {
92         gnutls_global_init();
93 }
94
95 void crypt_rsa_deinit() {
96         gnutls_global_deinit();
97 }
98
99 struct crypt_rsa_pubkey *crypt_rsa_load_pubkey(const char *key) {
100         struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
101         int ret;
102         const gnutls_datum_t key_dat = {(void *)key, strlen(key)};
103         
104         if(!pubkey)
105                 return NULL;
106         
107         ret = gnutls_x509_crt_init(&pubkey->crt);
108         if(ret < 0)
109                 goto crypt_rsa_load_pubkey_fail;
110         pubkey->free_crt = 1;
111         
112         ret = gnutls_x509_crt_import(pubkey->crt, &key_dat, GNUTLS_X509_FMT_PEM);
113         if (ret < 0)
114                 goto crypt_rsa_load_pubkey_fail;
115         
116         ret = gnutls_pubkey_init(&pubkey->pubkey);
117         if(ret < 0)
118                 goto crypt_rsa_load_pubkey_fail;
119         pubkey->free_pubkey = 1;
120         
121         ret = gnutls_pubkey_import_x509(pubkey->pubkey, pubkey->crt, 0);
122         if(ret < 0)
123                 goto crypt_rsa_load_pubkey_fail;
124         
125         return pubkey;
126         crypt_rsa_load_pubkey_fail:
127         crypt_rsa_unload_pubkey(pubkey);
128         return NULL;
129 }
130
131 void crypt_rsa_unload_pubkey(struct crypt_rsa_pubkey *pubkey) {
132         if(pubkey->free_crt)
133                 gnutls_x509_crt_deinit(pubkey->crt);
134         if(pubkey->free_pubkey)
135                 gnutls_pubkey_deinit(pubkey->pubkey);
136         free(pubkey);
137 }
138
139 char *crypt_rsa_export_pubkey(struct crypt_rsa_pubkey *pubkey) {
140         size_t size = 1024;
141         char *buffer = malloc(size);
142         int ret;
143         
144         ret = gnutls_pubkey_export(pubkey->pubkey, GNUTLS_X509_FMT_PEM, buffer, &size);
145         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
146                 buffer = realloc(buffer, size);
147                 ret = gnutls_pubkey_export(pubkey->pubkey, GNUTLS_X509_FMT_PEM, buffer, &size);
148         }
149         if(ret < 0) {
150                 free(buffer);
151                 return NULL;
152         }
153         return buffer;
154 }
155
156 struct crypt_rsa_privkey *crypt_rsa_load_privkey(const char *key) {
157         struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
158         int ret;
159         
160         const gnutls_datum_t key_dat = {(void *)key, strlen(key)};
161         
162         ret = gnutls_x509_privkey_init(&privkey->key);
163         if(ret < 0)
164                 goto crypt_rsa_load_privkey_fail;
165         privkey->free_key = 1;
166         
167         ret = gnutls_x509_privkey_import(privkey->key, &key_dat, GNUTLS_X509_FMT_PEM);
168         if (ret < 0)
169                 goto crypt_rsa_load_privkey_fail;
170         
171         ret = gnutls_privkey_init(&privkey->privkey);
172         if(ret < 0)
173                 goto crypt_rsa_load_privkey_fail;
174         privkey->free_privkey = 1;
175         
176         ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0);
177         if(ret < 0)
178                 goto crypt_rsa_load_privkey_fail;
179         
180         return privkey;
181         crypt_rsa_load_privkey_fail:
182         crypt_rsa_unload_privkey(privkey);
183         return NULL;
184 }
185
186 struct crypt_rsa_privkey *crypt_rsa_generate_privkey(const int keysize) {
187         struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
188         int ret;
189         
190         ret = gnutls_x509_privkey_init(&privkey->key);
191         if(ret < 0)
192                 goto crypt_rsa_generate_privkey_fail;
193         privkey->free_key = 1;
194         
195         ret = gnutls_x509_privkey_generate(privkey->key, GNUTLS_PK_RSA, keysize, 0);
196         if (ret < 0)
197                 goto crypt_rsa_generate_privkey_fail;
198         
199         ret = gnutls_privkey_init(&privkey->privkey);
200         if(ret < 0)
201                 goto crypt_rsa_generate_privkey_fail;
202         privkey->free_privkey = 1;
203         
204         ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0);
205         if(ret < 0)
206                 goto crypt_rsa_generate_privkey_fail;
207         
208         return privkey;
209         crypt_rsa_generate_privkey_fail:
210         crypt_rsa_unload_privkey(privkey);
211         return NULL;
212 }
213
214 char *crypt_rsa_export_privkey(struct crypt_rsa_privkey *privkey, int pubkey) {
215         size_t size = 1024;
216         char *buffer = malloc(size);
217         int ret;
218         
219         if(pubkey) {
220                 gnutls_pubkey_t pkey;
221                 ret = gnutls_pubkey_init(&pkey);
222                 if(ret < 0) {
223                         free(buffer);
224                         return NULL;
225                 }
226                 ret = gnutls_pubkey_import_privkey(pkey, privkey->privkey, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
227                 if(ret < 0) {
228                         free(buffer);
229                         gnutls_pubkey_deinit(pkey);
230                         return NULL;
231                 }
232                 ret = gnutls_pubkey_export(pkey, GNUTLS_X509_FMT_PEM, buffer, &size);
233                 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
234                         buffer = realloc(buffer, size);
235                         ret = gnutls_pubkey_export(pkey, GNUTLS_X509_FMT_PEM, buffer, &size);
236                 }
237                 gnutls_pubkey_deinit(pkey);
238         } else {
239                 ret = gnutls_x509_privkey_export(privkey->key, GNUTLS_X509_FMT_PEM, buffer, &size);
240                 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
241                         buffer = realloc(buffer, size);
242                         ret = gnutls_x509_privkey_export(privkey->key, GNUTLS_X509_FMT_PEM, buffer, &size);
243                 }
244         }
245         if(ret < 0) {
246                 free(buffer);
247                 return NULL;
248         }
249         return buffer;
250 }
251
252 void crypt_rsa_unload_privkey(struct crypt_rsa_privkey *privkey) {
253         if(privkey->free_key)
254                 gnutls_x509_privkey_deinit(privkey->key);
255         if(privkey->free_privkey)
256                 gnutls_privkey_deinit(privkey->privkey);
257         free(privkey);
258 }
259
260 struct crypt_rsa_pubkey *crypt_rsa_get_pubkey(struct crypt_rsa_privkey *privkey) {
261         struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
262         if(!pubkey)
263                 return NULL;
264         int ret;
265         
266         ret = gnutls_pubkey_init(&pubkey->pubkey);
267         if(ret < 0)
268                 goto crypt_rsa_get_pubkey_fail;
269         pubkey->free_pubkey = 1;
270         
271         ret = gnutls_pubkey_import_privkey(pubkey->pubkey, privkey->privkey, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
272         if(ret < 0)
273                 goto crypt_rsa_get_pubkey_fail;
274         
275         return pubkey;
276         crypt_rsa_get_pubkey_fail:
277         crypt_rsa_unload_pubkey(pubkey);
278         return NULL;
279 }
280
281 int crypt_rsa_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char **encrypted) {
282         const gnutls_datum_t data_dat = {(void *)data, datalen};
283         gnutls_datum_t out;
284         
285         int ret = gnutls_pubkey_encrypt_data(pubkey->pubkey, 0, &data_dat, &out);
286         if(ret < 0)
287                 return ret;
288         
289         *encrypted = out.data;
290         return out.size;
291 }
292
293 int crypt_rsa_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char **data) {
294         const gnutls_datum_t enc_dat = {(void *)encrypted, enclen};
295         gnutls_datum_t out;
296         
297         int ret = gnutls_privkey_decrypt_data(privkey->privkey, 0, &enc_dat, &out);
298         if(ret < 0)
299                 return ret;
300         
301         *data = out.data;
302         return out.size;
303 }
304
305 int crypt_rsa_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) {
306         //int size = (pubkey->pubkey->bits / 8) - 12;
307         //todo!
308         int size = 1024;
309         return size;
310 }
311
312 void crypt_rsa_encrypt_free(char *encrypted) {
313         gnutls_free(encrypted);
314 }
315
316 void crypt_rsa_decrypt_free(char *data) {
317         gnutls_free(data);
318 }
319
320 #elif defined(HAVE_OPENSSL_SSL_H)
321 */
322
323 #include <openssl/pem.h>
324 #include <openssl/ssl.h>
325 #include <openssl/rsa.h>
326 #include <openssl/evp.h>
327 #include <openssl/bio.h>
328 #include <openssl/err.h>
329
330 struct crypt_rsa_pubkey {
331         RSA *rsa;
332 };
333
334 struct crypt_rsa_privkey {
335         RSA *rsa;
336 };
337
338 void crypt_rsa_init() {
339         
340 }
341
342 void crypt_rsa_deinit() {
343         
344 }
345
346 RSA *createRSA(unsigned char *key, int public) {
347     RSA *rsa= NULL;
348     BIO *keybio ;
349     keybio = BIO_new_mem_buf(key, -1);
350     if(!keybio)
351         return NULL;
352     if(public)
353         rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
354     else
355         rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
356     BIO_free(keybio);
357     return rsa;
358 }
359
360 struct crypt_rsa_pubkey *crypt_rsa_load_pubkey(const char *key) {
361         struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
362         if(!pubkey)
363                 return NULL;
364         
365         RSA *rsa = createRSA((unsigned char *) key, 1);
366         
367         if(!rsa) {
368                 free(pubkey);
369                 return NULL;
370         }
371         
372         pubkey->rsa = rsa;
373         return pubkey;
374 }
375
376 void crypt_rsa_unload_pubkey(struct crypt_rsa_pubkey *pubkey) {
377         RSA_free(pubkey->rsa);
378         free(pubkey);
379 }
380
381 char *crypt_rsa_export_pubkey(struct crypt_rsa_pubkey *pubkey) {
382         BIO *bio = BIO_new(BIO_s_mem());
383         PEM_write_bio_RSA_PUBKEY(bio, pubkey->rsa);
384         
385         int keylen = BIO_pending(bio);
386         char *key = calloc(1, keylen+1);
387         BIO_read(bio, key, keylen);
388         
389         BIO_free_all(bio);
390         return key;
391 }
392
393 struct crypt_rsa_privkey *crypt_rsa_load_privkey(const char *key) {
394         struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
395         if(!privkey)
396                 return NULL;
397         
398         RSA *rsa = createRSA((unsigned char *) key, 0);
399         
400         if(!rsa) {
401                 free(privkey);
402                 return NULL;
403         }
404         
405         privkey->rsa = rsa;
406         return privkey;
407 }
408
409 struct crypt_rsa_privkey *crypt_rsa_generate_privkey(const int keysize) {
410         struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
411         if(!privkey)
412                 return NULL;
413                 
414         BIGNUM *e = BN_new();
415         RSA *rsa = RSA_new();
416         
417         BN_set_word(e, 65537);
418         if (!RSA_generate_key_ex(rsa, keysize, e, NULL)) {
419                 BN_free(e);
420                 RSA_free(rsa);
421                 free(privkey);
422                 return NULL;
423         }
424         
425         privkey->rsa = rsa;
426         return privkey;
427 }
428
429 char *crypt_rsa_export_privkey(struct crypt_rsa_privkey *privkey, int pubkey) {
430         BIO *bio = BIO_new(BIO_s_mem());
431         if(pubkey)
432                 PEM_write_bio_RSA_PUBKEY(bio, privkey->rsa);
433         else
434                 PEM_write_bio_RSAPrivateKey(bio, privkey->rsa, NULL, NULL, 0, NULL, NULL);
435         
436         int keylen = BIO_pending(bio);
437         char *key = calloc(1, keylen+1);
438         BIO_read(bio, key, keylen);
439         
440         BIO_free_all(bio);
441         return key;
442 }
443
444 void crypt_rsa_unload_privkey(struct crypt_rsa_privkey *privkey) {
445         RSA_free(privkey->rsa);
446         free(privkey);
447 }
448
449 struct crypt_rsa_pubkey *crypt_rsa_get_pubkey(struct crypt_rsa_privkey *privkey) {
450         struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
451         if(!pubkey)
452                 return NULL;
453         
454         RSA *rsa = RSA_new();
455         memcpy(rsa, privkey->rsa, sizeof(*rsa));
456         
457         pubkey->rsa = rsa;
458         return pubkey;
459 }
460
461 int crypt_rsa_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char **encrypted) {
462         if(!pubkey)
463                 return 0;
464         if(datalen > crypt_rsa_encrypt_maxlen(pubkey))
465                 return 0;
466         *encrypted = malloc(RSA_size(pubkey->rsa));
467         if(!*encrypted)
468                 return 0;
469         int ret = RSA_public_encrypt(datalen, data, *encrypted, pubkey->rsa, RSA_PKCS1_PADDING);
470         if(ret <= 0)
471                 free(*encrypted);
472         return ret;
473 }
474
475 int crypt_rsa_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char **data) {
476         if(!privkey)
477                 return 0;
478         if(enclen > RSA_size(privkey->rsa))
479                 return 0;
480         *data = malloc(RSA_size(privkey->rsa));
481         if(!*data)
482                 return 0;
483         int ret = RSA_private_decrypt(enclen, encrypted, *data, privkey->rsa, RSA_PKCS1_PADDING);
484         if(ret <= 0)
485                 free(*data);
486         return ret;
487 }
488
489 int crypt_rsa_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) {
490         return RSA_size(pubkey->rsa) - 12;
491 }
492
493 void crypt_rsa_encrypt_free(char *encrypted) {
494         free(encrypted);
495 }
496
497 void crypt_rsa_decrypt_free(char *data) {
498         free(data);
499 }
500
501 //#endif