X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=openssl.c;h=0ad9d7db4e7f035dce140365b2b38abc144b6923;hp=99b3f7a6c3258bc5ef9981f062388a5a7d2854ba;hb=bfb0f769d96dee610a25682b3b9c4218bc315b31;hpb=5f20d9afde364f9ce51aa7841ebe513028a65e81 diff --git a/openssl.c b/openssl.c index 99b3f7a6..0ad9d7db 100644 --- a/openssl.c +++ b/openssl.c @@ -55,24 +55,17 @@ void crypt_init(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(); } /* @@ -119,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 @@ -132,19 +125,167 @@ 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) +{ + 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 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) + 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_ssh_key(key_file, &blob, &decoded_size); + ret = decode_public_key(key_file, &blob, &decoded_size); if (ret < 0) goto out; ret = read_rsa_bignums(blob + ret, decoded_size - ret, &key->rsa); @@ -164,7 +305,7 @@ out: return ret; } -void free_public_key(struct asymmetric_key *key) +void apc_free_pubkey(struct asymmetric_key *key) { if (!key) return; @@ -172,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; @@ -207,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 */