X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=openssl.c;h=0ad9d7db4e7f035dce140365b2b38abc144b6923;hp=4895e176ba9cf7f86962d365f3d9514aed0f0180;hb=b3c68fd8519a426d6b6285dcb5a865670285e99a;hpb=ba83a291cd486e8ab53ac64d81b17d8f5705d715 diff --git a/openssl.c b/openssl.c index 4895e176..0ad9d7db 100644 --- a/openssl.c +++ b/openssl.c @@ -57,27 +57,15 @@ void crypt_init(void) void crypt_shutdown(void) { +#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA CRYPTO_cleanup_all_ex_data(); -} - -static int get_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; +#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(); } /* @@ -144,6 +132,152 @@ free_rsa: return ret; } +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; @@ -151,7 +285,7 @@ int apc_get_pubkey(const char *key_file, struct asymmetric_key **result) 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);