Come posso duplicare una struttura EVP_PKEY senza conoscere l'algoritmo sottostante?

1

Sto lavorando su un'implementazione TLS (utilizzando OpenSSL 1.0.1s) che attualmente utilizza chiavi RSA a 1024 bit sia per la crittografia che per l'autenticazione. Voglio aggiornare alla CE per motivi di prestazioni, ma ho bisogno di rimanere compatibile con le versioni precedenti.

Quindi ho deciso di utilizzare l'API EVP di OpenSSL per avere il maggior numero possibile di codice comune. Ma ho incontrato un problema quando voglio leggere i certificati dalla mia RAM (memorizzati nel formato ASN.1 DER), non riesco a trovare un modo per copiare completamente una struttura EVP_PKEY (nessuna PKEY_dup o PKEY_copy o qualcosa del genere).

Voglio evitare di cambiare il EVP_PKEY.type in modo che il prossimo aggiornamento risulti più agevole, qualche suggerimento?

    
posta Nimrod Morag 04.08.2016 - 17:27
fonte

1 risposta

1

Sono riuscito a duplicare convertendo in DER e viceversa. le funzioni generali di i2d / d2i chiamano quelle specifiche.

Codice:

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;

nota che le funzioni i2d / d2i incrementano i puntatori a cui sono dati

    
risposta data 11.08.2016 - 15:30
fonte

Leggi altre domande sui tag