Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SOFT: Import (C_CreateObject) ECC public key failed. #634

Closed
kevhsu-k opened this issue Dec 16, 2022 · 10 comments
Closed

SOFT: Import (C_CreateObject) ECC public key failed. #634

kevhsu-k opened this issue Dec 16, 2022 · 10 comments
Assignees
Labels

Comments

@kevhsu-k
Copy link

Hi there,

I was trying to import a ECC public key with the soft token.
Neither using the pkcs11-tool nor PKCS#11 API in C works.
(ECC private key however does work)

Here is how I import the public key:

// first using OpenSSL to create a EC key pair
openssl ecparam -name prime256v1 -genkey -noout -out ec_temp_private.pem
openssl ec -in ec_temp_private.pem -out temp_pub.der -outform DER -pubout 1>/dev/null 2>/dev/null

// Import the public key with OpenSC pkcs11-tool
pkcs11-tool --module /usr/local/lib/opencryptoki/libopencryptoki.so -l --pin <pin> --write-object ./temp_pub.der --type pubkey --id 2222


// I got 
// Using slot 3 with a present token (0x3)
// error: PKCS11 function C_CreateObject failed: rv = unknown PKCS11 error (0x1b9)
// Aborting.
// I tried both pem and der format. I  got the same error.

// Let's try private key

pkcs11-tool --module /usr/local/lib/opencryptoki/libopencryptoki.so -l --pin <pin> --write-object ./ec_temp_private.pem --type privkey --id 2222

// success

Similarly, if I use the PKCS#11 C API to C_CreateObject the EC public key and private key. I can create private key successfully but fail on public key.

@jschmidb jschmidb self-assigned this Dec 19, 2022
@jschmidb
Copy link
Contributor

I gave it a quick try on my test system (fedora 37). I had to use the --token-label parm to identify the softtoken:

# pkcs11-tool --module /usr/local/lib/opencryptoki/libopencryptoki.so -l --pin xxxxxxxx --write-object ./temp_pub.der --type pubkey --id 2222 --token-label softtok
Created public key:
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   044104f2fd1487d46853fab3ddf258cb4403d7ffbb517029ccf032763d1e543debdcf84999143aee1ce2cf28e0f7903e62bba86a16589a8797169070fd5f1616ab2b1a
  EC_PARAMS:  06082a8648ce3d030107
  label:
  ID:         2222
  Usage:      encrypt, verify, wrap
  Access:     none
  Unique ID:  37828c8faa5c2c36d3a70187fe7f3d0b219652526b30eb7d1b99cbd4abe8d079

So this worked ok. Same for private key. Can you retry with --token-label too? If it doesn't work, please turn on the opencryptoki trace:
# export OPENCRYPTOKI_TRACE_LEVEL=4
Then send me the trace output, which goes to /usr/local/var/log/opencryptoki.

@kevhsu-k
Copy link
Author

kevhsu-k commented Dec 20, 2022

Hello @jschmidb,
Thanks for trying this in your environment.
Mine is Ubuntu18.04 aarch64 + OpenSSL 1.1.1 11 Sep 2018
I am still having the same issue even with the --token-label param.

There is an ERROR: Not a valid EC Point: data too large in the below tracing.

