Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.

pratyush parimal
Hi all,

I was trying to use ECDH (in OpenSSL v1.0.1f) for a project, and after generating the EVP_PKEY structure, I needed to extract its public key and send it over to the other party. I was unable to find a straightforward way which worked for me.

What I tried was this:

EVP_PKEY*
extract_peerkey_3(EVP_PKEY* EVP_PKEY_both) //'both' meaning it contains public + private
{
int len = 0;

len = i2d_PUBKEY(EVP_PKEY_both, NULL); //find out required buffer length
unsigned char *buf, *p;
buf = (unsigned char*) malloc(len); //allocate
p = buf;
len = i2d_PUBKEY(EVP_PKEY_both, &p);

const unsigned char* p2 = buf;
EVP_PKEY* EVP_PKEY_public = d2i_PUBKEY(NULL, &p2, len);
if (EVP_PKEY_public == NULL)
{
handleCryptoError("d2i failed", ERR_get_error());
}

return EVP_PKEY_public;
}

The function doesn't throw an error, but when I pass the returned 'EVP_PKEY_public' structure to the function 'EVP_PKEY_derive_set_peer', I get an error message "error:10071065:elliptic curve routines:EC_POINT_cmp:incompatible objects".

When i reconstruct the EVP_PKEY using the steps EC_POINT_oct2point() -> EC_KEY_set_public_key() -> EVP_PKEY_set1_EC_KEY(), the resulting EVP_PKEY does work for me. In fact I'm able to derive the same secret on both sides using this sequence, but I feel it's too roundabout.

I also saw the following: http://marc.info/?l=openssl-users&m=116474297608094&w=2, which talks about using 'i2d_PUBKEY', but I haven't been able to make it work so far.

Is my usage of d2i_PUBKEY or i2d_PUBKEY wrong in some way? Does anyone know how to use them properly?
Any help will be appreciated.

Thanks!
Pratyush Parimal
Reply | Threaded
Open this post in threaded view
|

Fwd: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.

pratyush parimal
Hi all,

Did anyone have any luck with this one?

Thanks,
Pratyush Parimal.

---------- Forwarded message ----------
From: pratyush parimal <[hidden email]>
Date: Wed, Jun 25, 2014 at 10:43 AM
Subject: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.
To: [hidden email]


Hi all,

I was trying to use ECDH (in OpenSSL v1.0.1f) for a project, and after generating the EVP_PKEY structure, I needed to extract its public key and send it over to the other party. I was unable to find a straightforward way which worked for me.

What I tried was this:

EVP_PKEY*
extract_peerkey_3(EVP_PKEY* EVP_PKEY_both) //'both' meaning it contains public + private
{
int len = 0;

len = i2d_PUBKEY(EVP_PKEY_both, NULL); //find out required buffer length
unsigned char *buf, *p;
buf = (unsigned char*) malloc(len); //allocate
p = buf;
len = i2d_PUBKEY(EVP_PKEY_both, &p);

const unsigned char* p2 = buf;
EVP_PKEY* EVP_PKEY_public = d2i_PUBKEY(NULL, &p2, len);
if (EVP_PKEY_public == NULL)
{
handleCryptoError("d2i failed", ERR_get_error());
}

return EVP_PKEY_public;
}

The function doesn't throw an error, but when I pass the returned 'EVP_PKEY_public' structure to the function 'EVP_PKEY_derive_set_peer', I get an error message "error:10071065:elliptic curve routines:EC_POINT_cmp:incompatible objects".

When i reconstruct the EVP_PKEY using the steps EC_POINT_oct2point() -> EC_KEY_set_public_key() -> EVP_PKEY_set1_EC_KEY(), the resulting EVP_PKEY does work for me. In fact I'm able to derive the same secret on both sides using this sequence, but I feel it's too roundabout.

I also saw the following: http://marc.info/?l=openssl-users&m=116474297608094&w=2, which talks about using 'i2d_PUBKEY', but I haven't been able to make it work so far.

Is my usage of d2i_PUBKEY or i2d_PUBKEY wrong in some way? Does anyone know how to use them properly?
Any help will be appreciated.

Thanks!
Pratyush Parimal

Reply | Threaded
Open this post in threaded view
|

Re: Fwd: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.

Bala
We do the below for this operation:

1>How we convert public part of  'EVP_PKEY' structure to 'unsigned char*

//Extract a public key from a PKEY struct.

