<div dir="ltr">Hey Matt,<div><br></div><div>I'm using openssl-1.0.2j to do this.<br><div><br></div><div>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..</div></div><div><br></div><div>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:</div><div><br></div><div><div>static int deriveSharedSecret( EVP_PKEY *pkey, EVP_PKEY *peerkey,</div><div>                               char *sharedSecretHex ){</div><div>   /*</div><div>    * Generalized function to derive shared secret and return the hex format of it.</div><div>    */</div><div>   unsigned char sharedSecret[ 4096 ] = {0};</div><div>   size_t sharedSecretLen = 0;</div><div><br></div><div>   // Now derive the Shared Secret</div><div>   EVP_PKEY_CTX *ctx;</div><div><br></div><div>   ctx = EVP_PKEY_CTX_new(pkey, NULL);</div><div>   if (!ctx){</div><div>      fprintf( stderr, "Failed to make EVP_PKEY ctx\n" );</div><div>      ERR_load_crypto_strings();</div><div>      ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));</div><div>      return 0;</div><div>   }</div><div>   if (EVP_PKEY_derive_init(ctx) <= 0){</div><div>      fprintf( stderr, "Failed to init EVP_PKEY ctx\n" );</div><div>      ERR_load_crypto_strings();</div><div>      ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));</div><div>      return 0;</div><div>   }</div><div>   if (EVP_PKEY_derive_set_peer(ctx, peerkey) <= 0) {</div><div>      fprintf( stderr, "Failed to set EVP_PKEY peer\n" );</div><div>      ERR_load_crypto_strings();</div><div>      ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));</div><div>      return 0;</div><div>   }</div><div><br></div><div>   int secretLen = 2048;</div><div>   unsigned char *skey;</div><div><br></div><div>   /* Create the buffer */</div><div>   if(NULL == (skey = OPENSSL_malloc(secretLen))){</div><div>      fprintf( stderr, "Failed to malloc buffer for secret\n" );</div><div>      return;</div><div>   }</div><div><br></div><div>   /* Derive the shared secret */</div><div>   if(1 != (EVP_PKEY_derive(ctx, skey, &secretLen))){</div><div>      fprintf( stderr, "Failed to derive secret and place into buffer\n" );</div><div>      return;</div><div>   } else {</div><div>      fprintf( stderr, "Found the darn secret!\n" );</div><div>   }</div><div>   if (EVP_PKEY_derive(ctx, sharedSecret, &sharedSecretLen) <= 0){</div><div>      fprintf( stderr, "Failed to derive shared secret\n" );</div><div>      ERR_load_crypto_strings();</div><div>      ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));</div><div>      return 0;</div></div><div>   } else {</div><div><div>      fprintf( stderr, "FOUND IT!!!!!\n" );</div><div>   }</div><div><br></div><div>   bin2hex( sharedSecret, sharedSecretHex, sharedSecretLen );</div><div>   return 1;</div><div>}</div></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 10, 2017 at 1:44 PM, Matt Caswell <span dir="ltr"><<a href="mailto:matt@openssl.org" target="_blank">matt@openssl.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br>
<br>
On 10/03/17 20:58, Ethan Rahn wrote:<br>
> Hello Openssl-users,<br>
><br>
> I'm trying to write some code that derives the shared secret for 2<br>
> elliptic curve keys ( i.e. does ECDH )<br>
><br>
> I am doing the following to load up both the local and remote EC key (<br>
> code shown for local side ):<br>
><br>
> EC_KEY* localEC = EC_KEY_new_by_curve_name( curveName );<br>
> EC_KEY_set_private_key( localEC, privateKeyLocal )<br>
> EC_KEY_set_public_key_affine_<wbr>coordinates( localEC, publicXCoordLocal,<br>
> publicYCoordLocal )<br>
><br>
> I check the return values for all of these, as well as EC_KEY_check_key<br>
> at the end. Everything returns non-zero, so I assume that it is good to<br>
> go. I then do the following to turn the EC_KEY into an EVP_PKEY for ECDH:<br>
><br>
> pkey = EVP_PKEY_new();<br>
> EVP_PKEY_set1_EC_KEY( *pkey, localEC );<br>
><br>
> The same is done for the remote EC, except that the private key is not<br>
> loaded up.<br>
><br>
> Now this is where things get weird.<br>
><br>
> I run code pretty similar to the example given here ( starting from<br>
> EVP_PKEY_CTX_new() since I already have the pkey and peerkey. (<br>
> <a href="https://wiki.openssl.org/index.php/Elliptic_Curve_Diffie_Hellman" rel="noreferrer" target="_blank">https://wiki.openssl.org/<wbr>index.php/Elliptic_Curve_<wbr>Diffie_Hellman</a> ) and<br>
> it fails on the call to EVP_PKEY_derive()without an error message. I<br>
> tried running into under gdb() and it gets to ecdh_check() before it's<br>
> unable to fill in the ecdh_data structure, i.e. it returns it as NULL.<br>
><br>
> If I use the example code to generate the local EVP_PKEY with a random<br>
> set of points on the correct curve, then run the following line, the key<br>
> derivation will work with the parameters I read in:<br>
> ( in this example, pkey is as in the example code, i.e. generated<br>
> randomly. pkey2 is the one I made via EVP_PKEY_set1_EC_KEY )<br>
><br>
> EVP_PKEY_set1_EC_KEY( pkey, EVP_PKEY_get1_EC_KEY( pkey2 ) );<br>
><br>
> It would appear that there is something that EVP_PKEY_set1_EC_KEY is not<br>
> setting, or perhaps that I need to add, but I'm unclear what that would<br>
> be. Does anyone on this list have any ideas?<br>
<br>
</div></div>Which version of OpenSSL are you using?<br>
<br>
Can you provide a simple reproducer of the problem?<br>
<span class="HOEnZb"><font color="#888888"><br>
Matt<br>
<br>
--<br>
openssl-users mailing list<br>
To unsubscribe: <a href="https://mta.openssl.org/mailman/listinfo/openssl-users" rel="noreferrer" target="_blank">https://mta.openssl.org/<wbr>mailman/listinfo/openssl-users</a><br>
</font></span></blockquote></div><br></div>