12/20/2022 09:19:27 108 [usr/lib/common/trace.c:211 api] INFO: **** OCK Trace level 4 activated for OCK version 3.19.0 ****
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2897 api] INFO: C_Initialize
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:3099 api] DEVEL: pid: 108 real-pid: 108 euid: 0 real-uid: 108 real-gid: 0 gid: 108
12/20/2022 09:19:27 108 [usr/lib/api/policy.c:1529 api] DEVEL: Parsing strength configuration file
12/20/2022 09:19:27 108 [usr/lib/api/statistics.c:340 api] INFO: 5 slots defined
12/20/2022 09:19:27 108 [usr/lib/api/statistics.c:341 api] INFO: Statistics SHM size: 24400
12/20/2022 09:19:27 108 [usr/lib/api/statistics.c:190 api] INFO: Statistics SHM name: '/usr.local.var.lib.opencryptoki_stats_0'
12/20/2022 09:19:27 108 [usr/lib/api/apiutil.c:404 api] DEVEL: API_Register MgrProcIndc 0 (real) pid 108 
12/20/2022 09:19:27 108 [usr/lib/api/apiutil.c:541 api] DEVEL: DL_Load of libpkcs11_tpm.so failed, dlerror: libpkcs11_tpm.so: cannot open shared object file: No such file or directory
12/20/2022 09:19:27 108 [usr/lib/api/apiutil.c:541 api] DEVEL: DL_Load of libpkcs11_ica.so failed, dlerror: libpkcs11_ica.so: cannot open shared object file: No such file or directory
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:121 ccatok] DEVEL: Token version: 3.12
12/20/2022 09:19:27 108 [usr/lib/common/shared_memory.c:141 ccatok] DEVEL: File path "/usr/local/var/lib/opencryptoki/ccatok" converted to "/usr.local.var.lib.opencryptoki.ccatok".
12/20/2022 09:19:27 108 [usr/lib/common/shared_memory.c:341 ccatok] DEVEL: open: ref = 1
12/20/2022 09:19:27 108 [usr/lib/cca_stdll/cca_specific.c:1354 ccatok] INFO: cca token_specific_init slot=2 running
12/20/2022 09:19:27 108 [usr/lib/cca_stdll/cca_specific.c:1382 ccatok] ERROR: token_specific_init: Error loading shared library 'libcsulcca.so' [(null)]
12/20/2022 09:19:27 108 [usr/lib/cca_stdll/cca_specific.c:1411 ccatok] INFO: cca token_specific_final running
12/20/2022 09:19:27 108 [usr/lib/common/shared_memory.c:375 ccatok] DEVEL: close: ref = 0
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:166 ccatok] DEVEL: Token Specific Init failed.
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:121 swtok] DEVEL: Token version: 3.12
12/20/2022 09:19:27 108 [usr/lib/common/shared_memory.c:141 swtok] DEVEL: File path "/usr/local/var/lib/opencryptoki/swtok" converted to "/usr.local.var.lib.opencryptoki.swtok".
12/20/2022 09:19:27 108 [usr/lib/common/shared_memory.c:341 swtok] DEVEL: open: ref = 1
12/20/2022 09:19:27 108 [usr/lib/soft_stdll/soft_specific.c:238 swtok] INFO: soft token_specific_init slot=3 running
12/20/2022 09:19:27 108 [usr/lib/api/apiutil.c:541 api] DEVEL: DL_Load of libpkcs11_ep11.so failed, dlerror: libpkcs11_ep11.so: cannot open shared object file: No such file or directory
12/20/2022 09:19:27 108 [usr/lib/api/socket_client.c:471 api] DEVEL: Event thread 281473035473392 has been started
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2674 api] INFO: C_GetSlotList
12/20/2022 09:19:27 109 [usr/lib/api/socket_client.c:307 api] DEVEL: Event thread 281473035473392 running
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2687 api] DEVEL:  Present 0 Count 0
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2674 api] INFO: C_GetSlotList
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2687 api] DEVEL:  Present 0 Count 5
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2812 api] INFO: C_GetTokenInfo
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2830 api] DEVEL: Slot p = 0xffff8ce670e8 id 0
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2832 api] ERROR: Token Not Present
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2812 api] INFO: C_GetTokenInfo
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2830 api] DEVEL: Slot p = 0xffff8ce67120 id 1
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2832 api] ERROR: Token Not Present
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2812 api] INFO: C_GetTokenInfo
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2830 api] DEVEL: Slot p = 0xffff8ce67158 id 2
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2832 api] ERROR: Token Not Present
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2812 api] INFO: C_GetTokenInfo
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2830 api] DEVEL: Slot p = 0xffff8ce67190 id 3
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:290 swtok] INFO: C_GetTokenInfo: rc = 0x00000000
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2854 api] DEVEL: rv 0 CK_TOKEN_INFO Flags 44d
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:3487 api] INFO: C_OpenSession  3 6 (nil) (nil) 0xffffe504acb8
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:1028 swtok] INFO: C_OpenSession: rc = 0x00000000 sess = 1
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:3530 api] DEVEL: fcn->ST_OpenSession returned: 0x0
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2812 api] INFO: C_GetTokenInfo
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2830 api] DEVEL: Slot p = 0xffff8ce67190 id 3
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:290 swtok] INFO: C_GetTokenInfo: rc = 0x00000000
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:2854 api] DEVEL: rv 0 CK_TOKEN_INFO Flags 44d
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:3369 api] INFO: C_Login
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:3385 api] INFO: Valid Session handle id: 1
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:1512 swtok] INFO: C_Login: rc = 0x00000000
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:3400 api] DEVEL: fcn->ST_Login returned:0x0
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:623 api] INFO: C_CreateObject
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:634 api] INFO: Valid Session handle id: 1
12/20/2022 09:19:27 108 [usr/lib/common/asn1.c:409 swtok] ERROR: Function Failed
12/20/2022 09:19:27 108 [usr/lib/common/mech_ec.c:1551 swtok] DEVEL: Raw EC Point
12/20/2022 09:19:27 108 [usr/lib/common/mech_ec.c:1569 swtok] ERROR: Not a valid EC Point: data too large
12/20/2022 09:19:27 108 [usr/lib/common/mech_openssl.c:1910 swtok] DEVEL: ec_point_from_public_data failed
12/20/2022 09:19:27 108 [usr/lib/common/mech_openssl.c:2165 swtok] DEVEL: fill_ec_key_from_pubkey failed
12/20/2022 09:19:27 108 [usr/lib/common/obj_mgr.c:112 swtok] DEVEL: Token specific object add failed.
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:1613 swtok] DEVEL: object_mgr_add() failed.
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:1619 swtok] INFO: C_CreateObject: rc = 0x000001b9
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:668 api] DEVEL: fcn->ST_CreateObject returned:0x1b9
12/20/2022 09:19:27 108 [usr/lib/api/api_interface.c:1664 api] INFO: C_Finalize
12/20/2022 09:19:27 108 [usr/lib/api/socket_client.c:480 api] DEVEL: Canceling event thread 281473035473392
12/20/2022 09:19:27 108 [usr/lib/api/socket_client.c:486 api] DEVEL: Waiting for event thread 281473035473392 to terminate
12/20/2022 09:19:27 109 [usr/lib/api/socket_client.c:285 api] DEVEL: Event thread 281473035473392 terminating
12/20/2022 09:19:27 108 [usr/lib/api/socket_client.c:496 api] DEVEL: Event thread 281473035473392 has terminated
12/20/2022 09:19:27 108 [usr/lib/common/new_host.c:1053 swtok] INFO: C_CloseSession: rc = 0x00000000, sess = 1
12/20/2022 09:19:27 108 [usr/lib/common/shared_memory.c:375 swtok] DEVEL: close: ref = 0
12/20/2022 09:19:27 108 [usr/lib/soft_stdll/soft_specific.c:248 swtok] INFO: soft token_specific_final running

