openssl: X509_check_private_key() crash with EC key from engine

(cf. https://github.com/OpenSC/libp11/issues/98)

When the PKCS#11 engine has only private key and no public key, I get a crash in EC_POINT_cmp():

Starting program: /home/dwmw2/git/openconnect/ossl/.libs/openconnect -c pkcs11:token=foo1\;pin-value=1234\;object=ecnopub localhost:4443 --servercert sha1:a82547f68f44d6351bef6cacd1d7b96e84f9dfa3
...
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6c30a58 in EC_POINT_cmp (group=0x6d7680, a=0x6d6660, b=0x0, ctx=0x0)
    at ec_lib.c:1001
1001        if ((group->meth != a->meth) || (a->meth != b->meth)) {
Missing separate debuginfos, use: dnf debuginfo-install krb5-libs-1.14.1-7.fc23.x86_64 libp11-0.3.0-1.fc23.x86_64 libtasn1-4.8-2.fc23.x86_64 lz4-r131-1.fc23.x86_64 opensc-0.15.0-4.fc23.x86_64 pcsc-lite-libs-1.8.15-1.fc23.x86_64 softhsm-2.1.0-1.fc23.x86_64 stoken-libs-0.90-2.fc23.x86_64
(gdb) bt
#0  0x00007ffff6c30a58 in EC_POINT_cmp (group=0x6d7680, a=0x6d6660, b=0x0, 
    ctx=0x0) at ec_lib.c:1001
#1  0x00007ffff6c3aacc in eckey_pub_cmp (a=<optimized out>, b=0x6d44c0)
    at ec_ameth.c:224
#2  0x00007ffff6caee51 in X509_check_private_key (x=<optimized out>, 
    k=k@entry=0x6d44c0) at x509_cmp.c:333
#3  0x00007ffff6ffda9c in ssl_set_pkey (c=0x649bc0, pkey=0x6d44c0)
    at ssl_rsa.c:223
#4  0x00007ffff7bcdf99 in load_pkcs11_key (vpninfo=0x644a90)
    at ../openssl-pkcs11.c:584
#5  0x00007ffff7bca00d in load_certificate (vpninfo=0x644a90)
    at ../openssl.c:889
#6  0x00007ffff7bcb65c in openconnect_open_https (vpninfo=0x644a90)
    at ../openssl.c:1633
#7  0x00007ffff7ba21a0 in do_https_request (vpninfo=0x644a90, 
    method=0x7ffff7bd2bdf "POST", 
    request_body_type=0x7ffff7bd2e60 "application/x-www-form-urlencoded", 
    request_body=0x645660, form_buf=0x7fffffffd960, fetch_redirect=0)
    at ../http.c:875
#8  0x00007ffff7bbba70 in cstp_obtain_cookie (vpninfo=0x644a90)
    at ../auth.c:1285
#9  0x00007ffff7ba5b06 in openconnect_obtain_cookie (vpninfo=0x644a90)
    at ../library.c:182

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 32 (32 by maintainers)

Commits related to this issue

Most upvoted comments

You mean add another signature operation to be done on a possibly slow smart card?

Who is “we” in this? There are multiple pieces of software involved that each have a piece of the information and expectations of what they need.

OpenSSL expects it private EVP_PKEY to contain the ec_point.

The token, that does not have or does not expose the ec_point for a private key.

PKCS#11 does not return the ec_point as an attribute for private key, and specifically says to get the ec_pont from the public key.

libp11 that gets all its information from the token via PKCS#11 API.

You, the user, said you did not want to put the pubkey on the token. If you put the pubkey on the token, the problem goes away.

The openconnect could try and add the ec_point to the EVP_KEY by parsing the cert you are reading from a file anyway. But that only fixes the issue for openconnect.

libp11 could fail to load the private key if it can not also find the ec_point via the pubkey. If we add this you will have to put the pubkey on the token anyway.

In any case OpenSSL should not segfault. But what should OpenSSL do if the the key does not have the ec_point? Why is it comparing the keys to see if they match? Sounds like to me they added extra checks but if they did not check and just went ahead things should work. (Should be verified that that is the case.) But they may stick by their statement that “OpenSSL private keys contain public key components” and fail the compare.

If they take that stance, you will have to patch openconnect or add the pubkey to the token.

I have not run into this situation. The main card I have interest in is the PIV card. The only way to find out what keys are on the card, the type of the key, the parameters, the size and the ec_point is to read the certificate object for each key. The OpenSC driver reads the certificate to get the information and then presents via PKCS#11 the certificate, public key and private key. libp11 then reads the public key and private key and get the ec_point from the public key to place into the EVP_PKEY used by OpenSSL.

So why not just put the public key on the token?