2016-08-18 09:39:55 +00:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
|
|
|
|
#include <openssl/pem.h>
|
|
|
|
#include <openssl/rand.h>
|
|
|
|
#include <openssl/rsa.h>
|
|
|
|
#include <openssl/err.h>
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include "rsa.h"
|
|
|
|
#include "utils.h"
|
|
|
|
|
2018-05-11 10:48:17 +00:00
|
|
|
/* Forward compatibility functions if libssl < 1.1.0. */
|
|
|
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
|
|
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* If the fields n and e in r are NULL, the corresponding input
|
|
|
|
* parameters MUST be non-NULL for n and e. d may be
|
|
|
|
* left NULL (in case only the public key is used).
|
|
|
|
*/
|
|
|
|
if ((r->n == NULL && n == NULL)
|
|
|
|
|| (r->e == NULL && e == NULL))
|
|
|
|
return 0;
|
|
|
|
if (n != NULL) {
|
|
|
|
BN_free(r->n);
|
|
|
|
r->n = n;
|
|
|
|
}
|
|
|
|
if (e != NULL) {
|
|
|
|
BN_free(r->e);
|
|
|
|
r->e = e;
|
|
|
|
}
|
|
|
|
if (d != NULL) {
|
|
|
|
BN_free(r->d);
|
|
|
|
r->d = d;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RSA_get0_key(const RSA *r,
|
|
|
|
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (n != NULL)
|
|
|
|
*n = r->n;
|
|
|
|
if (e != NULL)
|
|
|
|
*e = r->e;
|
|
|
|
if (d != NULL)
|
|
|
|
*d = r->d;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-08-18 09:39:55 +00:00
|
|
|
RSA*
|
|
|
|
private_key_to_pub(RSA *priv)
|
|
|
|
{
|
|
|
|
RSA *pub = RSA_new();
|
2018-05-11 10:48:17 +00:00
|
|
|
const BIGNUM *n, *e;
|
2016-08-18 09:39:55 +00:00
|
|
|
|
2018-05-11 10:48:17 +00:00
|
|
|
RSA_get0_key (priv, &n, &e, NULL);
|
|
|
|
RSA_set0_key (pub, BN_dup(n), BN_dup(e), NULL);
|
2016-08-18 09:39:55 +00:00
|
|
|
|
|
|
|
return pub;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GString* public_key_to_gstring(const RSA *rsa)
|
|
|
|
{
|
|
|
|
GString *buf = g_string_new(NULL);
|
|
|
|
unsigned char *temp;
|
|
|
|
char *coded;
|
2018-05-11 10:48:17 +00:00
|
|
|
const BIGNUM *n, *e;
|
|
|
|
|
|
|
|
RSA_get0_key (rsa, &n, &e, NULL);
|
|
|
|
gsize len = BN_num_bytes(n);
|
2016-08-18 09:39:55 +00:00
|
|
|
|
|
|
|
temp = malloc(len);
|
2018-05-11 10:48:17 +00:00
|
|
|
BN_bn2bin(n, temp);
|
2016-08-18 09:39:55 +00:00
|
|
|
coded = g_base64_encode(temp, len);
|
|
|
|
g_string_append (buf, coded);
|
|
|
|
g_string_append_c (buf, ' ');
|
|
|
|
g_free(coded);
|
|
|
|
|
2018-05-11 10:48:17 +00:00
|
|
|
len = BN_num_bytes(e);
|
2016-08-18 09:39:55 +00:00
|
|
|
temp = realloc(temp, len);
|
2018-05-11 10:48:17 +00:00
|
|
|
BN_bn2bin(e, temp);
|
2016-08-18 09:39:55 +00:00
|
|
|
coded = g_base64_encode(temp, len);
|
|
|
|
g_string_append (buf, coded);
|
|
|
|
g_free(coded);
|
|
|
|
|
|
|
|
free(temp);
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
public_key_append_to_gstring(const RSA *rsa, GString *buf)
|
|
|
|
{
|
|
|
|
unsigned char *temp;
|
|
|
|
char *coded;
|
2018-05-11 10:48:17 +00:00
|
|
|
const BIGNUM *n, *e;
|
2016-08-18 09:39:55 +00:00
|
|
|
|
2018-05-11 10:48:17 +00:00
|
|
|
RSA_get0_key (rsa, &n, &e, NULL);
|
|
|
|
gsize len = BN_num_bytes(n);
|
2016-08-18 09:39:55 +00:00
|
|
|
temp = malloc(len);
|
2018-05-11 10:48:17 +00:00
|
|
|
BN_bn2bin(n, temp);
|
2016-08-18 09:39:55 +00:00
|
|
|
coded = g_base64_encode(temp, len);
|
|
|
|
g_string_append (buf, coded);
|
|
|
|
g_string_append_c (buf, ' ');
|
|
|
|
g_free(coded);
|
|
|
|
|
2018-05-11 10:48:17 +00:00
|
|
|
len = BN_num_bytes(e);
|
2016-08-18 09:39:55 +00:00
|
|
|
temp = realloc(temp, len);
|
2018-05-11 10:48:17 +00:00
|
|
|
BN_bn2bin(e, temp);
|
2016-08-18 09:39:55 +00:00
|
|
|
coded = g_base64_encode(temp, len);
|
|
|
|
g_string_append (buf, coded);
|
|
|
|
g_free(coded);
|
|
|
|
|
|
|
|
free(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
RSA* public_key_from_string(char *str)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
unsigned char *num;
|
|
|
|
gsize len;
|
2018-05-11 10:48:17 +00:00
|
|
|
BIGNUM *n = NULL, *e = NULL;
|
|
|
|
|
2016-08-18 09:39:55 +00:00
|
|
|
if (!str)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if ( !(p = strchr(str, ' ')) )
|
|
|
|
return NULL;
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
RSA *key = RSA_new();
|
|
|
|
|
|
|
|
num = g_base64_decode(str, &len);
|
2018-05-11 10:48:17 +00:00
|
|
|
n = BN_bin2bn(num, len, NULL);
|
|
|
|
if (!n)
|
2016-08-18 09:39:55 +00:00
|
|
|
goto err;
|
|
|
|
g_free(num);
|
|
|
|
|
|
|
|
num = g_base64_decode(p+1, &len);
|
2018-05-11 10:48:17 +00:00
|
|
|
e = BN_bin2bn(num, len, NULL);
|
|
|
|
if (!e)
|
2016-08-18 09:39:55 +00:00
|
|
|
goto err;
|
|
|
|
g_free(num);
|
|
|
|
|
2018-05-11 10:48:17 +00:00
|
|
|
RSA_set0_key (key, n, e, NULL);
|
|
|
|
|
2016-08-18 09:39:55 +00:00
|
|
|
*p = ' ';
|
|
|
|
return key;
|
|
|
|
err:
|
|
|
|
*p = ' ';
|
|
|
|
RSA_free (key);
|
2018-05-11 10:48:17 +00:00
|
|
|
if (n)
|
|
|
|
BN_free (n);
|
|
|
|
if (e)
|
|
|
|
BN_free (e);
|
2016-08-18 09:39:55 +00:00
|
|
|
g_free(num);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char *
|
|
|
|
private_key_decrypt(RSA *key, unsigned char *data, int len, int *decrypt_len)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
unsigned char *buf;
|
|
|
|
|
|
|
|
size = RSA_size(key);
|
|
|
|
buf = g_malloc(size);
|
|
|
|
*decrypt_len = RSA_private_decrypt(len, data, buf, key, RSA_PKCS1_PADDING);
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char *
|
|
|
|
public_key_encrypt(RSA *key, unsigned char *data, int len, int *encrypt_len)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
unsigned char *buf;
|
|
|
|
|
|
|
|
size = RSA_size(key);
|
|
|
|
buf = g_malloc(size);
|
|
|
|
*encrypt_len = RSA_public_encrypt(len, data, buf, key, RSA_PKCS1_PADDING);
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
id_from_pubkey (RSA *pubkey)
|
|
|
|
{
|
|
|
|
GString *buf;
|
|
|
|
unsigned char sha1[20];
|
|
|
|
char *id = g_malloc(41);
|
|
|
|
|
|
|
|
buf = public_key_to_gstring (pubkey);
|
|
|
|
calculate_sha1 (sha1, buf->str);
|
|
|
|
sha1_to_hex (sha1, id);
|
|
|
|
g_string_free (buf, TRUE);
|
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
RSA *
|
|
|
|
generate_private_key(u_int bits)
|
|
|
|
{
|
|
|
|
RSA *private = NULL;
|
|
|
|
|
|
|
|
private = RSA_generate_key(bits, 35, NULL, NULL);
|
|
|
|
if (private == NULL)
|
|
|
|
g_error ("rsa_generate_private_key: key generation failed.");
|
|
|
|
return private;
|
|
|
|
}
|