btw, I have tried the same commands with SoftHSMv2. I am able to insert the public key to SoftHSMv2 successfully.

@jschmidb
Copy link
Contributor

Interesting ... first I retried on a Ubuntu 18.04.6 LTS (which in fact has an OpenSSL 1.1.1 11 Sep 2018) with opencryptoki from the Ubuntu package:

# apt install opensc
# apt install opencryptoki
# openssl ecparam -name prime256v1 -genkey -noout -out ec_temp_private.pem
# openssl ec -in ec_temp_private.pem -out temp_pub.der -outform DER -pubout 1>/dev/null 2>/dev/null
# pkcs11-tool --module /usr/lib/s390x-linux-gnu/opencryptoki/libopencryptoki.so.0 -l --pin xxxxxxxx --write-object ./temp_pub.der --type pubkey --id 2222 --token-label softtok    
Created public key:
Public Key Object; EC  EC_POINT 248 bits
  EC_POINT:   0439d5568321e033c2158e0970c97af782472303f7e260f41cd75cb2351b41800b669a74e7642acd9642a9c1335e1c687d2519061211e588a27eb9877186c5df9e
  EC_PARAMS:  06082a8648ce3d030107
  label:
  ID:         2222
  Usage:      encrypt, verify, wrap

So this again worked ok.

