X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=openssl.c;h=0ad9d7db4e7f035dce140365b2b38abc144b6923;hp=f786ce29bc715ab72c12e49088aaf15fb9cf8fb7;hb=bfb0f769d96dee610a25682b3b9c4218bc315b31;hpb=f1adf8b86e072e22353e0481d96d13f627c364b4 diff --git a/openssl.c b/openssl.c index f786ce29..0ad9d7db 100644 --- a/openssl.c +++ b/openssl.c @@ -16,9 +16,7 @@ #include "error.h" #include "string.h" #include "crypt.h" -#include "fd.h" #include "crypt_backend.h" -#include "base64.h" #include "portable_io.h" struct asymmetric_key { @@ -45,7 +43,7 @@ void get_random_bytes_or_die(unsigned char *buf, int num) * \sa RAND_load_file(3), \ref get_random_bytes_or_die(), srandom(3), * random(3), \ref para_random(). */ -void init_random_seed_or_die(void) +void crypt_init(void) { int seed, ret = RAND_load_file("/dev/urandom", 64); @@ -57,24 +55,17 @@ void init_random_seed_or_die(void) srandom(seed); } -static int get_private_key(const char *path, RSA **rsa) +void crypt_shutdown(void) { - EVP_PKEY *pkey; - BIO *bio = BIO_new(BIO_s_file()); - - *rsa = NULL; - if (!bio) - return -E_PRIVATE_KEY; - if (BIO_read_filename(bio, path) <= 0) - goto bio_free; - pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); - if (!pkey) - goto bio_free; - *rsa = EVP_PKEY_get1_RSA(pkey); - EVP_PKEY_free(pkey); -bio_free: - BIO_free(bio); - return *rsa? RSA_size(*rsa) : -E_PRIVATE_KEY; +#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA + CRYPTO_cleanup_all_ex_data(); +#endif +#ifdef HAVE_OPENSSL_THREAD_STOP /* openssl-1.1 or later */ + OPENSSL_thread_stop(); +#else /* openssl-1.0 */ + ERR_remove_thread_state(NULL); +#endif + EVP_cleanup(); } /* @@ -121,11 +112,11 @@ static int read_rsa_bignums(const unsigned char *blob, int blen, RSA **result) return -E_BIGNUM; ret = read_bignum(p, end - p, &e); if (ret < 0) - goto fail; + goto free_rsa; p += ret; ret = read_bignum(p, end - p, &n); if (ret < 0) - goto fail; + goto free_e; #ifdef HAVE_RSA_SET0_KEY RSA_set0_key(rsa, n, e, NULL); #else @@ -134,58 +125,187 @@ static int read_rsa_bignums(const unsigned char *blob, int blen, RSA **result) #endif *result = rsa; return 1; -fail: +free_e: + BN_free(e); +free_rsa: RSA_free(rsa); return ret; } -int get_public_key(const char *key_file, struct asymmetric_key **result) +static int read_pem_private_key(const char *path, RSA **rsa) +{ + EVP_PKEY *pkey; + BIO *bio = BIO_new(BIO_s_file()); + + *rsa = NULL; + if (!bio) + return -E_PRIVATE_KEY; + if (BIO_read_filename(bio, path) <= 0) + goto bio_free; + pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + if (!pkey) + goto bio_free; + *rsa = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); +bio_free: + BIO_free(bio); + return *rsa? RSA_size(*rsa) : -E_PRIVATE_KEY; +} + +static int read_private_rsa_params(const unsigned char *blob, + const unsigned char *end, RSA **result) { - struct asymmetric_key *key = NULL; - void *map = NULL; - unsigned char *blob = NULL; - size_t map_size, encoded_size, decoded_size; - int ret, ret2; - char *cp; - - key = para_malloc(sizeof(*key)); - ret = mmap_full_file(key_file, O_RDONLY, &map, &map_size, NULL); + int ret; + RSA *rsa; + BN_CTX *ctx; + BIGNUM *n, *e, *d, *iqmp, *p, *q; /* stored in the key file */ + BIGNUM *dmp1, *dmq1; /* these will be computed */ + BIGNUM *tmp; + const unsigned char *cp = blob; + + rsa = RSA_new(); + if (!rsa) + return -E_BIGNUM; + ret = -E_BIGNUM; + tmp = BN_new(); + if (!tmp) + goto free_rsa; + ctx = BN_CTX_new(); + if (!ctx) + goto free_tmp; + dmp1 = BN_new(); + if (!dmp1) + goto free_ctx; + dmq1 = BN_new(); + if (!dmq1) + goto free_dmp1; + ret = read_bignum(cp, end - cp, &n); if (ret < 0) - goto out; - ret = is_ssh_rsa_key(map, map_size); - if (!ret) { - ret = -E_SSH_PARSE; - goto out_unmap; - } - cp = map + ret; - encoded_size = map_size - ret; - PARA_INFO_LOG("decoding public rsa-ssh key %s\n", key_file); - ret = uudecode(cp, encoded_size, (char **)&blob, &decoded_size); + goto free_dmq1; + cp += ret; + ret = read_bignum(cp, end - cp, &e); + if (ret < 0) + goto free_n; + cp += ret; + ret = read_bignum(cp, end - cp, &d); + if (ret < 0) + goto free_e; + cp += ret; + ret = read_bignum(cp, end - cp, &iqmp); + if (ret < 0) + goto free_d; + cp += ret; + ret = read_bignum(cp, end - cp, &p); + if (ret < 0) + goto free_iqmp; + cp += ret; + ret = read_bignum(cp, end - cp, &q); + if (ret < 0) + goto free_p; + ret = -E_BIGNUM; + if (!BN_sub(tmp, q, BN_value_one())) + goto free_q; + if (!BN_mod(dmp1, d, tmp, ctx)) + goto free_q; + if (!BN_sub(tmp, q, BN_value_one())) + goto free_q; + if (!BN_mod(dmq1, d, tmp, ctx)) + goto free_q; +#ifdef HAVE_RSA_SET0_KEY + RSA_set0_key(rsa, n, e, d); + RSA_set0_factors(rsa, p, q); + RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp); +#else + rsa->n = n; + rsa->e = e; + rsa->d = d; + rsa->p = p; + rsa->q = q; + rsa->dmp1 = dmp1; + rsa->dmq1 = dmq1; + rsa->iqmp = iqmp; +#endif + *result = rsa; + ret = 1; + goto free_ctx; +free_q: + BN_clear_free(q); +free_p: + BN_clear_free(p); +free_iqmp: + BN_clear_free(iqmp); +free_d: + BN_clear_free(d); +free_e: + BN_free(e); +free_n: + BN_free(n); +free_dmq1: + BN_clear_free(dmq1); +free_dmp1: + BN_clear_free(dmp1); +free_ctx: + BN_CTX_free(ctx); +free_tmp: + BN_clear_free(tmp); +free_rsa: + if (ret < 0) + RSA_free(rsa); + return ret; +} + +static int get_private_key(const char *path, RSA **rsa) +{ + int ret; + unsigned char *blob, *end; + size_t blob_size; + + *rsa = NULL; + ret = decode_private_key(path, &blob, &blob_size); if (ret < 0) - goto out_unmap; - ret = check_ssh_key_header(blob, decoded_size); + return ret; + end = blob + blob_size; + if (ret == PKT_OPENSSH) { + ret = find_openssh_bignum_offset(blob, blob_size); + if (ret < 0) + goto free_blob; + PARA_INFO_LOG("reading RSA params at offset %d\n", ret); + ret = read_private_rsa_params(blob + ret, end, rsa); + } else + ret = read_pem_private_key(path, rsa); +free_blob: + free(blob); + return ret; +} + +int apc_get_pubkey(const char *key_file, struct asymmetric_key **result) +{ + unsigned char *blob; + size_t decoded_size; + int ret; + struct asymmetric_key *key = para_malloc(sizeof(*key)); + + ret = decode_public_key(key_file, &blob, &decoded_size); if (ret < 0) - goto out_unmap; + goto out; ret = read_rsa_bignums(blob + ret, decoded_size - ret, &key->rsa); if (ret < 0) - goto out_unmap; + goto free_blob; ret = RSA_size(key->rsa); -out_unmap: - ret2 = para_munmap(map, map_size); - if (ret >= 0 && ret2 < 0) - ret = ret2; + assert(ret > 0); + *result = key; +free_blob: + free(blob); out: if (ret < 0) { free(key); *result = NULL; - PARA_ERROR_LOG("key %s: %s\n", key_file, para_strerror(-ret)); - } else - *result = key; - free(blob); + PARA_ERROR_LOG("can not load key %s\n", key_file); + } return ret; } -void free_public_key(struct asymmetric_key *key) +void apc_free_pubkey(struct asymmetric_key *key) { if (!key) return; @@ -193,7 +313,7 @@ void free_public_key(struct asymmetric_key *key) free(key); } -int priv_decrypt(const char *key_file, unsigned char *outbuf, +int apc_priv_decrypt(const char *key_file, unsigned char *outbuf, unsigned char *inbuf, int inlen) { struct asymmetric_key *priv; @@ -228,7 +348,7 @@ out: return ret; } -int pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf, +int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf, unsigned len, unsigned char *outbuf) { int ret, flen = len; /* RSA_public_encrypt expects a signed int */