--- /dev/null
+/* crypt_rsa.c - NextIRCd
+ * Copyright (C) 2012-2013 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "../config.h"
+struct crypt_rsa_pubkey;
+struct crypt_rsa_privkey;
+
+static struct crypt_rsa_pubkey *crypt_load_pubkey(const char *key);
+static void crypt_unload_pubkey(struct crypt_rsa_pubkey *pubkey);
+static struct crypt_rsa_privkey *crypt_load_privkey(const char *key);
+static void crypt_unload_privkey(struct crypt_rsa_privkey *privkey);
+
+static void crypt_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char *encrypted);
+static void crypt_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char *data);
+static int crypt_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey);
+static void crypt_encrypt_free(char *encrypted);
+static void crypt_decrypt_free(char *data);
+
+
+
+
+
+#if defined(HAVE_GNUTLS_GNUTLS_H)
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+struct crypt_rsa_pubkey {
+ unsigned int free_crt : 1;
+ unsigned int free_pubkey : 1;
+ gnutls_x509_crt_t crt;
+ gnutls_pubkey_t pubkey;
+}
+
+struct crypt_rsa_privkey {
+ unsigned int free_key : 1;
+ unsigned int free_privkey : 1;
+ gnutls_x509_privkey_t key;
+ gnutls_privkey_t privkey;
+}
+
+static struct crypt_rsa_pubkey *crypt_load_pubkey(const char *key) {
+ struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
+ int ret;
+ const gnutls_datum_t key_dat = {(void *)key, strlen(key)};
+
+ if(!pubkey)
+ return NULL;
+
+ ret = gnutls_x509_crt_init(&pubkey->crt);
+ if(ret < 0)
+ goto crypt_load_pubkey_fail;
+ pubkey->free_crt = 1;
+
+ ret = gnutls_x509_crt_import(pubkey->crt, &key_dat, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ goto crypt_load_pubkey_fail;
+
+ ret = gnutls_pubkey_init(&pubkey.pubkey);
+ if(ret < 0)
+ goto crypt_load_pubkey_fail;
+ pubkey->free_pubkey = 1;
+
+ ret = gnutls_pubkey_import_x509(pubkey->pubkey, pubkey->crt, 0);
+ if(ret < 0)
+ goto crypt_load_pubkey_fail;
+
+ return pubkey;
+ crypt_load_pubkey_fail:
+ crypt_unload_pubkey(pubkey);
+ return NULL;
+}
+
+static void crypt_unload_pubkey(struct crypt_rsa_pubkey *pubkey) {
+ if(pubkey->free_key)
+ gnutls_x509_crt_deinit(pubkey->crt);
+ if(pubkey->free_privkey)
+ gnutls_pubkey_deinit(pubkey->pubkey);
+ free(pubkey);
+}
+
+static struct crypt_rsa_privkey *crypt_load_privkey(const char *key) {
+ struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey));
+ int ret;
+
+ const gnutls_datum_t key_dat = {(void *)key, strlen(key)};
+ privkey.valid = 0;
+
+ ret = gnutls_x509_privkey_init(&privkey->key);
+ if(ret < 0)
+ goto crypt_load_privkey_fail;
+ privkey->free_key = 1;
+
+ ret = gnutls_x509_privkey_import(privkey->key, &key_dat, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ goto crypt_load_privkey_fail;
+
+ ret = gnutls_privkey_init(&privkey.privkey);
+ if(ret < 0)
+ goto crypt_load_privkey_fail;
+ privkey->free_privkey = 1;
+
+ ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0);
+ if(ret < 0)
+ goto crypt_load_privkey_fail;
+
+ return privkey;
+ crypt_load_privkey_fail:
+ crypt_unload_privkey(privkey);
+ return NULL;
+}
+
+static void crypt_unload_privkey(struct crypt_rsa_privkey *privkey) {
+ if(privkey->free_key)
+ gnutls_x509_privkey_deinit(privkey->key);
+ if(privkey->free_privkey)
+ gnutls_privkey_deinit(privkey->privkey);
+ free(privkey);
+}
+
+
+static void crypt_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char *encrypted) {
+
+}
+
+static void crypt_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char *data) {
+
+}
+
+static int crypt_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) {
+ int size = (pubkey->pubkey->bits / 8) - 12;
+ return size;
+}
+
+static void crypt_encrypt_free(char *encrypted) {
+
+}
+
+static void crypt_decrypt_free(char *data) {
+
+}
+
+#elif defined(HAVE_OPENSSL_SSL_H)
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+
+struct crypt_rsa_pubkey {
+ RSA *rsa;
+}
+
+struct crypt_rsa_privkey {
+ RSA *rsa;
+}
+
+static RSA *createRSA(unsigned char *key, int public) {
+ RSA *rsa= NULL;
+ BIO *keybio ;
+ keybio = BIO_new_mem_buf(key, -1);
+ if(!keybio)
+ return NULL;
+ if(public)
+ rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
+ else
+ rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
+ BIO_free(keybio);
+ return rsa;
+}
+
+static struct crypt_rsa_pubkey *crypt_load_pubkey(const char *key) {
+ struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey));
+ if(!pubkey)
+ return NULL;
+
+ RSA *rsa = createRSA((unsigned char) key, 1);
+
+ if(!rsa) {
+ free(pubkey);
+ return NULL;
+ }
+
+ pubkey->rsa = rsa;
+ return pubkey;
+}
+
+static void crypt_unload_pubkey(struct crypt_rsa_pubkey *pubkey) {
+ RSA_free(pubkey->rsa);
+ free(pubkey);
+}
+
+static struct crypt_rsa_privkey *crypt_load_privkey(const char *key) {
+ struct crypt_rsa_pubkey *privkey = calloc(1, sizeof(*pubkey));
+ if(!privkey)
+ return NULL;
+
+ RSA *rsa = createRSA((unsigned char) key, 0);
+
+ if(!rsa) {
+ free(privkey);
+ return NULL;
+ }
+
+ privkey->rsa = rsa;
+ return privkey;
+}
+
+static void crypt_unload_pubkey(struct crypt_rsa_privkey *privkey) {
+ RSA_free(privkey->rsa);
+ free(privkey);
+}
+
+static int crypt_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char **encrypted) {
+ if(!pubkey)
+ return 0;
+ if(datalen > crypt_encrypt_maxlen(pubkey))
+ return 0;
+ *encrypted = malloc(RSA_size(pubkey->rsa));
+ if(!*encrypted)
+ return 0;
+ int ret = RSA_public_encrypt(datalen, data, *encrypted, pubkey->rsa, RSA_PKCS1_PADDING);
+ if(ret <= 0)
+ free(*encrypted);
+ return ret;
+}
+
+static int crypt_decrypt_data(struct crypt_rsa_pubkey *privkey, const char *encrypted, int enclen, char **data) {
+ if(!privkey)
+ return 0;
+ if(enclen > RSA_size(privkey->rsa))
+ return 0;
+ *data = malloc(RSA_size(privkey->rsa));
+ if(!*data)
+ return 0;
+ int ret = RSA_private_decrypt(enclen, encrypted, *data, privkey->rsa, RSA_PKCS1_PADDING);
+ if(ret <= 0)
+ free(*data);
+ return ret;
+}
+
+static int crypt_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) {
+ return RSA_size(pubkey->rsa) - 12;
+}
+
+static void crypt_encrypt_free(char *encrypted) {
+ free(encrypted);
+}
+
+static void crypt_decrypt_free(char *data) {
+ free(data);
+}
+
+#endif