2016-08-08 109 views
0

我正在使用當前採用1024位RSA密鑰進行加密和身份驗證的TLS實現(使用OpenSSL 1.0.1s)。出於性能原因,我想升級到EC,但我需要保持向後兼容。如何在不知道底層算法的情況下複製EVP_PKEY結構?

因此,我決定使用OpenSSL的EVP API來儘可能多地使用通用代碼。但是,當我想從我的RAM中讀取證書(存儲在ASN.1 DER格式中)時遇到了問題,我無法找到完全複製EVP_PKEY結構(無PKEY_dupPKEY_copy或任何分類)。

我想避開開關外殼EVP_PKEY.type所以下次升級會更流暢,有什麼建議嗎?

回答

0

根據您的問題,您可以嘗試使用EVP_PKEY_up_ref()(即增量爲EVP_PKEY引用計數器),然後將指針傳遞給原始的EVP_PKEY。這樣你就可以安全地使用EVP_PKEY_free()(它首先遞減計數器,只有當它變爲零時才真正釋放)。

+0

,因爲我需要一個完全不同的副本up_ref不解決我的問題 –

1

我設法通過轉換爲DER並將其複製。一般的i2d/d2i函數調用特定的函數。

代碼:

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; 

注意I2D/D2I功能增加給他們的三分球

相關問題