2

I've learned that I cannot simply transfer a private key to my HSM via PKCS#11, I need to wrap it first and then unwrap it on the HSM. So I temporarily create a DES3 key on our HSM, then I'd like to wrap (encrypt) my RSA private key with it, then I want to unwrap it on the HSM.

My code looks like this:

    // Create temporary DES3 key for wrapping/unwrapping
    var tempKeyAttributes = new List<ObjectAttribute>();
    tempKeyAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
    tempKeyAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
    tempKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
    tempKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true));
    var tempKey = session.GenerateKey(new Mechanism(CKM.CKM_DES3_KEY_GEN), tempKeyAttributes);

    // Encrypt (wrap) the RSA private key
    var encryptedPrivateKeyParamsD = session.Encrypt(new Mechanism(CKM.CKM_DES3_ECB), tempKey, privateKeyParams.D);

    // Define how the new RSA private key should look like on the HSM
    var privateKeyAttributes = new List<ObjectAttribute>();
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
    [...]

    // Unwrap the private key onto the HSM
    var privateKeyHandle = session.UnwrapKey(new Mechanism(CKM.CKM_DES3_ECB), tempKey, encryptedPrivateKeyParamsD, privateKeyAttributes);

This doesn't work, it fails with CKR_INVALID_MECHANISM.

I'm pretty sure the problem is encryptedPrivateKeyParamsD, I should somehow encrypt the whole key instead. But how to? What is the correct format? I can't find anything in the docs about it :-(

Any ideas how to fix this? I simply want to put an existing RSA private key programmatically onto our HSM using PKCS#11.

D.R.
  • 20,268
  • 21
  • 102
  • 205
  • Have you tried to encrypt and unwrap with CBC mode? – always_a_rookie Dec 12 '18 at 14:53
  • For CBC mode I do need some kind of parameters, and I don't know which one to pass in. I'm pretty sure I'm encrypting the wrong stuff. Why should the "D" parameter of my RSAParams be the correct thingy... – D.R. Dec 12 '18 at 16:10

1 Answers1

2

I've found the answer: the format which must be used on SafeNet Luna HSM is PKCS#8 in binary DER encoding. I used BouncyCastle to bring my input data into the correct format:

var unencryptedPrivateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(
        new RsaPrivateCrtKeyParameters(
            new BigInteger(1, privateKeyParams.Modulus),
            new BigInteger(1, privateKeyParams.Exponent),
            new BigInteger(1, privateKeyParams.D),
            new BigInteger(1, privateKeyParams.P),
            new BigInteger(1, privateKeyParams.Q),
            new BigInteger(1, privateKeyParams.DP),
            new BigInteger(1, privateKeyParams.DQ),
            new BigInteger(1, privateKeyParams.InverseQ))).GetEncoded();

var result = new MemoryStream();
session.Encrypt(new Mechanism(CKM.CKM_DES3_CBC_PAD, iv), tempKey, new MemoryStream(unencryptedPrivateKey), result);
var encryptedPrivateKey = result.ToArray();

[...]

var privateKeyHandle = session.UnwrapKey(new Mechanism(CKM.CKM_DES3_CBC_PAD, iv), tempKey, encryptedPrivateKey, privateKeyAttributes);
D.R.
  • 20,268
  • 21
  • 102
  • 205