Search code examples
pkcs#11pkcs11interopamazon-cloudhsm

AWS cloudhsm with PKCS#11 not able to export RSA public key


I am generating a RSA key pair with AWS cloud HSM with PKCS11Interop c# library on top of AWS vendor PKCS library. Wanted to export a public key from HSM with PKCS 11 getAttributeValue methods.

The response states that attributes cannot be read, I have marked all the attributes values correctly to be able to export a key, can somebody point out what I am doing wrong ?

My sample code

private static void GenerateRSAKeyPair(ISession session, out IObjectHandle publicKeyHandle, out IObjectHandle privateKeyHandle, string keyAlias = null)
    {

        byte[] ckaId = null;
        if (string.IsNullOrEmpty(keyAlias))
            ckaId = session.GenerateRandom(20);
        else
            ckaId = Encoding.UTF8.GetBytes(keyAlias);

        // Prepare attribute template of new public key
        List<IObjectAttribute> publicKeyAttributes = new List<IObjectAttribute>();
        publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
        publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
        //publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, false)); // Throws InvalidAttribute Value
        publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
        publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_WRAP, true));
        //publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SENSITIVE, true));
        publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODULUS_BITS, 2048));
        publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }));

        // Prepare attribute template of new private key
        List<IObjectAttribute> privateKeyAttributes = new List<IObjectAttribute>();
        privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
        //privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, true)); 
        //publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SENSITIVE, true));
        privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
        privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_UNWRAP, true));

        // Specify key generation mechanism
        IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_X9_31_KEY_PAIR_GEN);

        // Generate key pair
        session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle);
    }  


private static byte[] GetKeyAttributeValue(ISession session, IObjectHandle keyHandle)
    {
        var readAttrs = session.GetAttributeValue(keyHandle, new List<CKA>() { CKA.CKA_VALUE });
        if (readAttrs[0].CannotBeRead)
            throw new Exception("Key cannot be exported");
        else
            return readAttrs[0].GetValueAsByteArray();
    }

Solution

  • RSA public key objects do not have CKA_VALUE attribute. Instead, there are two attributes called CKA_MODULUS and CKA_PUBLIC_EXPONENT that make up the key value.