ec_copy_public(EVP_PKEY *pKey, uint8_t *keybuf)

   EC_KEY            *pEcKey;
   uint8_t           encoded_key[MAX_KEYLEN_X962];
   uint8_t           *pMem;
   int               keylen = 0;

      /* Get the EC_KEY struct pointer. */
      pEcKey = (EC_KEY *)EVP_PKEY_get0(pKey);

      /* Extract the private key from the EC key struct. */
      if (pEcKey) {
         pMem = encoded_key;
         keylen = i2o_ECPublicKey(pEcKey, &pMem);

         /* Copy the decoded public key into the provided buffer. */
         if (keylen) {
            keylen = ipsec_ec_x962_decode(pEcKey, encoded_key, keylen, keybuf);           //fn defined in the end
         }
      }
   }

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2>How we get the peerkey to pass to EVP_PKEY_derive_set_peer(pctx, peerkey);


//The below function takes a character string as input and converts it to a public key.

Prototype:
 
EVP_PKEY *ec_create_static_public(uint8_t *public_key, int keylen, int curve)

 EC_KEY            *pEcKey = NULL;
   EC_KEY            *pEcKeyTemp;
   uint8_t           encoded_key[MAX_KEYLEN_X962];
   const uint8_t     *pMem;
   EC_POINT          *pEcPoint = NULL;
   BIGNUM            *pBignum = NULL;
   EVP_PKEY          *pKey = NULL;


   switch(curve) {
      case NID_secp384r1:
         pEcKey = EC_KEY_new_by_curve_name(curve);
         break;
      default:
         pEcKey = NULL;
   }

/* Encode the public key string into X9.62 format. */ defined later

ec_x962_encode(pEcKey, public_key, keylen, encoded_key);

      pMem = encoded_key;
      pEcKeyTemp = pEcKey;

      /* Place the encoded public key in the EC_KEY struct. */
      pEcKeyTemp = o2i_ECPublicKey(&pEcKeyTemp, &pMem, keylen);

      /* Allocate an EVP_PKEY struct for the EC_KEY. */
      pKey = EVP_PKEY_new();

      /* Assign the public key to the EVP_PKEY wrapper. */
      EVP_PKEY_assign_EC_KEY(pKey, pEcKey);

     pEcKey = NULL;

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


int
ec_x962_encode(EC_KEY *pEcKey, uint8_t *key, int keylen, uint8_t *conv)
{
   point_conversion_form_t form;

   /* Get the conversion format. */
   form = EC_KEY_get_conv_form(pEcKey);

   /* Make sure the format is supported. If so, the first byte of the encoded
      data will be the format identifier. */
   switch (form) {
      case POINT_CONVERSION_UNCOMPRESSED:
         conv[0] = POINT_CONVERSION_UNCOMPRESSED;
         conv++;
         break;
      case POINT_CONVERSION_COMPRESSED:
      case POINT_CONVERSION_HYBRID:
      default:
         keylen = 0;
         break;
   }

   /* If the format is valid, copy the key into the destination buffer. */
   if (keylen) {
      memcpy(conv, key, keylen);
      keylen++;
   }

   return(keylen);
}


Thanks,
Bala

