OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string

Matt Caswell matt at openssl.org
Wed Mar 10 09:12:27 UTC 2021



On 10/03/2021 00:53, Stephen Farrell wrote:
> 
> Hiya,
> 
> On 09/03/2021 03:09, Benjamin Kaduk wrote:
>> I would have expected that the API should hide the differences
>> other than the group name ... but these APIs are still pretty
>> new to me, too.  If you can point me at your code I might have
>> more to say.
> 
> So again it's probably my fault but I'm still not seeing the
> same behaviour for NIST and non-NIST curves. I made up what
> I hope is a fairly simple bit of test code [1] so that might
> help clarify where I'm wrong or (less likely) where a change
> in the library might be useful.
> 
> As I build the test code, the p256 cases seem to work, with
> or without the public key, but both 25519 cases fail. In my
> (still untidy:-) HPKE code EVP_PKEY_new_raw_private_key
> for the non-NIST curves works, but not for NIST curves. So I
> have an ok workaround, even if the fault's not mine, which
> it of course probably is:-)

Hi Stephen

There are two important things to understand that your code was not 
quite handling correctly:

1) X25519/X448/ED25519/ED448 are treated as different key types to 
"traditional" EC. They really are very different things: different OIDs, 
different standards, different file formats, different key formats etc. 
So while the "traditional" EC curves have the key type "EC", we have 
separate key types of "X25519", "X448", "ED25519" and "ED448"

2) The type of the parameters is dependent on the key type. So a private 
key in "EC" is an integer. But a private key for "X25519" is an octet 
string.

Refer to:

https://www.openssl.org/docs/manmaster/man7/EVP_PKEY-EC.html
https://www.openssl.org/docs/manmaster/man7/EVP_PKEY-X25519.html


I made these changes to your test code to get it to work:

$ diff -u test2evp.c test2evp2.c
--- test2evp.c	2021-03-10 08:47:59.467451154 +0000
+++ test2evp2.c	2021-03-10 09:03:47.258657721 +0000
@@ -29,6 +29,7 @@
  #include <openssl/core_names.h>

  int bufs2evp(
+        const char *keytype,
          char *groupname,
          unsigned char *privbuf, size_t privbuflen,
          unsigned char *pubuf, size_t pubuflen,
@@ -41,38 +42,38 @@
      OSSL_PARAM_BLD *param_bld=NULL;;
      OSSL_PARAM *params = NULL;

-    priv = BN_bin2bn(privbuf, privbuflen, NULL);
-    if (!priv) {
-        erv=__LINE__; goto err;
-    }
      param_bld = OSSL_PARAM_BLD_new();
      if (!param_bld) {
          erv=__LINE__; goto err;
      }
      if (pubuf && pubuflen>0) {
-        if (OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", 
groupname,0)!=1) {
-            erv=__LINE__; goto err;
-        }
-        if (OSSL_PARAM_BLD_push_BN(param_bld, "priv", priv)!=1) {
-            erv=__LINE__; goto err;
-        }
          if (OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", pubuf, 
pubuflen)!=1) {
              erv=__LINE__; goto err;
          }
          params = OSSL_PARAM_BLD_to_param(param_bld);
-    } else {
-        if (OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", 
groupname,0)!=1) {
+    }
+    if (groupname != NULL && OSSL_PARAM_BLD_push_utf8_string(param_bld, 
"group", groupname,0)!=1) {
+        erv=__LINE__; goto err;
+    }
+    if (strcmp(keytype, "EC") == 0) {
+        priv = BN_bin2bn(privbuf, privbuflen, NULL);
+        if (!priv) {
              erv=__LINE__; goto err;
-        }
+        }
          if (OSSL_PARAM_BLD_push_BN(param_bld, "priv", priv)!=1) {
              erv=__LINE__; goto err;
          }
-        params = OSSL_PARAM_BLD_to_param(param_bld);
+    } else {
+        if (OSSL_PARAM_BLD_push_octet_string(param_bld, "priv", 
privbuf, privbuflen)!=1) {
+            erv=__LINE__; goto err;
+        }
      }
+    params = OSSL_PARAM_BLD_to_param(param_bld);
+
      if (!params) {
          erv=__LINE__; goto err;
      }
-    ctx = EVP_PKEY_CTX_new_from_name(NULL,"EC", NULL);
+    ctx = EVP_PKEY_CTX_new_from_name(NULL,keytype, NULL);
      if (ctx == NULL) {
          erv=__LINE__; goto err;
      }
@@ -167,7 +168,7 @@
       * First do a p-256 one that works, then an x25519 one that does not.
       */

-    rv=bufs2evp("P-256",nprivbuf,nprivlen,npubbuf,npublen,&retkey);
+    rv=bufs2evp("EC","P-256",nprivbuf,nprivlen,npubbuf,npublen,&retkey);
      if (rv==1) {
          printf("P-256 with key pair worked\n");
      } else {
@@ -175,7 +176,7 @@
      }
      EVP_PKEY_free(retkey);retkey=NULL;

-    rv=bufs2evp("P-256",nprivbuf,nprivlen,NULL,0,&retkey);
+    rv=bufs2evp("EC","P-256",nprivbuf,nprivlen,NULL,0,&retkey);
      if (rv==1) {
          printf("P-256 with just private key worked\n");
      } else {
@@ -183,7 +184,7 @@
      }
      EVP_PKEY_free(retkey);retkey=NULL;

-    rv=bufs2evp("X25519",xprivbuf,xprivlen,xpubbuf,xpublen,&retkey);
+    rv=bufs2evp("X25519",NULL,xprivbuf,xprivlen,xpubbuf,xpublen,&retkey);
      if (rv==1) {
          printf("X25519 with key pair worked\n");
      } else {
@@ -191,7 +192,7 @@
      }
      EVP_PKEY_free(retkey);retkey=NULL;

-    rv=bufs2evp("X25519",xprivbuf,xprivlen,NULL,0,&retkey);
+    rv=bufs2evp("X25519",NULL,xprivbuf,xprivlen,NULL,0,&retkey);
      if (rv==1) {
          printf("X25519 with just private key worked\n");
      } else {


Matt


More information about the openssl-users mailing list