To generate key pair on a token, I need to provide the management key. The interface seems to be willing to accept it as --so-pin, however it appears that OpenSC checks the PIN length, determines that 48 (length of the management key) is longer than 8, and aborts with an error.
Either add a configuration parameter for so-pin min and max length, or at least point me at where in the code this check occurs, so I can temporarily switch it off.
Try
$ pkcs11-tool -k --key-type rsa:2048 --usage-sign --login --id 02 --login-type so --so-pin env:SOPIN --private --sensitive
$ pkcs11-tool --module /Library/OpenSC/lib/pkcs11-spy.dylib -k --key-type rsa:2048 --usage-sign --login --id 02 --login-type so --so-pin env:SOPIN --private --sensitive
*************** OpenSC PKCS#11 spy *****************
Loaded: "/Library/OpenSC/lib/opensc-pkcs11.dylib"
0: C_GetFunctionList
2018-05-15 21:05:33.465
Returned: 0 CKR_OK
1: C_Initialize
2018-05-15 21:05:33.467
[in] pInitArgs = 0x0
Returned: 0 CKR_OK
2: C_GetSlotList
2018-05-15 21:05:33.557
[in] tokenPresent = 0x0
[out] pSlotList:
Count is 1
[out] *pulCount = 0x1
Returned: 0 CKR_OK
3: C_GetSlotList
2018-05-15 21:05:33.558
[in] tokenPresent = 0x0
[out] pSlotList:
Slot 0
[out] *pulCount = 0x1
Returned: 0 CKR_OK
4: C_GetSlotInfo
2018-05-15 21:05:33.559
[in] slotID = 0x0
[out] pInfo:
slotDescription: 'Yubico Yubikey 4 OTP+U2F+CCID '
' '
manufacturerID: 'Yubico '
hardwareVersion: 4.55
firmwareVersion: 0.0
flags: 7
CKF_TOKEN_PRESENT
CKF_REMOVABLE_DEVICE
CKF_HW_SLOT
Returned: 0 CKR_OK
Using slot 0 with a present token (0x0)
5: C_OpenSession
2018-05-15 21:05:33.562
[in] slotID = 0x0
[in] flags = 0x6
pApplication=0x0
Notify=0x0
[out] *phSession = 0x7fc101f1f470
Returned: 0 CKR_OK
6: C_GetTokenInfo
2018-05-15 21:05:33.562
[in] slotID = 0x0
[out] pInfo:
label: 'PIV_II '
manufacturerID: 'piv_II '
model: 'PKCS#15 emulated'
serialNumber: 'f05f6fe956a5e163'
ulMaxSessionCount: 0
ulSessionCount: 0
ulMaxRwSessionCount: 0
ulRwSessionCount: 0
ulMaxPinLen: 8
ulMinPinLen: 4
ulTotalPublicMemory: -1
ulFreePublicMemory: -1
ulTotalPrivateMemory: -1
ulFreePrivateMemory: -1
hardwareVersion: 0.0
firmwareVersion: 0.0
time: ' '
flags: 40d
CKF_RNG
CKF_LOGIN_REQUIRED
CKF_USER_PIN_INITIALIZED
CKF_TOKEN_INITIALIZED
Returned: 0 CKR_OK
7: C_Login
2018-05-15 21:05:33.565
[in] hSession = 0x7fc101f1f470
[in] userType = CKU_SO
[in] pPin[ulPinLen] 00007ffee230acce / 48
00000000 . . . . .
Returned: 162 CKR_PIN_LEN_RANGE
8: C_Finalize
2018-05-15 21:05:33.565
Returned: 0 CKR_OK
error: PKCS11 function C_Login failed: rv = CKR_PIN_LEN_RANGE (0xa2)
Aborting.
$
I know the problem is with OpenSC, because when I use YKCS11 library it works:
$ pkcs11-tool --module /Library/OpenSC/lib/pkcs11-spy.dylib -k --key-type rsa:2048 --usage-sign --login --id 02 --login-type so --so-pin env:SOPIN --private --sensitive
*************** OpenSC PKCS#11 spy *****************
Loaded: "/usr/local/lib/libykcs11.dylib"
0: C_GetFunctionList
2018-05-15 21:07:09.336
Returned: 0 CKR_OK
1: C_Initialize
2018-05-15 21:07:09.336
[in] pInitArgs = 0x0
Returned: 0 CKR_OK
2: C_GetSlotList
2018-05-15 21:07:09.382
[in] tokenPresent = 0x0
[out] pSlotList:
Count is 1
[out] *pulCount = 0x1
Returned: 0 CKR_OK
3: C_GetSlotList
2018-05-15 21:07:09.382
[in] tokenPresent = 0x0
[out] pSlotList:
Slot 0
[out] *pulCount = 0x1
Returned: 0 CKR_OK
4: C_GetSlotInfo
2018-05-15 21:07:09.382
[in] slotID = 0x0
[out] pInfo:
slotDescription: ' Yubico Yubikey 4 OTP+U2F+CCID'
' ]'
manufacturerID: 'Yubico '
hardwareVersion: 1.0
firmwareVersion: 1.0
flags: 5
CKF_TOKEN_PRESENT
CKF_HW_SLOT
Returned: 0 CKR_OK
Using slot 0 with a present token (0x0)
5: C_OpenSession
2018-05-15 21:07:09.382
[in] slotID = 0x0
[in] flags = 0x6
pApplication=0x0
Notify=0x0
[out] *phSession = 0x51b660
Returned: 0 CKR_OK
6: C_GetTokenInfo
2018-05-15 21:07:09.525
[in] slotID = 0x0
[out] pInfo:
label: 'YubiKey PIV '
manufacturerID: 'Yubico '
model: 'YubiKey YK4 '
serialNumber: '1234 '
ulMaxSessionCount: -1
ulSessionCount: -1
ulMaxRwSessionCount: -1
ulRwSessionCount: -1
ulMaxPinLen: 8
ulMinPinLen: 6
ulTotalPublicMemory: -1
ulFreePublicMemory: -1
ulTotalPrivateMemory: -1
ulFreePrivateMemory: -1
hardwareVersion: 0.0
firmwareVersion: 4.51
time: ' '
flags: 40d
CKF_RNG
CKF_LOGIN_REQUIRED
CKF_USER_PIN_INITIALIZED
CKF_TOKEN_INITIALIZED
Returned: 0 CKR_OK
7: C_Login
2018-05-15 21:07:09.525
[in] hSession = 0x51b660
[in] userType = CKU_SO
[in] pPin[ulPinLen] 00007ffee9378cd6 / 48
00000000 . . . . .
Returned: 0 CKR_OK
8: C_GetMechanismList
2018-05-15 21:07:09.530
[in] slotID = 0x0
[out] pMechanismList[20]:
Count is 20
Returned: 0 CKR_OK
9: C_GetMechanismList
2018-05-15 21:07:09.530
[in] slotID = 0x0
[out] pMechanismList[20]:
CKM_RSA_PKCS_KEY_PAIR_GEN
CKM_RSA_PKCS
CKM_RSA_PKCS_PSS
CKM_RSA_X_509
CKM_SHA1_RSA_PKCS
CKM_SHA256_RSA_PKCS
CKM_SHA384_RSA_PKCS
CKM_SHA512_RSA_PKCS
CKM_SHA1_RSA_PKCS_PSS
CKM_SHA256_RSA_PKCS_PSS
CKM_SHA384_RSA_PKCS_PSS
CKM_SHA512_RSA_PKCS_PSS
CKM_EC_KEY_PAIR_GEN
CKM_ECDSA
CKM_ECDSA_SHA1
Unknown Mechanism (00001044)
CKM_SHA_1
CKM_SHA256
CKM_SHA384
CKM_SHA512
Returned: 0 CKR_OK
. . . . .
30: C_GenerateKeyPair
2018-05-15 21:07:09.531
[in] hSession = 0x51b660
pMechanism->type=CKM_RSA_PKCS_KEY_PAIR_GEN
[in] pPublicKeyTemplate[8]:
CKA_CLASS CKO_PUBLIC_KEY
CKA_TOKEN True
CKA_MODULUS_BITS 00007ffee9376b20 / 8
00000000 00 08 00 00 00 00 00 00 ........
CKA_PUBLIC_EXPONENT 00007ffee9376b3a / 3
00000000 01 00 01 ...
CKA_VERIFY True
CKA_WRAP True
CKA_ID 00000001068a5730 / 1
00000000 02 .
CKA_PRIVATE True
[in] pPrivateKeyTemplate[7]:
CKA_CLASS CKO_PRIVATE_KEY
CKA_TOKEN True
CKA_PRIVATE True
CKA_SENSITIVE True
CKA_SIGN True
CKA_UNWRAP True
CKA_ID 00000001068a5730 / 1
00000000 02 .
Attempt to generate RSA key, key_len=2048
[out] hPublicKey = 0x59
[out] hPrivateKey = 0x40
Returned: 0 CKR_OK
Key pair generated:
31: C_GetAttributeValue
2018-05-15 21:07:14.843
[in] hSession = 0x51b660
[in] hObject = 0x40
[in] pTemplate[1]:
CKA_CLASS 00007ffee9376aa0 / 8
[out] pTemplate[1]:
CKA_CLASS CKO_PRIVATE_KEY
Returned: 0 CKR_OK
32: C_GetAttributeValue
2018-05-15 21:07:14.844
[in] hSession = 0x51b660
[in] hObject = 0x40
[in] pTemplate[1]:
CKA_KEY_TYPE 00007ffee9376aa0 / 8
[out] pTemplate[1]:
CKA_KEY_TYPE CKK_RSA
Returned: 0 CKR_OK
. . . . .
56: C_CloseSession
2018-05-15 21:07:14.846
[in] hSession = 0x51b660
Returned: 0 CKR_OK
57: C_Finalize
2018-05-15 21:07:14.849
Returned: 0 CKR_OK
$
The PIV's PUK is fixed to a maximum of 8 digits, which is the reason for this behavior, I suppose. Maybe @dengert has some idea on how to make this more flexible...
The PUK is a 8 byte PIN and is not the same as the admin 9B key which is 3DES, 2DES or AES.
The PIV driver does not support trying to pass a 48 byte key as a PIN.
NIST 800-73 specifically left card provisioning up to the card vendors. (And it does not define any commands to write a private key to the card only how to generate a key pair on the card returning the public key as part of the command.)
The OpenSC piv-tool does provide a way to use a 3DES or AES key with external or mutual authentication to the card as defined in NIST 800-73, but a vendor is not required to use the 9B key to provision their cards. You need to look at the card's documentation to see what the card requires. The piv-tool was designed to allow for doing some card provisioning for test purposes. Get a Card Management System or use the Yubico piv tool if needed.
piv-tool Wiki page describes how to:
@dengert, understood, thank you! You're perfectly correct in everything you said, and thanks for the reference to piv-tool that can do the job!
Still, since pkcs11-tool does offer the option of generating key pairs (--keypairgen), it would be nice if there was a way to pass the 9B key along with the --keypairgen request. Otherwise one wonders what's the point of allowing an operation you've no way of authenticating for.
What is your opinion?
P.S. Could you point me at the place in the code where the PIV PUK length is checked? I'd like to introduce a command-line parameter to disable that check that could be used in a special case (generating key pair), while for all the "normal" operations this check would still be present.
"what's the point?" The point some cards are designed (and documented) to do things other cards are not. The PIV driver is sticking to the documented standards PIV standards. There are security risks too with the 9B key. Each card should have a different 9B key. NIST does not define how to change it. A card management system would do that for you.
I keep talking about using the card vendor's tools for card management. Yubico is the card vendor in your case and they know all the features of their device and how to manage it. Use their tools for card management. You could ask the Yubico people to add the feature to their pkcs11 module. If not they have open source, you could modify their code too.
P.S. I am not going to point you at the place in the code teh PIV PUK length is checked. Its not just checking the length, you then have to use it.
Yubico is the card vendor in your case and they know all the features of their device and how to manage it. Use their tools for card management.
I am cross-checking their tools. Also, their tools use different naming/addressing for the objects on the token, which is a pain.
You could ask the Yubico people to add the feature to their pkcs11 module.
I already did.
If not they have open source, you could modify their code too.
I already did.