¿Cómo puedo duplicar una estructura EVP_PKEY sin conocer el algoritmo subyacente?

1

Estoy trabajando en una implementación TLS (usando OpenSSL 1.0.1s) que actualmente emplea claves RSA de 1024 bits para el cifrado y la autenticación. Quiero actualizar a EC por razones de rendimiento, pero necesito seguir siendo compatible con versiones anteriores.

Así que decidí usar la API de EVP de OpenSSL para tener tanto código común como sea posible. Pero, tengo un problema cuando quiero leer los certificados de mi RAM (almacenados en formato ASN.1 DER), no puedo encontrar una manera de copiar completamente una estructura EVP_PKEY (no PKEY_dup o PKEY_copy o algo por el estilo).

Quiero evitar cambiar la caja del EVP_PKEY.type para que la próxima actualización sea más sencilla, ¿alguna sugerencia?

    
pregunta Nimrod Morag 04.08.2016 - 17:27
fuente

1 respuesta

1

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

    
respondido por el Nimrod Morag 11.08.2016 - 15:30
fuente

Lea otras preguntas en las etiquetas