My application wants to sign documents using YubiKey with PIV (PKCS11). I was able to Login to my YubiKey but When I try to generate KeyPairs, it throws this error.
"Method C_GenerateKeyPair returned CKR_ATTRIBUTE_VALUE_INVALID"
This is the code I have right now (C# .NET)
byte[] ckaId = session.GenerateRandom(20);
// Prepare attribute template of new public key
List<IObjectAttribute> publicKeyAttributes = new List<IObjectAttribute>();
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, false));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, @"TestApp"));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ENCRYPT, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_VERIFY, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_WRAP, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODIFIABLE, false));
// Prepare attribute template of new private key
List<IObjectAttribute> privateKeyAttributes = new List<IObjectAttribute>();
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, @"TestApp"));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SENSITIVE, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DECRYPT, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SIGN, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_UNWRAP, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODIFIABLE, false));
// Specify key generation mechanism
IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN);
// Generate key pair
IObjectHandle publicKeyHandle = null;
IObjectHandle privateKeyHandle = null;
session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle);
There are a few changes that need to be made to get past all the errors. To help anyone that hits similar vague error messages in the future the thing that helped me the most here was setting the
YKCS11_DBG
environment variable so that error messages from the libykcs11 library get printed to stderr (the Yubico docs here aren't up to date in all sections but they mention the variable and a few other relevant things here https://developers.yubico.com/yubico-piv-tool/YKCS11/)As for the changes in order:
CKA_ID
should be the same for both the private and public key template, but has a finite set of allowed values (covered by the Yubico docs page, and in the source) so you can't just use 20 random bytesCKA_MODIFIABLE
is not a valid attribute for the public or private key templates (although the Yubico docs show it as a supported attribute)CKA_MODULUS_BITS
must be set to 2048 or 1024 for the public key in RSA mode sourceSo something like this ended up working for me:
Also since it looks like you're roughly following the pkcs11interop sample, note that if you call
session.DestroyObject
on the key handles then the cert gets deleted