PyKCS11: session.deriveKey and CKR_DATA_LEN_RANGE

Good morning!

my goal is to set up an ECIES with ECDH1. I have it working using pkcs11-tool and openssl, however i can’t make this work with python.

PyKCS11/test/test_derive.py at master · LudovicRousseau/PyKCS11 · GitHub

triggers:

derivedKey = self.session.deriveKey(self.baseEcPvtKey, derivedAESKeyTemplate, mechanism)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/armin/PyKCS11/PyKCS11/init.py”, line 1311, in deriveKey
raise PyKCS11Error(rv)
PyKCS11.PyKCS11Error: CKR_DATA_LEN_RANGE (0x00000021)

Question: The idea behind the python code is to create the derived AES key on the HSM. However, afaik the nitrokey HSM can’t decrypt AES anyhow. The pkcs11-tool just dumps the byte[] of the DH derived key into a file (which is good for me). However, i was unable to find something like

session.deriveBytes(…) or similar. I hope you get the idea. Please clarify howto do ECDH using python.

Thanks,
Armin

Generate an EC key pair

> pkcs11-tool --login --pin 648219 --keypairgen --key-type EC:prime256v1 --label ecdh
Using slot 0 with a present token (0x0)
Key pair generated:
Private Key Object; EC
  label:      ecdh
  ID:         d439cc0a31785ba7f028e5f91834daaf52cc9a72
  Usage:      sign, derive
  Access:     none
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   044104d921d999e57869dd2804b0acacde7c15b666e2bf638e611e353451afb9fe9c797f72f9f8ef348d08adb2afb793391003d03af4ff278f8e5a2a7da76837bda5e7
  EC_PARAMS:  06082a8648ce3d030107
  label:      ecdh
  ID:         d439cc0a31785ba7f028e5f91834daaf52cc9a72
  Usage:      verify, derive
  Access:     none

Export the public key

> pkcs11-tool --login --pin 648219 --read --type pubkey --id d439cc0a31785ba7f028e5f91834daaf52cc9a72 -o pubkey

Perform derive using the exported public key and the private key in the device

pkcs11-tool --login --pin 648219 --derive --id d439cc0a31785ba7f028e5f91834daaf52cc9a72 -i pubkey -o res

This of course also works any EC public key on the same curve.

At the PKCS#11 layer the following functions are called

47: C_DeriveKey
2023-08-08 11:51:03.857
[in] hSession = 0x55b1f23054a0
[in] pMechanism->type = CKM_ECDH1_COFACTOR_DERIVE    
[in] pMechanism->pParameter->kdf = CKD_NULL
[in] pMechanism->pParameter->pSharedData[ulSharedDataLen] = NULL [size : 0x0 (0)]
[in] pMechanism->pParameter->pPublicData[ulPublicDataLen] = 000055b1f23137a0 / 65
    00000000  04 D9 21 D9 99 E5 78 69 DD 28 04 B0 AC AC DE 7C  ..!...xi.(.....|
    00000010  15 B6 66 E2 BF 63 8E 61 1E 35 34 51 AF B9 FE 9C  ..f..c.a.54Q....
    00000020  79 7F 72 F9 F8 EF 34 8D 08 AD B2 AF B7 93 39 10  yr...4.......9.
    00000030  03 D0 3A F4 FF 27 8F 8E 5A 2A 7D A7 68 37 BD A5  ..:..'..Z*}.h7..
    00000040  E7                                               .               
[in] hBaseKey = 0x55b1f2303230
[in] pTemplate[10]: 
    CKA_TOKEN             False
    CKA_CLASS             CKO_SECRET_KEY       
    CKA_KEY_TYPE          CKK_GENERIC_SECRET 
    CKA_SENSITIVE         False
    CKA_EXTRACTABLE       True
    CKA_ENCRYPT           True
    CKA_DECRYPT           True
    CKA_WRAP              True
    CKA_UNWRAP            True
    CKA_VALUE_LEN         00007ffe115a4988 / 8
    00000000  20 00 00 00 00 00 00 00                           .......        
[out] hKey = 0x55b1f2314640
Returned:  0 CKR_OK

48: C_GetAttributeValue
2023-08-08 11:51:03.937
[in] hSession = 0x55b1f23054a0
[in] hObject = 0x55b1f2314640
[in] pTemplate[1]: 
    CKA_VALUE             0000000000000000 / 0
[out] pTemplate[1]: 
    CKA_VALUE             0000000000000000 / 32
Returned:  0 CKR_OK

49: C_GetAttributeValue
2023-08-08 11:51:03.938
[in] hSession = 0x55b1f23054a0
[in] hObject = 0x55b1f2314640
[in] pTemplate[1]: 
    CKA_VALUE             000055b1f23146f0 / 32
[out] pTemplate[1]: 
    CKA_VALUE             000055b1f23146f0 / 32
    00000000  89 B2 C0 76 DE 55 38 3D 87 29 78 31 35 31 EC 0F  ...v.U8=.)x151..
    00000010  B2 A8 E7 43 62 DC 21 F8 A1 52 8B E5 BD B5 7A 25  ...Cb.!..R....z%
Returned:  0 CKR_OK

When reading the public key with C_GetAttributeValue(CKA_EC_POINT) at the PKCS#11 interface it is important to remember, that the EC_POINT is returned in DER encoding, meaning that you need to strip the first two bytes (Tag,Length) before you pass it in pPublicData.

I’ve created a sc-hsm-python repo in the CDN with amended samples.