Then I installed opencryptoki from upstream and can now reproduce your error:

12/21/2022 12:18:53 207817 [usr/lib/common/mech_ec.c:1569 swtok] ERROR: Not a valid EC Point: data too large
12/21/2022 12:18:53 207817 [usr/lib/common/mech_openssl.c:1910 swtok] DEVEL: ec_point_from_public_data failed
12/21/2022 12:18:53 207817 [usr/lib/common/mech_openssl.c:2165 swtok] DEVEL: fill_ec_key_from_pubkey failed

We will get back to you when we know more ...
For now, as a circumvention, you may install and use opencryptoki via the Ubuntu package manager. I guess this will also work in your environment. Thanks for reporting!

@kevhsu-k
Copy link
Author

Hello @jschmidb,

I tried the Ubuntu package, and it works. I think the package is supporting OpenCryptoki 3.9.0. However, I need the some mechanism listed in 3.19.0. I will wait for your response. Really appreciate your help. ☺️

@ifranzki
Copy link
Contributor

ifranzki commented Jan 4, 2023

It seems that the EC Point that is passed in via CKA_EC_POINT attribute in the public key template is not DER encoded.
As per PKCS#11 standard, the CKA_EC_POINT attribute must hold the DER-encoding of ANSI X9.62 ECPoint value Q. This means it must be an EC-point enclosed within a OCTET STRING.

Joergs tracing shows that it is instead a a 'raw' EC-Point that is passed in.
So from that I would conclude that openCryptoki is behaving correctly by rejecting this as invalid data. It may be that an earlier openCryptoki version did accept such a raw EC-Point, but this was a bug then.

Please note that the only place where an EC public key is accepted as raw EC-point is via pPublicData within the CK_ECDH1_DERIVE_PARAMS structure of a ECDH mechanism parameter. There, the PKCS#11 standard states:

pPublicData - pointer to other party’s EC public key value. A token MUST be able to accept this value encoded as a raw octet string (as per section A.5.2 of [ANSI X9.62]). A token MAY, in addition, support accepting this value as a DER-encoded ECPoint (as per section E.6 of [ANSI X9.62]) i.e. the same as a CKA_EC_POINT encoding. The calling application is responsible for converting the offered public key to the compressed or uncompressed forms of these encodings if the token does not support the offered form.

Please note that this note does NOT apply for importing EC public keys! CKA_EC_POINT attributes must always contain the DER encoded EC-point.

So I guess that the bug is in the pkcs11-tool not supplying a DER-encoded EC-point in CKA_EC_POINT.

Note that the openssl ecparam command outputs a DER encoded SubjectPublicKeyInfo which consists of a SEQUENCE of an AlgorithmIdentifier and the subjectPublicKey. The subjectPublicKey is a BITSTRING containing the raw EC-Point. So pkcs11-tool will need to take the raw EC-POINT and DER encode it by wrapping it within an OCTET STRING and pass the result as CKA_EC_POINT to openCryptoki.

@ifranzki
Copy link
Contributor

ifranzki commented Jan 4, 2023

Given that Joerg tried it on Fedora 37 and it worked, I assume that the pkcs11-tool fixed this problem aready some time ago. Fedora 37 probably has a newer opensc package (that includes the fix) than Ubuntu 18.04 (which does not include the fix).....

@kevhsu-k
Copy link
Author

kevhsu-k commented Jan 4, 2023

