Search code examples
c#rsapkcs#11pkcs11interop

Import a private key using PKCS#11


We're trying to import an RSA key pair using C# and PKCS#11 into our HSM. Importing the private key using:

    var privateKeyAttributes = new List<ObjectAttribute>();
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, ckaId));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN_RECOVER, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS, privateKeyParams.Modulus));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE_EXPONENT, privateKeyParams.D));
    var privateKeyHandle = session.CreateObject(privateKeyAttributes);

Fails with the error code CKR_TEMPLATE_INCONSISTENT. Unfortunately, it doesn't say what is inconsistent. I tried various other combinations of attributes and it always fails :-(

How to properly import the private key via PKCS#11?


Note: Importing the public key using very similar code works:

    var publicKeyAttributes = new List<ObjectAttribute>();
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, ckaId));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY_RECOVER, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_WRAP, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS, publicKeyParams.Modulus));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, publicKeyParams.Exponent));
    var publicKeyHandle = session.CreateObject(publicKeyAttributes);

Solution

  • The answer is: you can't directly import a private key into a SafeNet Luna HSM. You have to first encrypt (wrap) the private key and can only then transfer it to the HSM. See PKCS#11 unwrap private key to HSM for an answer on how to do this.