Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
On 10/03/2021 12:08, Stephen Farrell wrote: It seems a pity that one has to special case in two ways there (both keytype and groupname) but I can live with it, For X25519 you can actually pass a groupname of "x25519" through if you want to keep everything consistent. But it's not strictly necessary since that is the only group supported by that keytype. Matt
Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
Thanks Matt, On 10/03/2021 09:12, Matt Caswell wrote: 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. I had tried all those, but not in the right combination, so thanks! My test code works now with your changes. (It's still at [1] and feel free to use as an example if that's useful.) It seems a pity that one has to special case in two ways there (both keytype and groupname) but I can live with it, Thanks again, S. [1] https://github.com/sftcd/happykey/blob/master/test2evp.c 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 + +++ test2evp2.c 2021-03-10 09:03:47.258657721 + @@ -29,6 +29,7 @@ #include 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,); + rv=bufs2evp("EC","P-256",nprivbuf,nprivlen,npubbuf,npublen,); 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,); + rv=bufs2evp("EC","P-256",nprivbuf,nprivlen,NULL,0,); if (rv==1) { printf("P-256 with just private key worked\n"); } else { @@ -183,7 +184,7 @@ }
Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
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 + +++ test2evp2.c 2021-03-10 09:03:47.258657721 + @@ -29,6 +29,7 @@ #include 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,); +rv=bufs2evp("EC","P-256",nprivbuf,nprivlen,npubbuf,npublen,); 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,); +rv=bufs2evp("EC","P-256",nprivbuf,nprivlen,NULL,0,); 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,); +rv=bufs2evp("X25519",NULL,xprivbuf,xprivlen,xpubbuf,xpublen,); 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,); +rv=bufs2evp("X25519",NULL,xprivbuf,xprivlen,NULL,0,); if (rv==1) { printf("X25519 with just private key worked\n");
Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
On Wed, 2021-03-10 at 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:-) Not sure if there are any other issues, but the public key parameter should be "encoded-pub-key" AFAIK. Tomas Mraz
Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
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:-) Cheers, S. [1] https://github.com/sftcd/happykey/blob/master/test2evp.c OpenPGP_0x5AB2FAF17B172BEA.asc Description: application/pgp-keys OpenPGP_signature Description: OpenPGP digital signature
Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
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. Will check it out some more, tidy the code up and get back later/tomorrow, Cheers, S. OpenPGP_0x5AB2FAF17B172BEA.asc Description: application/pgp-keys OpenPGP_signature Description: OpenPGP digital signature
Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
On Tue, Mar 09, 2021 at 02:44:20AM +, Stephen Farrell wrote: > > Hiya, > > On 08/03/2021 02:37, Benjamin Kaduk wrote: > > Hi Stephen :) > > > > The API you'll want to use is EVP_PKEY_fromdata(); there's > > a stubbed out example of using it to make an EVP_PKEY with > > EC group parameters at > > https://github.com/openssl/openssl/issues/14258#issuecomment-783351031 > > but the translation to also specify OSSL_PKEY_PARAM_PRIV_KEY > > (and possibly OSSL_PKEY_PARAM_PUB_KEY; I forget if you need > > to pass both) should be fairly straightforward. > > Thanks for that! I worked around a few things and still need > to tidy-up but got things working that way without any more > deprecation warnings. > > > > > Let us know if you run into trouble with that route. > > One outstanding issue is that I still need different code > paths for NIST curves vs. 25519 & 448 - is that just me > (quite likely:-) or should these new APIs hide differences > between those different curves? 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. -Ben
Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
Hiya, On 08/03/2021 02:37, Benjamin Kaduk wrote: Hi Stephen :) The API you'll want to use is EVP_PKEY_fromdata(); there's a stubbed out example of using it to make an EVP_PKEY with EC group parameters at https://github.com/openssl/openssl/issues/14258#issuecomment-783351031 but the translation to also specify OSSL_PKEY_PARAM_PRIV_KEY (and possibly OSSL_PKEY_PARAM_PUB_KEY; I forget if you need to pass both) should be fairly straightforward. Thanks for that! I worked around a few things and still need to tidy-up but got things working that way without any more deprecation warnings. Let us know if you run into trouble with that route. One outstanding issue is that I still need different code paths for NIST curves vs. 25519 & 448 - is that just me (quite likely:-) or should these new APIs hide differences between those different curves? Thanks again, S. -Ben On Mon, Mar 08, 2021 at 02:23:36AM +, Stephen Farrell wrote: Hiya, My question: how does one setup an EVP_PKEY for a NIST curve (e.g. p256) key pair when one has the private key in an octet string using the latest OpenSSL 3.0.0 high level APIs? I'm trying to get rid of deprecation warnings from my code for HPKE [1] when dealing with NIST curves using the new (I guess?) OSSL_PARAM_* approach. I'm failing at the moment;-) So, given an octet string from a set of test vectors (e.g. [2]) what's the proper way to setup an EVP_PKEY for that to allow one to validate the test vectors? Happy to try produce a stand-alone example for this in the next few days if one doesn't exist (I've not found one so far). Thanks, Stephen. [1] https://github.com/sftcd/happykey/blob/7d52d34c516ab58ca1433004ff82b2a6a82eea4c/hpke.c#L1263 [2] https://github.com/cfrg/draft-irtf-cfrg-hpke pub RSA 4096/7B172BEA 2017-12-22 Stephen Farrell (2017) sub RSA 4096/36CB8BB6 2017-12-22 OpenPGP_0x5AB2FAF17B172BEA.asc Description: application/pgp-keys OpenPGP_signature Description: OpenPGP digital signature
Re: OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
Hi Stephen :) The API you'll want to use is EVP_PKEY_fromdata(); there's a stubbed out example of using it to make an EVP_PKEY with EC group parameters at https://github.com/openssl/openssl/issues/14258#issuecomment-783351031 but the translation to also specify OSSL_PKEY_PARAM_PRIV_KEY (and possibly OSSL_PKEY_PARAM_PUB_KEY; I forget if you need to pass both) should be fairly straightforward. Let us know if you run into trouble with that route. -Ben On Mon, Mar 08, 2021 at 02:23:36AM +, Stephen Farrell wrote: > > Hiya, > > My question: how does one setup an EVP_PKEY for a NIST > curve (e.g. p256) key pair when one has the private key > in an octet string using the latest OpenSSL 3.0.0 high > level APIs? > > I'm trying to get rid of deprecation warnings from my > code for HPKE [1] when dealing with NIST curves using > the new (I guess?) OSSL_PARAM_* approach. I'm failing > at the moment;-) > > So, given an octet string from a set of test vectors > (e.g. [2]) what's the proper way to setup an EVP_PKEY > for that to allow one to validate the test vectors? > > Happy to try produce a stand-alone example for this > in the next few days if one doesn't exist (I've not > found one so far). > > Thanks, > Stephen. > > [1] > https://github.com/sftcd/happykey/blob/7d52d34c516ab58ca1433004ff82b2a6a82eea4c/hpke.c#L1263 > [2] https://github.com/cfrg/draft-irtf-cfrg-hpke pub RSA 4096/7B172BEA 2017-12-22 Stephen Farrell (2017) > sub RSA 4096/36CB8BB6 2017-12-22 >
OpenSSL 3.0.0 APIs for creating an EVP_PKEY from a p256 private key octet string
Hiya, My question: how does one setup an EVP_PKEY for a NIST curve (e.g. p256) key pair when one has the private key in an octet string using the latest OpenSSL 3.0.0 high level APIs? I'm trying to get rid of deprecation warnings from my code for HPKE [1] when dealing with NIST curves using the new (I guess?) OSSL_PARAM_* approach. I'm failing at the moment;-) So, given an octet string from a set of test vectors (e.g. [2]) what's the proper way to setup an EVP_PKEY for that to allow one to validate the test vectors? Happy to try produce a stand-alone example for this in the next few days if one doesn't exist (I've not found one so far). Thanks, Stephen. [1] https://github.com/sftcd/happykey/blob/7d52d34c516ab58ca1433004ff82b2a6a82eea4c/hpke.c#L1263 [2] https://github.com/cfrg/draft-irtf-cfrg-hpke OpenPGP_0x5AB2FAF17B172BEA.asc Description: application/pgp-keys OpenPGP_signature Description: OpenPGP digital signature