@ifranzki @jschmidb
Thanks for the reply. I also wrote a cpp code to try it. And still no good.

    // Given a EVP_PKEY, ecpubkey
    EC_KEY* ecc_key = EVP_PKEY_get1_EC_KEY(ecpubkey);
    // Read the EC params.
    int num_bytes = i2d_ECParameters(ecc_key, nullptr);
    std::vector<uint8_t> ec_params(num_bytes);
    unsigned char* ec_params_bytes = ec_params.data();
    i2d_ECParameters(ecc_key, &ec_params_bytes);
    
    // Read the EC Point.
    num_bytes = i2o_ECPublicKey(ecc_key, nullptr);
    std::vector<uint8_t> ec_Qvalue(num_bytes);
    unsigned char* ec_Qvalue_bytes = ec_Qvalue.data();
    i2o_ECPublicKey(ecc_key, &ec_Qvalue_bytes);

    CK_RV rv;
    CK_OBJECT_CLASS ecc_key_class = CKO_PUBLIC_KEY;
    CK_KEY_TYPE key_type = CKK_EC;
    

    CK_ATTRIBUTE ecc_tmpl[] = {
            {CKA_KEY_TYPE,        &key_type,      sizeof(key_type)},
            {CKA_CLASS,              &ecc_key_class, sizeof(ecc_key_class)},
            {CKA_TOKEN,              &true_val,      sizeof(CK_BBOOL)},
            {CKA_PRIVATE,           &false_val,     sizeof(CK_BBOOL)},
            {CKA_VERIFY,              &true_val,      sizeof(CK_BBOOL)},
            {CKA_EC_PARAMS,    ec_params.data(),  ec_params.size()},
            {CKA_EC_POINT,        ec_Qvalue.data(),   ec_Qvalue.size()}
    };
    rv = funcs->C_CreateObject(session, ecc_tmpl, sizeof(ecc_tmpl) / sizeof(CK_ATTRIBUTE), &key_handle);

I have also double checked the content of ec_Qvalue_bytes are 65 bytes. And the value is the same as the last 65 bytes in my DER encoded public key.

  • The last 65 bytes of the hex dump of my pubkey.der is 04 dc d2 c9 d7 ... c9
  • The value of ec_Qvalue_bytes is 4 220 210 201 215 ... 201

Please correct me if I did anything wrong.

Btw, I have also tried the above code on AWS CloudHSM and it works.

@ifranzki
Copy link
Contributor

ifranzki commented Jan 4, 2023

The 65 bytes is the raw EC-Point. But CKA_EC_POINT needs to hold the DER encoded (OCTET STRING) enclosed EC-Point:
04 41 04 dc d2 c9 d7 ... c9 ... with total of 67 bytes (65 + 2)
The first 04 is the DER tag for an OCTET STRING. The 41 is the length of the octet string, i.e. 65 bytes. The rest is the EC-point with its format byte (04) and then two times 32 bytes for X and Y (= 65 bytes).

Btw, I have also tried the above code on AWS CloudHSM and it works.

Well, then AWS CloudHSM is not conforming to the PKCS#11 standard. The PKCS#11 standard clearly states that CKA_EC_POINT must contain the DER-encoding of ANSI X9.62 ECPoint value Q, and ANSI X9.62 defines
ECPoint ::= OCTET STRING

@ifranzki
Copy link
Contributor

ifranzki commented Jan 4, 2023

This was fixed with OpenSC issue OpenSC/OpenSC#1286 and commit OpenSC/OpenSC@ea4baf5
Before that commit it was passing the raw EC-point to CKA_EC_POINT.
So most likely your system still has an pkcs11-tool version without that fix.

@kevhsu-k
Copy link
Author

kevhsu-k commented Jan 4, 2023

@ifranzki
Really thanks a lot.
I just tried adding the 04 41 and make it 67 bytes. It works.
Also tried that on AWS CloudHSM and works as well. (seems AWS CloudHSM accept both 65 and 67 bytes.)
I will close this issue now. Really appreciate your help 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants