Search code examples
openssltls1.2public-key-exchange

OpenSSL public key from EVP_PKEY to buffer


I'm programming a client that partecipates in a TLS 1.2 handshake by sending messages through a TCP socket connected to Google's server. I'm using the ECDH key exchange method.

I generated the client keypair using this code, and now I want to send the ClientKeyExchange to the server containing the public key. In order to do that I first need to transfer the key containted in the EVP_PKEY into a buffer. I already did the opposite transformation for the server peerkey but I haven't figured out what to do now.

My code is:

void get_buffer(EVP_PKEY * pkey, unsigned char * client_pub_key, int pkeyLen) {

   EC_KEY *tempEcKey = NULL;

   tempEcKey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

   if(0 == (EVP_PKEY_set1_EC_KEY(pkey, tempEcKey))){
      handleErrors();
   }

   const EC_GROUP * group = EC_KEY_get0_group(tempEcKey);
   point_conversion_form_t form = EC_GROUP_get_point_conversion_form(group);

   //write in the buffer
   pkeyLen = EC_KEY_key2buf(tempEcKey, form, *client_pub_key, NULL);
   if(pkeyLen == 0){
      handleErrors();
   } 
}

The code causes a segmentation fault when calling EVP_PKEY_set1_EC_KEY(pkey, tempEcKey).

What am I doing wrong?

I also looked at the EVP_PKEY_get_raw_public_key() function but it doesn't work either. docs


Solution

  • You need to get the EC_KEY from the EVP_PKEY instead of EC_KEY_new_by_curve_name and EVP_PKEY_set1_EC_KEY use EVP_PKEY_get0_EC_KEY.

    EC_KEY_key2buf allocates a buffer for you and is not using a pre allocated buffer, this allocated buffer must be freed using OPENSSL_free.

    void get_buffer(EVP_PKEY * pkey, unsigned char ** client_pub_key, int *pkeyLen) {
        EC_KEY *tempEcKey = NULL;
    
        tempEcKey = EVP_PKEY_get0_EC_KEY(pkey);
        if(tempEcKey == NULL) {
            handleErrors("Getting EC_KEY from EVP_PKEY");
            return;
        }
    
        const EC_GROUP * group = EC_KEY_get0_group(tempEcKey);
        point_conversion_form_t form = EC_GROUP_get_point_conversion_form(group);
    
        *pkeyLen = EC_KEY_key2buf(tempEcKey, form, client_pub_key, NULL);
        if(*pkeyLen == 0){
           handleErrors("Creating buffer from key");
           return;
        } 
    }