--------------------------------------------
On Sun, 6/29/14, pratyush parimal <[hidden email]> wrote:

 Subject: Fwd: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.
 To: [hidden email]
 Date: Sunday, June 29, 2014, 11:43 PM
 
 Hi all,
 Did anyone have any luck with this
 one?
 Thanks,Pratyush Parimal.
 
 ---------- Forwarded
 message ----------
 From: pratyush
 parimal <[hidden email]>
 
 Date: Wed, Jun 25, 2014 at 10:43 AM
 Subject: Converting public part of 'EVP_PKEY'
 structure to 'unsigned char*' , and back.
 To: [hidden email]
 
 
 
 Hi all,
 I was trying to use ECDH (in OpenSSL v1.0.1f) for
 a project, and after generating the EVP_PKEY structure, I
 needed to extract its public key and send it over to the
 other party. I was unable to find a straightforward way
 which worked for me.
 
 
 What I tried was this:
 
 EVP_PKEY*extract_peerkey_3(EVP_PKEY*
 EVP_PKEY_both) //'both' meaning it contains public +
 private{ int len =
 0;
 
  len =
 i2d_PUBKEY(EVP_PKEY_both, NULL); //find out required buffer
 length unsigned char *buf,
 *p;
  buf = (unsigned
 char*) malloc(len); //allocate p =
 buf; len =
 i2d_PUBKEY(EVP_PKEY_both, &p);
 
 
  const
 unsigned char* p2 = buf; EVP_PKEY*
 EVP_PKEY_public = d2i_PUBKEY(NULL, &p2, len);
  if
 (EVP_PKEY_public == NULL) { handleCryptoError("d2i
 failed", ERR_get_error());
 
  }
  return
 EVP_PKEY_public;}
 The function doesn't throw an error, but when
 I pass the returned 'EVP_PKEY_public' structure to
 the function 'EVP_PKEY_derive_set_peer', I get an
 error message "error:10071065:elliptic curve
 routines:EC_POINT_cmp:incompatible objects".
 
 
 I also tried to follow the steps given at http://stackoverflow.com/questions/18155559/how-does-one-access-the-raw-ecdh-public-key-private-key-and-params-inside-opens.
 
 When i reconstruct the EVP_PKEY using the steps EC_POINT_oct2point()
 -> EC_KEY_set_public_key()
 -> EVP_PKEY_set1_EC_KEY(),
 the resulting EVP_PKEY does work for me. In fact I'm
 able to derive the same secret on both sides using this
 sequence, but I feel it's too roundabout.
 
 
 I
 also saw the following: http://marc.info/?l=openssl-users&m=116474297608094&w=2,
 which talks about using 'i2d_PUBKEY',
 but I haven't been able to make it work so
 far.
 
 
 Is my usage of d2i_PUBKEY or i2d_PUBKEY wrong in
 some way? Does anyone know how to use them
 properly?Any help will be
 appreciated.
 Thanks!
 Pratyush Parimal
 
 
 

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.

Thulasi Goriparthi
In reply to this post by pratyush parimal
Guessing the context that is sent to EVP_PKEY_derive_set_peer is initialized/created with a pkey belonging to different group.

In other words, EC keys of both parties in DH are not of the same group.


On Mon, Jun 30, 2014 at 10:13 AM, pratyush parimal <[hidden email]> wrote:
Hi all,

Did anyone have any luck with this one?

Thanks,
Pratyush Parimal.


---------- Forwarded message ----------
From: pratyush parimal <[hidden email]>
Date: Wed, Jun 25, 2014 at 10:43 AM
Subject: Converting public part of 'EVP_PKEY' structure to 'unsigned char*' , and back.
To: [hidden email]


Hi all,

I was trying to use ECDH (in OpenSSL v1.0.1f) for a project, and after generating the EVP_PKEY structure, I needed to extract its public key and send it over to the other party. I was unable to find a straightforward way which worked for me.

What I tried was this:

EVP_PKEY*
extract_peerkey_3(EVP_PKEY* EVP_PKEY_both) //'both' meaning it contains public + private
{
int len = 0;

len = i2d_PUBKEY(EVP_PKEY_both, NULL); //find out required buffer length
unsigned char *buf, *p;
buf = (unsigned char*) malloc(len); //allocate
p = buf;
len = i2d_PUBKEY(EVP_PKEY_both, &p);

const unsigned char* p2 = buf;
EVP_PKEY* EVP_PKEY_public = d2i_PUBKEY(NULL, &p2, len);
if (EVP_PKEY_public == NULL)
{
handleCryptoError("d2i failed", ERR_get_error());
}

return EVP_PKEY_public;
}

The function doesn't throw an error, but when I pass the returned 'EVP_PKEY_public' structure to the function 'EVP_PKEY_derive_set_peer', I get an error message "error:10071065:elliptic curve routines:EC_POINT_cmp:incompatible objects".

When i reconstruct the EVP_PKEY using the steps EC_POINT_oct2point() -> EC_KEY_set_public_key() -> EVP_PKEY_set1_EC_KEY(), the resulting EVP_PKEY does work for me. In fact I'm able to derive the same secret on both sides using this sequence, but I feel it's too roundabout.

I also saw the following: http://marc.info/?l=openssl-users&m=116474297608094&w=2, which talks about using 'i2d_PUBKEY', but I haven't been able to make it work so far.

Is my usage of d2i_PUBKEY or i2d_PUBKEY wrong in some way? Does anyone know how to use them properly?
Any help will be appreciated.

Thanks!
Pratyush Parimal