/// <summary>
/// Generates symetric key.
/// </summary>
/// <param name='pkcs11'>Initialized PKCS11 wrapper</param>
/// <param name='session'>Read-write session with user logged in</param>
/// <param name='keyId'>Output parameter for key object handle</param>
/// <returns>Return value of C_GenerateKey</returns>
public static CKR GenerateKey(Pkcs11 pkcs11, uint session, ref uint keyId)
{
CKR rv = CKR.CKR_OK;
// Prepare attribute template of new key
CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[6];
template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY);
template[1] = CkaUtils.CreateAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3);
template[2] = CkaUtils.CreateAttribute(CKA.CKA_ENCRYPT, true);
template[3] = CkaUtils.CreateAttribute(CKA.CKA_DECRYPT, true);
template[4] = CkaUtils.CreateAttribute(CKA.CKA_DERIVE, true);
template[5] = CkaUtils.CreateAttribute(CKA.CKA_EXTRACTABLE, true);
// Specify key generation mechanism (needs no parameter => no unamanaged memory is needed)
CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_DES3_KEY_GEN);
// Generate key
rv = pkcs11.C_GenerateKey(session, ref mechanism, template, Convert.ToUInt32(template.Length), ref keyId);
// In LowLevelAPI we have to free unmanaged memory taken by attributes
for (int i = 0; i < template.Length; i++)
{
UnmanagedMemory.Free(ref template[i].value);
template[i].valueLen = 0;
}
return rv;
}