Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we copy an EVP_PKEY which includes RSA key?

I found the function EVP_PKEY_copy_parameters, which can copy EVP_PKEY. But some documentations about this function says it can only be used for DSA/ECC algorithms. The official documentation (from openssl.org) does not mention whether the function can be used for RSA EVP_PKEYs.

Another implementation for EVP_PKEY (that contains an RSA key) could be this:

EVP_PKEY_assign_RSA(RSAPrivateKey_dup(EVP_PKEY_get1_RSA(pkey)));

Do you have any suggestions?

like image 945
uping Avatar asked Jun 23 '11 04:06

uping


2 Answers

If you don't really need to duplicate the key, you can just increment its reference count, like this:

CRYPTO_add(&your_evp_pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);

Otherwise, a similar (almost identical) approach to what you suggested would be the following:

int pkey_rsa_dup(EVP_PKEY *dst_pkey, EVP_PKEY *src_key) {
    // Validate underlying key type - Only allow a RSA key
    if (src_key->type != EVP_PKEY_RSA)
        return -1;

    RSA *rsa = EVP_PKEY_get1_RSA(src_key); // Get the underlying RSA key
    RSA *dup_rsa = RSAPrivateKey_dup(rsa); // Duplicate the RSA key
    RSA_free(rsa); // Decrement reference count

    EVP_PKEY_set1_RSA(dst_pkey, dup_rsa); // Set the underlying RSA key in dst_pkey
    // EVP_PKEY_set1_RSA also adjusts the other members in dst_pkey

    return 0;
}

Reference: Re: How to duplicate an EVP_PKEY -> As @X-Istence says below, the RSA_dup method suggested in this reference thread doesn't exist in OpenSSL (at least until the date of this update).

like image 83
jweyrich Avatar answered Sep 19 '22 23:09

jweyrich


In OpenSSL 1.0.0d, EVP_PKEY_copy_parameters should work. However, judging from the implementation, it just seems to copy the public parameters:

static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
    RSA_PKEY_CTX *dctx, *sctx;
    if (!pkey_rsa_init(dst))
        return 0;
    sctx = src->data;
    dctx = dst->data;
    dctx->nbits = sctx->nbits;
    if (sctx->pub_exp) {
        dctx->pub_exp = BN_dup(sctx->pub_exp);
        if (!dctx->pub_exp)
            return 0;
    }
    dctx->pad_mode = sctx->pad_mode;
    dctx->md = sctx->md;
    return 1;
}

Apart from jweyrich's solution, another simple method is to first i2d_RSAPrivateKey your RSA key then d2i_RSAPrivateKey it again - there's your copy :)

like image 20
emboss Avatar answered Sep 19 '22 23:09

emboss