1 /* crypt_rsa.c - NextIRCd
2 * Copyright (C) 2012-2013 Philipp Kreil (pk910)
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.
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.
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/>.
17 #include "../config.h"
18 #include "crypt_rsa.h"
26 int main(char *argv[], int argc) {
29 struct crypt_rsa_privkey *privkey;
31 if(fp = fopen("privkey.pem", "r")) {
33 fread(buffer, sizeof(buffer), 1, fp);
36 privkey = crypt_load_privkey(buffer);
38 privkey = crypt_generate_privkey(2048);
40 fp = fopen("privkey.pem", "w");
41 char *buffer = crypt_export_privkey(privkey, 0);
42 fprintf(fp, "%s", buffer);
47 struct crypt_rsa_pubkey *pubkey = crypt_get_pubkey(privkey);
48 char plain[] = "Test String!!!";
50 int len = crypt_encrypt_data(pubkey, plain, sizeof(plain), &crypted);
52 printf("Crypt Len: %d\n", len);
55 for(i = 0; i < len; i++) {
56 printf(" %02X", ((unsigned int)crypted[i] & 0xFF));
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);
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...
72 #if defined(HAVE_GNUTLS_GNUTLS_H)
73 #include <gnutls/gnutls.h>
74 #include <gnutls/x509.h>
75 #include <gnutls/abstract.h>
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;
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;
91 void crypt_rsa_init() {
95 void crypt_rsa_deinit() {
96 gnutls_global_deinit();
99 struct crypt_rsa_pubkey *crypt_rsa_load_pubkey(const char *key) {
100 struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
102 const gnutls_datum_t key_dat = {(void *)key, strlen(key)};
107 ret = gnutls_x509_crt_init(&pubkey->crt);
109 goto crypt_rsa_load_pubkey_fail;
110 pubkey->free_crt = 1;
112 ret = gnutls_x509_crt_import(pubkey->crt, &key_dat, GNUTLS_X509_FMT_PEM);
114 goto crypt_rsa_load_pubkey_fail;
116 ret = gnutls_pubkey_init(&pubkey->pubkey);
118 goto crypt_rsa_load_pubkey_fail;
119 pubkey->free_pubkey = 1;
121 ret = gnutls_pubkey_import_x509(pubkey->pubkey, pubkey->crt, 0);
123 goto crypt_rsa_load_pubkey_fail;
126 crypt_rsa_load_pubkey_fail:
127 crypt_rsa_unload_pubkey(pubkey);
131 void crypt_rsa_unload_pubkey(struct crypt_rsa_pubkey *pubkey) {
133 gnutls_x509_crt_deinit(pubkey->crt);
134 if(pubkey->free_pubkey)
135 gnutls_pubkey_deinit(pubkey->pubkey);
139 char *crypt_rsa_export_pubkey(struct crypt_rsa_pubkey *pubkey) {
141 char *buffer = malloc(size);
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);
156 struct crypt_rsa_privkey *crypt_rsa_load_privkey(const char *key) {
157 struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
160 const gnutls_datum_t key_dat = {(void *)key, strlen(key)};
162 ret = gnutls_x509_privkey_init(&privkey->key);
164 goto crypt_rsa_load_privkey_fail;
165 privkey->free_key = 1;
167 ret = gnutls_x509_privkey_import(privkey->key, &key_dat, GNUTLS_X509_FMT_PEM);
169 goto crypt_rsa_load_privkey_fail;
171 ret = gnutls_privkey_init(&privkey->privkey);
173 goto crypt_rsa_load_privkey_fail;
174 privkey->free_privkey = 1;
176 ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0);
178 goto crypt_rsa_load_privkey_fail;
181 crypt_rsa_load_privkey_fail:
182 crypt_rsa_unload_privkey(privkey);
186 struct crypt_rsa_privkey *crypt_rsa_generate_privkey(const int keysize) {
187 struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
190 ret = gnutls_x509_privkey_init(&privkey->key);
192 goto crypt_rsa_generate_privkey_fail;
193 privkey->free_key = 1;
195 ret = gnutls_x509_privkey_generate(privkey->key, GNUTLS_PK_RSA, keysize, 0);
197 goto crypt_rsa_generate_privkey_fail;
199 ret = gnutls_privkey_init(&privkey->privkey);
201 goto crypt_rsa_generate_privkey_fail;
202 privkey->free_privkey = 1;
204 ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0);
206 goto crypt_rsa_generate_privkey_fail;
209 crypt_rsa_generate_privkey_fail:
210 crypt_rsa_unload_privkey(privkey);
214 char *crypt_rsa_export_privkey(struct crypt_rsa_privkey *privkey, int pubkey) {
216 char *buffer = malloc(size);
220 gnutls_pubkey_t pkey;
221 ret = gnutls_pubkey_init(&pkey);
226 ret = gnutls_pubkey_import_privkey(pkey, privkey->privkey, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
229 gnutls_pubkey_deinit(pkey);
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);
237 gnutls_pubkey_deinit(pkey);
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);
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);
260 struct crypt_rsa_pubkey *crypt_rsa_get_pubkey(struct crypt_rsa_privkey *privkey) {
261 struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
266 ret = gnutls_pubkey_init(&pubkey->pubkey);
268 goto crypt_rsa_get_pubkey_fail;
269 pubkey->free_pubkey = 1;
271 ret = gnutls_pubkey_import_privkey(pubkey->pubkey, privkey->privkey, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
273 goto crypt_rsa_get_pubkey_fail;
276 crypt_rsa_get_pubkey_fail:
277 crypt_rsa_unload_pubkey(pubkey);
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};
285 int ret = gnutls_pubkey_encrypt_data(pubkey->pubkey, 0, &data_dat, &out);
289 *encrypted = out.data;
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};
297 int ret = gnutls_privkey_decrypt_data(privkey->privkey, 0, &enc_dat, &out);
305 int crypt_rsa_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) {
306 //int size = (pubkey->pubkey->bits / 8) - 12;
312 void crypt_rsa_encrypt_free(char *encrypted) {
313 gnutls_free(encrypted);
316 void crypt_rsa_decrypt_free(char *data) {
320 #elif defined(HAVE_OPENSSL_SSL_H)
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>
330 struct crypt_rsa_pubkey {
334 struct crypt_rsa_privkey {
338 void crypt_rsa_init() {
342 void crypt_rsa_deinit() {
346 RSA *createRSA(unsigned char *key, int public) {
349 keybio = BIO_new_mem_buf(key, -1);
353 rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
355 rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
360 struct crypt_rsa_pubkey *crypt_rsa_load_pubkey(const char *key) {
361 struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
365 RSA *rsa = createRSA((unsigned char *) key, 1);
376 void crypt_rsa_unload_pubkey(struct crypt_rsa_pubkey *pubkey) {
377 RSA_free(pubkey->rsa);
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);
385 int keylen = BIO_pending(bio);
386 char *key = calloc(1, keylen+1);
387 BIO_read(bio, key, keylen);
393 struct crypt_rsa_privkey *crypt_rsa_load_privkey(const char *key) {
394 struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
398 RSA *rsa = createRSA((unsigned char *) key, 0);
409 struct crypt_rsa_privkey *crypt_rsa_generate_privkey(const int keysize) {
410 struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
414 BIGNUM *e = BN_new();
415 RSA *rsa = RSA_new();
417 BN_set_word(e, 65537);
418 if (!RSA_generate_key_ex(rsa, keysize, e, NULL)) {
429 char *crypt_rsa_export_privkey(struct crypt_rsa_privkey *privkey, int pubkey) {
430 BIO *bio = BIO_new(BIO_s_mem());
432 PEM_write_bio_RSA_PUBKEY(bio, privkey->rsa);
434 PEM_write_bio_RSAPrivateKey(bio, privkey->rsa, NULL, NULL, 0, NULL, NULL);
436 int keylen = BIO_pending(bio);
437 char *key = calloc(1, keylen+1);
438 BIO_read(bio, key, keylen);
444 void crypt_rsa_unload_privkey(struct crypt_rsa_privkey *privkey) {
445 RSA_free(privkey->rsa);
449 struct crypt_rsa_pubkey *crypt_rsa_get_pubkey(struct crypt_rsa_privkey *privkey) {
450 struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
454 RSA *rsa = RSA_new();
455 memcpy(rsa, privkey->rsa, sizeof(*rsa));
461 int crypt_rsa_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char **encrypted) {
464 if(datalen > crypt_rsa_encrypt_maxlen(pubkey))
466 *encrypted = malloc(RSA_size(pubkey->rsa));
469 int ret = RSA_public_encrypt(datalen, data, *encrypted, pubkey->rsa, RSA_PKCS1_PADDING);
475 int crypt_rsa_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char **data) {
478 if(enclen > RSA_size(privkey->rsa))
480 *data = malloc(RSA_size(privkey->rsa));
483 int ret = RSA_private_decrypt(enclen, encrypted, *data, privkey->rsa, RSA_PKCS1_PADDING);
489 int crypt_rsa_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) {
490 return RSA_size(pubkey->rsa) - 12;
493 void crypt_rsa_encrypt_free(char *encrypted) {
497 void crypt_rsa_decrypt_free(char *data) {