EVP_PKEY_set1_EC_KEY seems to not set something that EVP_PKEY_derive needs

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

EVP_PKEY_set1_EC_KEY seems to not set something that EVP_PKEY_derive needs

Ethan Rahn
Hello Openssl-users,

I'm trying to write some code that derives the shared secret for 2 elliptic curve keys ( i.e. does ECDH )

I am doing the following to load up both the local and remote EC key ( code shown for local side ):

EC_KEY* localEC = EC_KEY_new_by_curve_name( curveName );
EC_KEY_set_private_key( localEC, privateKeyLocal )
EC_KEY_set_public_key_affine_coordinates( localEC, publicXCoordLocal, publicYCoordLocal ) 

I check the return values for all of these, as well as EC_KEY_check_key at the end. Everything returns non-zero, so I assume that it is good to go. I then do the following to turn the EC_KEY into an EVP_PKEY for ECDH:

pkey = EVP_PKEY_new();
EVP_PKEY_set1_EC_KEY( *pkey, localEC );

The same is done for the remote EC, except that the private key is not loaded up.

Now this is where things get weird.

I run code pretty similar to the example given here ( starting from EVP_PKEY_CTX_new() since I already have the pkey and peerkey. ( https://wiki.openssl.org/index.php/Elliptic_Curve_Diffie_Hellman ) and it fails on the call to EVP_PKEY_derive()without an error message. I tried running into under gdb() and it gets to ecdh_check() before it's unable to fill in the ecdh_data structure, i.e. it returns it as NULL.

If I use the example code to generate the local EVP_PKEY with a random set of points on the correct curve, then run the following line, the key derivation will work with the parameters I read in:
( in this example, pkey is as in the example code, i.e. generated randomly. pkey2 is the one I made via EVP_PKEY_set1_EC_KEY )

EVP_PKEY_set1_EC_KEY( pkey, EVP_PKEY_get1_EC_KEY( pkey2 ) );

It would appear that there is something that EVP_PKEY_set1_EC_KEY is not setting, or perhaps that I need to add, but I'm unclear what that would be. Does anyone on this list have any ideas?

Much thanks,

Ethan

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: EVP_PKEY_set1_EC_KEY seems to not set something that EVP_PKEY_derive needs

Matt Caswell-2


On 10/03/17 20:58, Ethan Rahn wrote:

> Hello Openssl-users,
>
> I'm trying to write some code that derives the shared secret for 2
> elliptic curve keys ( i.e. does ECDH )
>
> I am doing the following to load up both the local and remote EC key (
> code shown for local side ):
>
> EC_KEY* localEC = EC_KEY_new_by_curve_name( curveName );
> EC_KEY_set_private_key( localEC, privateKeyLocal )
> EC_KEY_set_public_key_affine_coordinates( localEC, publicXCoordLocal,
> publicYCoordLocal )
>
> I check the return values for all of these, as well as EC_KEY_check_key
> at the end. Everything returns non-zero, so I assume that it is good to
> go. I then do the following to turn the EC_KEY into an EVP_PKEY for ECDH:
>
> pkey = EVP_PKEY_new();
> EVP_PKEY_set1_EC_KEY( *pkey, localEC );
>
> The same is done for the remote EC, except that the private key is not
> loaded up.
>
> Now this is where things get weird.
>
> I run code pretty similar to the example given here ( starting from
> EVP_PKEY_CTX_new() since I already have the pkey and peerkey. (
> https://wiki.openssl.org/index.php/Elliptic_Curve_Diffie_Hellman ) and
> it fails on the call to EVP_PKEY_derive()without an error message. I
> tried running into under gdb() and it gets to ecdh_check() before it's
> unable to fill in the ecdh_data structure, i.e. it returns it as NULL.
>
> If I use the example code to generate the local EVP_PKEY with a random
> set of points on the correct curve, then run the following line, the key
> derivation will work with the parameters I read in:
> ( in this example, pkey is as in the example code, i.e. generated
> randomly. pkey2 is the one I made via EVP_PKEY_set1_EC_KEY )
>
> EVP_PKEY_set1_EC_KEY( pkey, EVP_PKEY_get1_EC_KEY( pkey2 ) );
>
> It would appear that there is something that EVP_PKEY_set1_EC_KEY is not
> setting, or perhaps that I need to add, but I'm unclear what that would
> be. Does anyone on this list have any ideas?

Which version of OpenSSL are you using?

Can you provide a simple reproducer of the problem?

Matt

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: EVP_PKEY_set1_EC_KEY seems to not set something that EVP_PKEY_derive needs

Ethan Rahn
Hey Matt,

I'm using openssl-1.0.2j to do this.

After a lot of debugging and poking around, I realized that my initial thoughts were not quite correct. Somewhere in trying to come up with an example, I noticed that the problem actually appears to be the buffer I am passing in..

If I use a char array, it will fail to derive the shared secret, if I use a char* it will succeed. I'm not quite sure what is going on there, but I have some code below that shows the issue:

static int deriveSharedSecret( EVP_PKEY *pkey, EVP_PKEY *peerkey,
                               char *sharedSecretHex ){
   /*
    * Generalized function to derive shared secret and return the hex format of it.
    */
   unsigned char sharedSecret[ 4096 ] = {0};
   size_t sharedSecretLen = 0;

   // Now derive the Shared Secret
   EVP_PKEY_CTX *ctx;

   ctx = EVP_PKEY_CTX_new(pkey, NULL);
   if (!ctx){
      fprintf( stderr, "Failed to make EVP_PKEY ctx\n" );
      ERR_load_crypto_strings();
      ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
      return 0;
   }
   if (EVP_PKEY_derive_init(ctx) <= 0){
      fprintf( stderr, "Failed to init EVP_PKEY ctx\n" );
      ERR_load_crypto_strings();
      ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
      return 0;
   }
   if (EVP_PKEY_derive_set_peer(ctx, peerkey) <= 0) {
      fprintf( stderr, "Failed to set EVP_PKEY peer\n" );
      ERR_load_crypto_strings();
      ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
      return 0;
   }

   int secretLen = 2048;
   unsigned char *skey;

   /* Create the buffer */
   if(NULL == (skey = OPENSSL_malloc(secretLen))){
      fprintf( stderr, "Failed to malloc buffer for secret\n" );
      return;
   }

   /* Derive the shared secret */
   if(1 != (EVP_PKEY_derive(ctx, skey, &secretLen))){
      fprintf( stderr, "Failed to derive secret and place into buffer\n" );
      return;
   } else {
      fprintf( stderr, "Found the darn secret!\n" );
   }
   if (EVP_PKEY_derive(ctx, sharedSecret, &sharedSecretLen) <= 0){
      fprintf( stderr, "Failed to derive shared secret\n" );
      ERR_load_crypto_strings();
      ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
      return 0;
   } else {
      fprintf( stderr, "FOUND IT!!!!!\n" );
   }

   bin2hex( sharedSecret, sharedSecretHex, sharedSecretLen );
   return 1;
}



On Fri, Mar 10, 2017 at 1:44 PM, Matt Caswell <[hidden email]> wrote:


On 10/03/17 20:58, Ethan Rahn wrote:
> Hello Openssl-users,
>
> I'm trying to write some code that derives the shared secret for 2
> elliptic curve keys ( i.e. does ECDH )
>
> I am doing the following to load up both the local and remote EC key (
> code shown for local side ):
>
> EC_KEY* localEC = EC_KEY_new_by_curve_name( curveName );
> EC_KEY_set_private_key( localEC, privateKeyLocal )
> EC_KEY_set_public_key_affine_coordinates( localEC, publicXCoordLocal,
> publicYCoordLocal )
>
> I check the return values for all of these, as well as EC_KEY_check_key
> at the end. Everything returns non-zero, so I assume that it is good to
> go. I then do the following to turn the EC_KEY into an EVP_PKEY for ECDH:
>
> pkey = EVP_PKEY_new();
> EVP_PKEY_set1_EC_KEY( *pkey, localEC );
>
> The same is done for the remote EC, except that the private key is not
> loaded up.
>
> Now this is where things get weird.
>
> I run code pretty similar to the example given here ( starting from
> EVP_PKEY_CTX_new() since I already have the pkey and peerkey. (
> https://wiki.openssl.org/index.php/Elliptic_Curve_Diffie_Hellman ) and
> it fails on the call to EVP_PKEY_derive()without an error message. I
> tried running into under gdb() and it gets to ecdh_check() before it's
> unable to fill in the ecdh_data structure, i.e. it returns it as NULL.
>
> If I use the example code to generate the local EVP_PKEY with a random
> set of points on the correct curve, then run the following line, the key
> derivation will work with the parameters I read in:
> ( in this example, pkey is as in the example code, i.e. generated
> randomly. pkey2 is the one I made via EVP_PKEY_set1_EC_KEY )
>
> EVP_PKEY_set1_EC_KEY( pkey, EVP_PKEY_get1_EC_KEY( pkey2 ) );
>
> It would appear that there is something that EVP_PKEY_set1_EC_KEY is not
> setting, or perhaps that I need to add, but I'm unclear what that would
> be. Does anyone on this list have any ideas?

Which version of OpenSSL are you using?

Can you provide a simple reproducer of the problem?

Matt

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users


--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: EVP_PKEY_set1_EC_KEY seems to not set something that EVP_PKEY_derive needs

Matt Caswell-2


On 11/03/17 18:38, Ethan Rahn wrote:
>    size_t sharedSecretLen = 0;

Set this to sizeof(sharedSecret).

>
>    // Now derive the Shared Secret
>    EVP_PKEY_CTX *ctx;
>
>    ctx = EVP_PKEY_CTX_new(pkey, NULL);
>    if (!ctx){
>       fprintf( stderr, "Failed to make EVP_PKEY ctx\n" );
>       ERR_load_crypto_strings();

This should be called once at the start of your program - *before* any
calls that might generate an error.

>    if (EVP_PKEY_derive(ctx, sharedSecret, &sharedSecretLen) <= 0){

From the EVP_PKEY_derive documentation:

https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive.html

"If key is not NULL then before the call the keylen parameter should
contain the length of the key buffer, if the call is successful the
shared secret is written to key and the amount of data written to keylen."

Matt

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: EVP_PKEY_set1_EC_KEY seems to not set something that EVP_PKEY_derive needs

Ethan Rahn
Wow,

That was quite the oversight of mine. That fixed the issue. Thanks so much, I appreciate your patience in dealing with my confusion over the APIs!

Cheers,

Ethan

On Sat, Mar 11, 2017 at 12:28 PM, Matt Caswell <[hidden email]> wrote:


On 11/03/17 18:38, Ethan Rahn wrote:
>    size_t sharedSecretLen = 0;

Set this to sizeof(sharedSecret).

>
>    // Now derive the Shared Secret
>    EVP_PKEY_CTX *ctx;
>
>    ctx = EVP_PKEY_CTX_new(pkey, NULL);
>    if (!ctx){
>       fprintf( stderr, "Failed to make EVP_PKEY ctx\n" );
>       ERR_load_crypto_strings();

This should be called once at the start of your program - *before* any
calls that might generate an error.

>    if (EVP_PKEY_derive(ctx, sharedSecret, &sharedSecretLen) <= 0){

From the EVP_PKEY_derive documentation:

https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_derive.html

"If key is not NULL then before the call the keylen parameter should
contain the length of the key buffer, if the call is successful the
shared secret is written to key and the amount of data written to keylen."

Matt

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users


--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users