Search code examples
keyhsmpkcs11interopncryptoki

Pkcs11Interop read key value from HSM


I'm trying to use Pkcs11Interop to extract the value of the key from the HSM. I know, the key has to stay in the HSM, but I need it, so...

I already do it with NCryptoki and I'd like to do it also with Pkcs11Interop

I tried this code:

// Prepare attribute template that defines search criteria
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "MY_KEY"));

// Find all objects that match provided attributes
List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes);

var key = foundObjects[0];
 byte[] plainKeyValue = null;
 List<ObjectAttribute> readAttrs = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_VALUE });
 if (readAttrs[0].CannotBeRead)
     throw new Exception("Key cannot be exported");
 else
     plainKeyValue = readAttrs[0].GetValueAsByteArray();

But the plainKeyValue is all zeros, but, as you can imagine, this is not true.

SO, how can I reach my goal?


Solution

  • I solved it with this code

    static public byte[] findTargetKeySValue(String label, String type, string command)
    {
        try
        {
            string pkcs11LibraryPath = @"C:\Program Files\SafeNet\Protect Toolkit 5\Protect Toolkit C SDK\bin\hsm\cryptoki.dll";
            Utility.Logger("cryptoki dll path " + pkcs11LibraryPath, command);
            using (Pkcs11 pkcs11 = new Pkcs11(pkcs11LibraryPath, Inter_Settings.AppType))
            {
                // Find first slot with token present
                Slot slot = Inter_Helpers.GetUsableSlot(pkcs11);
                // Open RW session
                using (Session session = slot.OpenSession(SessionType.ReadOnly))
                {
                    // Login as normal user
                    session.Login(CKU.CKU_USER, Inter_Settings.NormalUserPin);
                    // Prepare attribute template that defines search criteria
                    List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
                    objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
                    if (type == "DES")
                        objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES));
                    else if (type == "DES2")
                        objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES2));
                    else if (type == "DES3")
                        objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
                    objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, label));//PROVAK
    
                    List<ObjectHandle> foundObjects = session.FindAllObjects(objectAttributes);
                    var key = foundObjects[0];
                    byte[] plainKeyValue = null;
                    List<ObjectAttribute> readAttrsSensitive = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_SENSITIVE });
                    if (!readAttrsSensitive[0].GetValueAsBool())
                    {
                        Utility.Logger("findTargetKeySValue chiave " + label + " non senstive", command);
                        List<ObjectAttribute> readAttrs = session.GetAttributeValue(key, new List<CKA>() { CKA.CKA_VALUE });
                        if (readAttrs[0].CannotBeRead)
                            throw new Exception("Key cannot be exported");
                        else
                            plainKeyValue = readAttrs[0].GetValueAsByteArray();
                        //Console.WriteLine(ByteArrayToAsciiHEX(plainKeyValue));
                        session.Logout();
                        return plainKeyValue;
                    }
                    else
                    {
                        Utility.Logger("findTargetKeySValue chiave " + label + " senstive", command);
                        Console.WriteLine("wrap/unwrap");
                        objectAttributes = new List<ObjectAttribute>();
                        objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
                        objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
                        objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "WRAPPING_KEY")); //WRAPPING_KEY WRK
                        foundObjects = session.FindAllObjects(objectAttributes);
    
                        var wrappingKey = foundObjects[0];
                        Mechanism m = new Mechanism(CKM.CKM_DES3_ECB);
    
                        var wrapped = session.WrapKey(m, wrappingKey, key);
                        //Console.WriteLine("wrapped " + ByteArrayToAsciiHEX(wrapped));
    
                        //Console.WriteLine(ByteArrayToAsciiHEX(session.Decrypt(m, wrappingKey, wrapped)));
                        var k = session.Decrypt(m, wrappingKey, wrapped); 
                        session.Logout();
                        return k;
    
                    }
                }
            }
        }
        catch (Exception e)
        {
            //Console.WriteLine(e.ToSafeString());
            Utility.Logger("findTargetKeySValue " + e.ToSafeString(), command);
            return null;
        }
    }