Logré duplicar convirtiéndolo a DER y viceversa. Las funciones generales de i2d / d2i llaman a las específicas.
Código:
error_code_ENUM read_evp_pkey_from_ram (int index,
int DB_ID,
EVP_PKEY **pkey_ptr_PTR){
EVP_PKEY *pkey;
unsigned char *p;
unsigned char *DER_PTR;
int DER_size;
int pub_len, priv_len, type;
*pkey_ptr_PTR = NULL;
if ((pkey = sensitive_EVP_PKEY_data[DB_ID][index]) == NULL)
return error_code_no_key;
type = pkey->type;
/*passing NULL to char *out returns the length only*/
pub_len = i2d_PUBKEY(pkey, NULL);
priv_len = i2d_PrivateKey(pkey, NULL);
if (pub_len <= 0 || priv_len <= 0 )
return error_code_general_error;
DER_size = pub_len + priv_len + 2 * sizeof(UINT_16);
if ((DER_PTR = OPENSSL_malloc(DER_size)) == NULL)
return error_code_no_memory;
/*
* store the key in buffer as:
* |public key length | public key | private key length | private key|
*/
p = DER_PTR;
*(UINT_16*)p = pub_len;
p += 2;
pub_len = i2d_PUBKEY(pkey,&p);/*p is incremented here by the key size*/
*(UINT_16*)p = priv_len;
p += 2;
priv_len = i2d_PrivateKey(pkey,&p);
p = DER_PTR + 2;
/*pass NULL to EVP_PKEY *key causes a fresh EVP_PKEY struct to be allocated and a pointer to it returned*/
pkey = d2i_PUBKEY(NULL, (const unsigned char **)&p, pub_len);
if (pkey == NULL){
OPENSSL_free(DER_PTR);
return error_code_general_error;
}
priv_len = *(UINT_16 *)p;
if (priv_len == 0){
EVP_PKEY_free(pkey);
OPENSSL_free(DER_PTR);
return error_code_general_error;
}
p += 2;
/*now pass &pkey*/
if (d2i_PrivateKey(type, &pkey, (const unsigned char **)&p, priv_len) == NULL){
OPENSSL_free(DER_PTR);
return error_code_general_error;
}
OPENSSL_free(DER_PTR);
*pkey_ptr_PTR = pkey;
return error_code_no_error;
tenga en cuenta que las funciones i2d / d2i incrementan los punteros que se les dan