Openssl 3.0.0 creating ECC key from X and Y, PEM_write_PUBKEY fails

Matt Caswell matt at
Mon Oct 25 14:05:14 UTC 2021

On 22/10/2021 21:02, Ken Goldman wrote:
> I have X and Y as bignums.  I create EVP_PKEY with this.
> I suspect that I have to do another step to indicate that I supplied X 
> and Y and not a compressed
> public key.

Unfortunately supplying x and y separately is not supported for import. 
You have to instead use OSSL_PKEY_PARAM_PUB_KEY. You can supply the key 
as an uncompressed public key simply be concatenating the byte "04", the 
x co-ord (padded to the appropriate size if necessary) and the y co-cord 
(also padded as appropriate).

defined as "getters" only. From the manual:

"qx" (OSSL_PKEY_PARAM_EC_PUB_X) <unsigned integer>
Used for getting the EC public key X component.

"qy" (OSSL_PKEY_PARAM_EC_PUB_Y) <unsigned integer>
Used for getting the EC public key Y component.

>      param_bld = OSSL_PARAM_BLD_new();
>      rc = getEcCurveString(&curveString,        gets strings like 
> prime256v1
>      irc = OSSL_PARAM_BLD_push_utf8_string(param_bld, 
>                            curveString, 0);
>      irc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_EC_PUB_X, x);
>      irc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_EC_PUB_Y, y);
>      params = OSSL_PARAM_BLD_to_param(param_bld);
>      ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
>      irc = EVP_PKEY_fromdata_init(ctx);
>      irc = EVP_PKEY_fromdata(ctx, evpPubkey, EVP_PKEY_PUBLIC_KEY, params);

It's actually quite surprising that this call succeeds. IMO it should 
have failed:

What you've actually ended up with here is a parameters only EVP_PKEY value.

> following that, this fails with
>      irc = PEM_write_PUBKEY(pemFile, evpPubkey);
> ==88032== Invalid read of size 8

This crash is a bug in OpenSSL. You should have got a failure because 
your EVP_PKEY doesn't have a public key in it:


More information about the openssl-users mailing list