/// <summary> /// Creates attribute of given type with ulong array value /// </summary> /// <param name="type">Attribute type</param> /// <param name="value">Attribute value</param> /// <returns>Attribute of given type with ulong array value</returns> public static CK_ATTRIBUTE CreateAttribute(ulong type, ulong[] value) { CK_ATTRIBUTE attribute = new CK_ATTRIBUTE(); attribute.type = type; if ((value != null) && (value.Length > 0)) { int ckmSize = UnmanagedMemory.SizeOf(typeof(ulong)); attribute.value = UnmanagedMemory.Allocate(ckmSize * value.Length); for (int i = 0; i < value.Length; i++) { IntPtr tempPointer = new IntPtr(attribute.value.ToInt64() + (i * ckmSize)); UnmanagedMemory.Write(tempPointer, ConvertUtils.ULongToBytes(value[i])); } attribute.valueLen = Convert.ToUInt64(ckmSize * value.Length); } else { attribute.value = IntPtr.Zero; attribute.valueLen = 0; } return attribute; }
/// <summary> /// Reads value of attribute and returns it as byte array /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out byte[] value) { value = ConvertValue(ref attribute); }
/// <summary> /// Creates attribute of given type with attribute array value /// </summary> /// <param name="type">Attribute type</param> /// <param name="value">Attribute value</param> /// <returns>Attribute of given type with attribute array value</returns> public static CK_ATTRIBUTE CreateAttribute(CKA type, CK_ATTRIBUTE[] value) { return CreateAttribute(Convert.ToUInt64((uint)type), value); }
/// <summary> /// Searches for all token and session objects that match provided attributes /// </summary> /// <param name="attributes">Attributes that should be matched</param> /// <returns>Handles of found objects</returns> public List<ObjectHandle> FindAllObjects(List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); List<ObjectHandle> foundObjects = new List<ObjectHandle>(); CK_ATTRIBUTE[] template = null; ulong templateLength = 0; if (attributes != null) { templateLength = Convert.ToUInt64(attributes.Count); template = new CK_ATTRIBUTE[templateLength]; for (int i = 0; i < Convert.ToInt32(templateLength); i++) template[i] = attributes[i].CkAttribute; } CKR rv = _p11.C_FindObjectsInit(_sessionId, template, templateLength); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_FindObjectsInit", rv); ulong objectsLength = 256; ulong[] objects = new ulong[objectsLength]; ulong objectCount = objectsLength; while (objectCount == objectsLength) { rv = _p11.C_FindObjects(_sessionId, objects, objectsLength, ref objectCount); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_FindObjects", rv); for (int i = 0; i < Convert.ToInt32(objectCount); i++) foundObjects.Add(new ObjectHandle(objects[i])); } rv = _p11.C_FindObjectsFinal(_sessionId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_FindObjectsFinal", rv); return foundObjects; }
/// <summary> /// Reads value of attribute and returns it as bool /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out bool value) { byte[] bytes = ConvertValue(ref attribute); value = ConvertUtils.BytesToBool(bytes); }
/// <summary> /// Reads value of attribute and returns it as bool /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out bool value) { byte[] bytes = ConvertValue(ref attribute); value = ConvertUtils.BytesToBool(bytes); }
/// <summary> /// Modifies the value of one or more attributes of an object /// </summary> /// <param name="objectHandle">Handle of object whose attributes should be modified</param> /// <param name="attributes">List of attributes that should be modified</param> public void SetAttributeValue(ObjectHandle objectHandle, List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); if (attributes == null) throw new ArgumentNullException("attributes"); if (attributes.Count < 1) throw new ArgumentException("No attributes specified", "attributes"); CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[attributes.Count]; for (int i = 0; i < attributes.Count; i++) template[i] = attributes[i].CkAttribute; CKR rv = _p11.C_SetAttributeValue(_sessionId, objectHandle.ObjectId, template, Convert.ToUInt64(template.Length)); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SetAttributeValue", rv); }
/// <summary> /// Initializes a search for token and session objects that match a template /// </summary> /// <param name="session">The session's handle</param> /// <param name="template">Search template that specifies the attribute values to match</param> /// <param name="count">The number of attributes in the search template</param> /// <returns>CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID</returns> public CKR C_FindObjectsInit(ulong session, CK_ATTRIBUTE[] template, ulong count) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); ulong rv = _delegates.C_FindObjectsInit(session, template, count); return (CKR)Convert.ToUInt32(rv); }
public void _01_GetAttributeValueTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) Assert.Inconclusive("Test cannot be executed on this platform"); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) Assert.Fail(rv.ToString()); // Find first slot with token present ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Login as normal user rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Create object ulong objectId = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11, session, ref objectId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Prepare list of empty attributes we want to read CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[2]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_LABEL); template[1] = CkaUtils.CreateAttribute(CKA.CKA_VALUE); // Get size of each individual attribute value in first call rv = pkcs11.C_GetAttributeValue(session, objectId, template, Convert.ToUInt64(template.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // In LowLevelAPI we have to allocate unmanaged memory for attribute value for (int i = 0; i < template.Length; i++) template[i].value = UnmanagedMemory.Allocate(Convert.ToInt32(template[i].valueLen)); // Get attribute value in second call rv = pkcs11.C_GetAttributeValue(session, objectId, template, Convert.ToUInt64(template.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Do something interesting with attribute value byte[] ckaLabel = UnmanagedMemory.Read(template[0].value, Convert.ToInt32(template[0].valueLen)); Assert.IsTrue(Convert.ToBase64String(ckaLabel) == Convert.ToBase64String(Settings.ApplicationNameArray)); // 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; } rv = pkcs11.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); } }
/// <summary> /// Copies an object, creating a new object for the copy /// </summary> /// <param name="session">The session's handle</param> /// <param name="objectId">The object's handle</param> /// <param name="template">Template for the new object</param> /// <param name="count">The number of attributes in the template</param> /// <param name="newObjectId">Location that receives the handle for the copy of the object</param> /// <returns>CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN</returns> public CKR C_CopyObject(ulong session, ulong objectId, CK_ATTRIBUTE[] template, ulong count, ref ulong newObjectId) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); ulong rv = _delegates.C_CopyObject(session, objectId, template, count, ref newObjectId); return (CKR)Convert.ToUInt32(rv); }
/// <summary> /// Modifies the value of one or more attributes of an object /// </summary> /// <param name="session">The session's handle</param> /// <param name="objectId">The object's handle</param> /// <param name="template">Template that specifies which attribute values are to be modified and their new values</param> /// <param name="count">The number of attributes in the template</param> /// <returns>CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN</returns> public CKR C_SetAttributeValue(ulong session, ulong objectId, CK_ATTRIBUTE[] template, ulong count) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); ulong rv = _delegates.C_SetAttributeValue(session, objectId, template, count); return (CKR)Convert.ToUInt32(rv); }
/// <summary> /// Derives a key from a base key, creating a new key object /// </summary> /// <param name="session">The session's handle</param> /// <param name="mechanism">Key derivation mechanism</param> /// <param name="baseKey">The handle of the base key</param> /// <param name="template">The template for the new key</param> /// <param name="attributeCount">The number of attributes in the template</param> /// <param name="key">Location that receives the handle of the derived key</param> /// <returns>CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN</returns> public CKR C_DeriveKey(ulong session, ref CK_MECHANISM mechanism, ulong baseKey, CK_ATTRIBUTE[] template, ulong attributeCount, ref ulong key) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); ulong rv = _delegates.C_DeriveKey(session, ref mechanism, baseKey, template, attributeCount, ref key); return (CKR)Convert.ToUInt32(rv); }
/// <summary> /// Reads value of attribute and returns it as byte array /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out byte[] value) { value = ConvertValue(ref attribute); }
/// <summary> /// Reads value of attribute and returns it as string /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out string value) { byte[] bytes = ConvertValue(ref attribute); value = ConvertUtils.BytesToUtf8String(bytes); }
/// <summary> /// Reads value of attribute and returns it as mechanism array /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out CKM[] value) { ulong[] ulongArray = null; ConvertValue(ref attribute, out ulongArray); CKM[] ckmArray = null; if (ulongArray != null) { ckmArray = new CKM[ulongArray.Length]; for (int i = 0; i < ulongArray.Length; i++) ckmArray[i] = (CKM)Convert.ToUInt32(ulongArray[i]); } value = ckmArray; }
public void _07_AttributeArrayAttributeTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) Assert.Inconclusive("Test cannot be executed on this platform"); CK_ATTRIBUTE[] originalValue = new CK_ATTRIBUTE[2]; originalValue[0] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); originalValue[1] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, true); // Create attribute with attribute array value CK_ATTRIBUTE attr = CkaUtils.CreateAttribute(CKA.CKA_WRAP_TEMPLATE, originalValue); Assert.IsTrue(attr.type == (ulong)CKA.CKA_WRAP_TEMPLATE); Assert.IsTrue(attr.value != IntPtr.Zero); Assert.IsTrue(attr.valueLen == Convert.ToUInt64((UnmanagedMemory.SizeOf(typeof(CK_ATTRIBUTE)) * originalValue.Length))); CK_ATTRIBUTE[] recoveredValue = null; // Read the value of attribute CkaUtils.ConvertValue(ref attr, out recoveredValue); Assert.IsTrue(originalValue.Length == recoveredValue.Length); for (int i = 0; i < recoveredValue.Length; i++) { Assert.IsTrue(originalValue[i].type == recoveredValue[i].type); Assert.IsTrue(originalValue[i].valueLen == recoveredValue[i].valueLen); bool originalBool = false; // Read the value of nested attribute CkaUtils.ConvertValue(ref originalValue[i], out originalBool); bool recoveredBool = true; // Read the value of nested attribute CkaUtils.ConvertValue(ref recoveredValue[i], out recoveredBool); Assert.IsTrue(originalBool == recoveredBool); // In this example there is the same pointer to unmanaged memory // in both originalValue and recoveredValue array therefore it // needs to be freed only once. Assert.IsTrue(originalValue[i].value == recoveredValue[i].value); // Free value of nested attributes UnmanagedMemory.Free(ref originalValue[i].value); originalValue[i].valueLen = 0; recoveredValue[i].value = IntPtr.Zero; recoveredValue[i].valueLen = 0; } // Free attribute value UnmanagedMemory.Free(ref attr.value); attr.valueLen = 0; Assert.IsTrue(attr.type == (ulong)CKA.CKA_WRAP_TEMPLATE); Assert.IsTrue(attr.value == IntPtr.Zero); Assert.IsTrue(attr.valueLen == 0); // Create attribute with null attribute array value attr = CkaUtils.CreateAttribute(CKA.CKA_WRAP_TEMPLATE, (CK_ATTRIBUTE[])null); Assert.IsTrue(attr.type == (ulong)CKA.CKA_WRAP_TEMPLATE); Assert.IsTrue(attr.value == IntPtr.Zero); Assert.IsTrue(attr.valueLen == 0); // Create attribute with empty attribute array value attr = CkaUtils.CreateAttribute(CKA.CKA_WRAP_TEMPLATE, new CK_ATTRIBUTE[0]); Assert.IsTrue(attr.type == (ulong)CKA.CKA_WRAP_TEMPLATE); Assert.IsTrue(attr.value == IntPtr.Zero); Assert.IsTrue(attr.valueLen == 0); }
/// <summary> /// Copies attribute value from unmanaged memory to managed byte array /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <returns>Managed copy of attribute value</returns> private static byte[] ConvertValue(ref CK_ATTRIBUTE attribute) { byte[] value = null; if (attribute.value != IntPtr.Zero) value = UnmanagedMemory.Read(attribute.value, Convert.ToInt32(attribute.valueLen)); return value; }
public void _08_AttributeArrayAttributeTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) { Assert.Inconclusive("Test cannot be executed on this platform"); } ObjectAttribute nestedAttribute1 = new ObjectAttribute(CKA.CKA_TOKEN, true); ObjectAttribute nestedAttribute2 = new ObjectAttribute(CKA.CKA_PRIVATE, true); List <ObjectAttribute> originalValue = new List <ObjectAttribute>(); originalValue.Add(nestedAttribute1); originalValue.Add(nestedAttribute2); // Create attribute with attribute array value using (ObjectAttribute attr = new ObjectAttribute(CKA.CKA_WRAP_TEMPLATE, originalValue)) { Assert.IsTrue(attr.Type == (ulong)CKA.CKA_WRAP_TEMPLATE); List <ObjectAttribute> recoveredValue = attr.GetValueAsObjectAttributeList(); Assert.IsTrue(recoveredValue.Count == 2); Assert.IsTrue(recoveredValue[0].Type == (ulong)CKA.CKA_TOKEN); Assert.IsTrue(recoveredValue[0].GetValueAsBool() == true); Assert.IsTrue(recoveredValue[1].Type == (ulong)CKA.CKA_PRIVATE); Assert.IsTrue(recoveredValue[1].GetValueAsBool() == true); } // There is the same pointer to unmanaged memory in both nestedAttribute1 and recoveredValue[0] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. LLA80.CK_ATTRIBUTE ckAttribute1 = (LLA80.CK_ATTRIBUTE) typeof(ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(nestedAttribute1); ckAttribute1.value = IntPtr.Zero; ckAttribute1.valueLen = 0; typeof(ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(nestedAttribute1, ckAttribute1); // There is the same pointer to unmanaged memory in both nestedAttribute2 and recoveredValue[1] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. LLA80.CK_ATTRIBUTE ckAttribute2 = (LLA80.CK_ATTRIBUTE) typeof(ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(nestedAttribute2); ckAttribute2.value = IntPtr.Zero; ckAttribute2.valueLen = 0; typeof(ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(nestedAttribute2, ckAttribute2); originalValue = null; // Create attribute with null attribute array value using (ObjectAttribute attr = new ObjectAttribute(CKA.CKA_WRAP_TEMPLATE, originalValue)) { Assert.IsTrue(attr.Type == (ulong)CKA.CKA_WRAP_TEMPLATE); Assert.IsTrue(attr.GetValueAsObjectAttributeList() == originalValue); } originalValue = new List <ObjectAttribute>(); // Create attribute with empty attribute array value using (ObjectAttribute attr = new ObjectAttribute(CKA.CKA_WRAP_TEMPLATE, originalValue)) { Assert.IsTrue(attr.Type == (ulong)CKA.CKA_WRAP_TEMPLATE); Assert.IsTrue(attr.GetValueAsObjectAttributeList() == null); } }
/// <summary> /// Obtains the value of one or more attributes of an object /// </summary> /// <param name="objectHandle">Handle of object whose attributes should be read</param> /// <param name="attributes">List of attributes that should be read</param> /// <returns>Object attributes</returns> public List<ObjectAttribute> GetAttributeValue(ObjectHandle objectHandle, List<ulong> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); if (attributes == null) throw new ArgumentNullException("attributes"); if (attributes.Count < 1) throw new ArgumentException("No attributes specified", "attributes"); // Prepare array of CK_ATTRIBUTEs CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[attributes.Count]; for (int i = 0; i < attributes.Count; i++) template[i] = CkaUtils.CreateAttribute(attributes[i]); // Determine size of attribute values CKR rv = _p11.C_GetAttributeValue(_sessionId, objectHandle.ObjectId, template, Convert.ToUInt64(template.Length)); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_ATTRIBUTE_SENSITIVE) && (rv != CKR.CKR_ATTRIBUTE_TYPE_INVALID)) throw new Pkcs11Exception("C_GetAttributeValue", rv); // Allocate memory for each attribute for (int i = 0; i < template.Length; i++) { // PKCS#11 v2.20 page 133: // If the specified attribute (i.e., the attribute specified by the type field) for the object // cannot be revealed because the object is sensitive or unextractable, then the // ulValueLen field in that triple is modified to hold the value -1 (i.e., when it is cast to a // CK_LONG, it holds -1). if ((long)template[i].valueLen != -1) template[i].value = Common.UnmanagedMemory.Allocate(Convert.ToInt32(template[i].valueLen)); } // Read values of attributes rv = _p11.C_GetAttributeValue(_sessionId, objectHandle.ObjectId, template, Convert.ToUInt64(template.Length)); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_ATTRIBUTE_SENSITIVE) && (rv != CKR.CKR_ATTRIBUTE_TYPE_INVALID)) throw new Pkcs11Exception("C_GetAttributeValue", rv); // Convert CK_ATTRIBUTEs to ObjectAttributes List<ObjectAttribute> outAttributes = new List<ObjectAttribute>(); for (int i = 0; i < template.Length; i++) outAttributes.Add(new ObjectAttribute(template[i])); return outAttributes; }
public void _02_GenerateKeyPairTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) Assert.Inconclusive("Test cannot be executed on this platform"); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) Assert.Fail(rv.ToString()); // Find first slot with token present ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Login as normal user rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // The CKA_ID attribute is intended as a means of distinguishing multiple key pairs held by the same subject byte[] ckaId = new byte[20]; rv = pkcs11.C_GenerateRandom(session, ckaId, Convert.ToUInt64(ckaId.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Prepare attribute template of new public key CK_ATTRIBUTE[] pubKeyTemplate = new CK_ATTRIBUTE[10]; pubKeyTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); pubKeyTemplate[1] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, false); pubKeyTemplate[2] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.ApplicationName); pubKeyTemplate[3] = CkaUtils.CreateAttribute(CKA.CKA_ID, ckaId); pubKeyTemplate[4] = CkaUtils.CreateAttribute(CKA.CKA_ENCRYPT, true); pubKeyTemplate[5] = CkaUtils.CreateAttribute(CKA.CKA_VERIFY, true); pubKeyTemplate[6] = CkaUtils.CreateAttribute(CKA.CKA_VERIFY_RECOVER, true); pubKeyTemplate[7] = CkaUtils.CreateAttribute(CKA.CKA_WRAP, true); pubKeyTemplate[8] = CkaUtils.CreateAttribute(CKA.CKA_MODULUS_BITS, 1024); pubKeyTemplate[9] = CkaUtils.CreateAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }); // Prepare attribute template of new private key CK_ATTRIBUTE[] privKeyTemplate = new CK_ATTRIBUTE[9]; privKeyTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); privKeyTemplate[1] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, true); privKeyTemplate[2] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.ApplicationName); privKeyTemplate[3] = CkaUtils.CreateAttribute(CKA.CKA_ID, ckaId); privKeyTemplate[4] = CkaUtils.CreateAttribute(CKA.CKA_SENSITIVE, true); privKeyTemplate[5] = CkaUtils.CreateAttribute(CKA.CKA_DECRYPT, true); privKeyTemplate[6] = CkaUtils.CreateAttribute(CKA.CKA_SIGN, true); privKeyTemplate[7] = CkaUtils.CreateAttribute(CKA.CKA_SIGN_RECOVER, true); privKeyTemplate[8] = CkaUtils.CreateAttribute(CKA.CKA_UNWRAP, true); // Specify key generation mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN); // Generate key pair ulong pubKeyId = CK.CK_INVALID_HANDLE; ulong privKeyId = CK.CK_INVALID_HANDLE; rv = pkcs11.C_GenerateKeyPair(session, ref mechanism, pubKeyTemplate, Convert.ToUInt64(pubKeyTemplate.Length), privKeyTemplate, Convert.ToUInt64(privKeyTemplate.Length), ref pubKeyId, ref privKeyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // In LowLevelAPI we have to free unmanaged memory taken by attributes for (int i = 0; i < privKeyTemplate.Length; i++) { UnmanagedMemory.Free(ref privKeyTemplate[i].value); privKeyTemplate[i].valueLen = 0; } for (int i = 0; i < pubKeyTemplate.Length; i++) { UnmanagedMemory.Free(ref pubKeyTemplate[i].value); pubKeyTemplate[i].valueLen = 0; } // Do something interesting with generated key pair // Destroy object rv = pkcs11.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); } }
/// <summary> /// Initializes a search for token and session objects that match a attributes /// </summary> /// <param name="attributes">Attributes that should be matched</param> public void FindObjectsInit(List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); CK_ATTRIBUTE[] template = null; ulong templateLength = 0; if (attributes != null) { templateLength = Convert.ToUInt64(attributes.Count); template = new CK_ATTRIBUTE[templateLength]; for (int i = 0; i < Convert.ToInt32(templateLength); i++) template[i] = attributes[i].CkAttribute; } CKR rv = _p11.C_FindObjectsInit(_sessionId, template, templateLength); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_FindObjectsInit", rv); }
public void _01_GenerateKeyTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) Assert.Inconclusive("Test cannot be executed on this platform"); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) Assert.Fail(rv.ToString()); // Find first slot with token present ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Login as normal user rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Prepare attribute template of new key CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[4]; 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); // Specify key generation mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_DES3_KEY_GEN); // Generate key ulong keyId = CK.CK_INVALID_HANDLE; rv = pkcs11.C_GenerateKey(session, ref mechanism, template, Convert.ToUInt64(template.Length), ref keyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // 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; } // Do something interesting with generated key // Destroy object rv = pkcs11.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); } }
public void _01_BasicWrapAndUnwrapKeyTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) Assert.Inconclusive("Test cannot be executed on this platform"); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) Assert.Fail(rv.ToString()); // Find first slot with token present ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Login as normal user rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Generate asymetric key pair ulong pubKeyId = CK.CK_INVALID_HANDLE; ulong privKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKeyPair(pkcs11, session, ref pubKeyId, ref privKeyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Generate symetric key ulong keyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11, session, ref keyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Specify wrapping mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_RSA_PKCS); // Get length of wrapped key in first call ulong wrappedKeyLen = 0; rv = pkcs11.C_WrapKey(session, ref mechanism, pubKeyId, keyId, null, ref wrappedKeyLen); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); Assert.IsTrue(wrappedKeyLen > 0); // Allocate array for wrapped key byte[] wrappedKey = new byte[wrappedKeyLen]; // Get wrapped key in second call rv = pkcs11.C_WrapKey(session, ref mechanism, pubKeyId, keyId, wrappedKey, ref wrappedKeyLen); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Do something interesting with wrapped key // Define attributes for unwrapped 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); // Unwrap key ulong unwrappedKeyId = 0; rv = pkcs11.C_UnwrapKey(session, ref mechanism, privKeyId, wrappedKey, wrappedKeyLen, template, Convert.ToUInt64(template.Length), ref unwrappedKeyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Do something interesting with unwrapped key rv = pkcs11.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); } }
public void _01_CreateDestroyObjectTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) Assert.Inconclusive("Test cannot be executed on this platform"); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) Assert.Fail(rv.ToString()); // Find first slot with token present ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Login as normal user rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Prepare attribute template of new data object CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[5]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_DATA); template[1] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); template[2] = CkaUtils.CreateAttribute(CKA.CKA_APPLICATION, Settings.ApplicationName); template[3] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.ApplicationName); template[4] = CkaUtils.CreateAttribute(CKA.CKA_VALUE, "Data object content"); // Create object ulong objectId = CK.CK_INVALID_HANDLE; rv = pkcs11.C_CreateObject(session, template, Convert.ToUInt64(template.Length), ref objectId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // 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; } // Do something interesting with new object // Destroy object rv = pkcs11.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); } }
/// <summary> /// Reads value of attribute and returns it as string /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out string value) { byte[] bytes = ConvertValue(ref attribute); value = ConvertUtils.BytesToUtf8String(bytes); }
public void _08_AttributeArrayAttributeTest() { IObjectAttribute nestedAttribute1 = Settings.Factories.ObjectAttributeFactory.CreateObjectAttribute(CKA.CKA_TOKEN, true); IObjectAttribute nestedAttribute2 = Settings.Factories.ObjectAttributeFactory.CreateObjectAttribute(CKA.CKA_PRIVATE, true); List <IObjectAttribute> originalValue = new List <IObjectAttribute>(); originalValue.Add(nestedAttribute1); originalValue.Add(nestedAttribute2); // Create attribute with attribute array value using (IObjectAttribute attr = Settings.Factories.ObjectAttributeFactory.CreateObjectAttribute(CKA.CKA_WRAP_TEMPLATE, originalValue)) { Assert.IsTrue(attr.Type == ConvertUtils.UInt64FromCKA(CKA.CKA_WRAP_TEMPLATE)); List <IObjectAttribute> recoveredValue = attr.GetValueAsObjectAttributeList(); Assert.IsTrue(recoveredValue.Count == 2); Assert.IsTrue(recoveredValue[0].Type == ConvertUtils.UInt64FromCKA(CKA.CKA_TOKEN)); Assert.IsTrue(recoveredValue[0].GetValueAsBool() == true); Assert.IsTrue(recoveredValue[1].Type == ConvertUtils.UInt64FromCKA(CKA.CKA_PRIVATE)); Assert.IsTrue(recoveredValue[1].GetValueAsBool() == true); } if (Platform.NativeULongSize == 4) { if (Platform.StructPackingSize == 0) { // There is the same pointer to unmanaged memory in both nestedAttribute1 and recoveredValue[0] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. HLA40.ObjectAttribute objectAttribute40a = (HLA40.ObjectAttribute)nestedAttribute1; LLA40.CK_ATTRIBUTE ckAttribute40a = (LLA40.CK_ATTRIBUTE) typeof(HLA40.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectAttribute40a); ckAttribute40a.value = IntPtr.Zero; ckAttribute40a.valueLen = 0; typeof(HLA40.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectAttribute40a, ckAttribute40a); // There is the same pointer to unmanaged memory in both nestedAttribute2 and recoveredValue[1] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. HLA40.ObjectAttribute objectAttribute40b = (HLA40.ObjectAttribute)nestedAttribute2; LLA40.CK_ATTRIBUTE ckAttribute40b = (LLA40.CK_ATTRIBUTE) typeof(HLA40.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectAttribute40b); ckAttribute40b.value = IntPtr.Zero; ckAttribute40b.valueLen = 0; typeof(HLA40.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectAttribute40b, ckAttribute40b); } else { // There is the same pointer to unmanaged memory in both nestedAttribute1 and recoveredValue[0] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. HLA41.ObjectAttribute objectAttribute41a = (HLA41.ObjectAttribute)nestedAttribute1; LLA41.CK_ATTRIBUTE ckAttribute41a = (LLA41.CK_ATTRIBUTE) typeof(HLA41.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectAttribute41a); ckAttribute41a.value = IntPtr.Zero; ckAttribute41a.valueLen = 0; typeof(HLA41.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectAttribute41a, ckAttribute41a); // There is the same pointer to unmanaged memory in both nestedAttribute2 and recoveredValue[1] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. HLA41.ObjectAttribute objectAttribute41b = (HLA41.ObjectAttribute)nestedAttribute2; LLA41.CK_ATTRIBUTE ckAttribute41b = (LLA41.CK_ATTRIBUTE) typeof(HLA41.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectAttribute41b); ckAttribute41b.value = IntPtr.Zero; ckAttribute41b.valueLen = 0; typeof(HLA41.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectAttribute41b, ckAttribute41b); } } else { if (Platform.StructPackingSize == 0) { // There is the same pointer to unmanaged memory in both nestedAttribute1 and recoveredValue[0] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. HLA80.ObjectAttribute objectAttribute80a = (HLA80.ObjectAttribute)nestedAttribute1; LLA80.CK_ATTRIBUTE ckAttribute80a = (LLA80.CK_ATTRIBUTE) typeof(HLA80.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectAttribute80a); ckAttribute80a.value = IntPtr.Zero; ckAttribute80a.valueLen = 0; typeof(HLA80.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectAttribute80a, ckAttribute80a); // There is the same pointer to unmanaged memory in both nestedAttribute2 and recoveredValue[1] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. HLA80.ObjectAttribute objectAttribute80b = (HLA80.ObjectAttribute)nestedAttribute2; LLA80.CK_ATTRIBUTE ckAttribute80b = (LLA80.CK_ATTRIBUTE) typeof(HLA80.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectAttribute80b); ckAttribute80b.value = IntPtr.Zero; ckAttribute80b.valueLen = 0; typeof(HLA80.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectAttribute80b, ckAttribute80b); } else { // There is the same pointer to unmanaged memory in both nestedAttribute1 and recoveredValue[0] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. HLA81.ObjectAttribute objectAttribute81a = (HLA81.ObjectAttribute)nestedAttribute1; LLA81.CK_ATTRIBUTE ckAttribute81a = (LLA81.CK_ATTRIBUTE) typeof(HLA81.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectAttribute81a); ckAttribute81a.value = IntPtr.Zero; ckAttribute81a.valueLen = 0; typeof(HLA81.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectAttribute81a, ckAttribute81a); // There is the same pointer to unmanaged memory in both nestedAttribute2 and recoveredValue[1] instances // therefore private low level attribute structure needs to be modified to prevent double free. // This special handling is needed only in this synthetic test and should be avoided in real world application. HLA81.ObjectAttribute objectAttribute81b = (HLA81.ObjectAttribute)nestedAttribute2; LLA81.CK_ATTRIBUTE ckAttribute81b = (LLA81.CK_ATTRIBUTE) typeof(HLA81.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectAttribute81b); ckAttribute81b.value = IntPtr.Zero; ckAttribute81b.valueLen = 0; typeof(HLA81.ObjectAttribute).GetField("_ckAttribute", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectAttribute81b, ckAttribute81b); } } originalValue = null; // Create attribute with null attribute array value using (IObjectAttribute attr = Settings.Factories.ObjectAttributeFactory.CreateObjectAttribute(CKA.CKA_WRAP_TEMPLATE, originalValue)) { Assert.IsTrue(attr.Type == ConvertUtils.UInt64FromCKA(CKA.CKA_WRAP_TEMPLATE)); Assert.IsTrue(attr.GetValueAsObjectAttributeList() == originalValue); } originalValue = new List <IObjectAttribute>(); // Create attribute with empty attribute array value using (IObjectAttribute attr = Settings.Factories.ObjectAttributeFactory.CreateObjectAttribute(CKA.CKA_WRAP_TEMPLATE, originalValue)) { Assert.IsTrue(attr.Type == ConvertUtils.UInt64FromCKA(CKA.CKA_WRAP_TEMPLATE)); Assert.IsTrue(attr.GetValueAsObjectAttributeList() == null); } }
/// <summary> /// Reads value of attribute and returns it as DateTime (CK_DATE) /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out DateTime? value) { byte[] bytes = ConvertValue(ref attribute); if (bytes.Length == 0) { // PKCS#11 v2.20: // When a Cryptoki object carries an attribute of this type, and the default value of the // attribute is specified to be "empty," then Cryptoki libraries shall set the attribute's ulValueLen to 0. value = null; return; } if ((bytes == null) || (bytes.Length != 8)) throw new Exception("Unable to convert attribute value to DateTime"); string year = ConvertUtils.BytesToUtf8String(bytes, 0, 4); string month = ConvertUtils.BytesToUtf8String(bytes, 4, 2); string day = ConvertUtils.BytesToUtf8String(bytes, 6, 2); if ((year == "0000") && (month == "00") && (day == "00")) { // PKCS#11 v2.20: // Note that implementations of previous versions of Cryptoki may have used other // methods to identify an "empty" attribute of type CK_DATE, and that applications that needs to // interoperate with these libraries therefore have to be flexible in what they accept as an empty value. value = null; return; } value = new DateTime(Int32.Parse(year), Int32.Parse(month), Int32.Parse(day), 0, 0, 0, DateTimeKind.Utc); }
/// <summary> /// Generates a secret key or set of domain parameters, creating a new object /// </summary> /// <param name="mechanism">Generation mechanism</param> /// <param name="attributes">Attributes of the new key or set of domain parameters</param> /// <returns>Handle of the new key or set of domain parameters</returns> public ObjectHandle GenerateKey(Mechanism mechanism, List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CK_ATTRIBUTE[] template = null; ulong templateLength = 0; if (attributes != null) { templateLength = Convert.ToUInt64(attributes.Count); template = new CK_ATTRIBUTE[templateLength]; for (int i = 0; i < Convert.ToInt32(templateLength); i++) template[i] = attributes[i].CkAttribute; } ulong keyId = CK.CK_INVALID_HANDLE; CKR rv = _p11.C_GenerateKey(_sessionId, ref ckMechanism, template, templateLength, ref keyId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_GenerateKey", rv); return new ObjectHandle(keyId); }
/// <summary> /// Reads value of attribute and returns it as attribute array /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out CK_ATTRIBUTE[] value) { int ckAttributeSize = UnmanagedMemory.SizeOf(typeof(CK_ATTRIBUTE)); int attrCount = Convert.ToInt32(attribute.valueLen) / ckAttributeSize; int attrCountMod = Convert.ToInt32(attribute.valueLen) % ckAttributeSize; if (attrCountMod != 0) throw new Exception("Unable to convert attribute value to attribute array"); if (attrCount == 0) { value = null; } else { CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[attrCount]; for (int i = 0; i < attrCount; i++) { IntPtr tempPointer = new IntPtr(attribute.value.ToInt64() + (i * ckAttributeSize)); #if SILVERLIGHT CK_ATTRIBUTE_CLASS attrClass = (CK_ATTRIBUTE_CLASS)UnmanagedMemory.Read(tempPointer, typeof(CK_ATTRIBUTE_CLASS)); attrClass.ToCkAttributeStruct(ref attrs[i]); #else attrs[i] = (CK_ATTRIBUTE)UnmanagedMemory.Read(tempPointer, typeof(CK_ATTRIBUTE)); #endif } value = attrs; } }
/// <summary> /// Generates a public/private key pair, creating new key objects /// </summary> /// <param name="mechanism">Key generation mechanism</param> /// <param name="publicKeyAttributes">Attributes of the public key</param> /// <param name="privateKeyAttributes">Attributes of the private key</param> /// <param name="publicKeyHandle">Handle of the new public key</param> /// <param name="privateKeyHandle">Handle of the new private key</param> public void GenerateKeyPair(Mechanism mechanism, List<ObjectAttribute> publicKeyAttributes, List<ObjectAttribute> privateKeyAttributes, out ObjectHandle publicKeyHandle, out ObjectHandle privateKeyHandle) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CK_ATTRIBUTE[] publicKeyTemplate = null; ulong publicKeyTemplateLength = 0; if (publicKeyAttributes != null) { publicKeyTemplateLength = Convert.ToUInt64(publicKeyAttributes.Count); publicKeyTemplate = new CK_ATTRIBUTE[publicKeyTemplateLength]; for (int i = 0; i < Convert.ToInt32(publicKeyTemplateLength); i++) publicKeyTemplate[i] = publicKeyAttributes[i].CkAttribute; } CK_ATTRIBUTE[] privateKeyTemplate = null; ulong privateKeyTemplateLength = 0; if (privateKeyAttributes != null) { privateKeyTemplateLength = Convert.ToUInt64(privateKeyAttributes.Count); privateKeyTemplate = new CK_ATTRIBUTE[privateKeyTemplateLength]; for (int i = 0; i < Convert.ToInt32(privateKeyTemplateLength); i++) privateKeyTemplate[i] = privateKeyAttributes[i].CkAttribute; } ulong publicKeyId = CK.CK_INVALID_HANDLE; ulong privateKeyId = CK.CK_INVALID_HANDLE; CKR rv = _p11.C_GenerateKeyPair(_sessionId, ref ckMechanism, publicKeyTemplate, publicKeyTemplateLength, privateKeyTemplate, privateKeyTemplateLength, ref publicKeyId, ref privateKeyId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_GenerateKeyPair", rv); publicKeyHandle = new ObjectHandle(publicKeyId); privateKeyHandle = new ObjectHandle(privateKeyId); }
/// <summary> /// Reads value of attribute and returns it as ulong array /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out ulong[] value) { int ckmSize = UnmanagedMemory.SizeOf(typeof(ulong)); int attrCount = Convert.ToInt32(attribute.valueLen) / ckmSize; int attrCountMod = Convert.ToInt32(attribute.valueLen) % ckmSize; if (attrCountMod != 0) throw new Exception("Unable to convert attribute value to ulong array"); if (attrCount == 0) { value = null; } else { ulong[] attrs = new ulong[attrCount]; for (int i = 0; i < attrCount; i++) { IntPtr tempPointer = new IntPtr(attribute.value.ToInt64() + (i * ckmSize)); attrs[i] = ConvertUtils.BytesToULong(UnmanagedMemory.Read(tempPointer, ckmSize)); } value = attrs; } }
/// <summary> /// Derives a key from a base key, creating a new key object /// </summary> /// <param name="mechanism">Derivation mechanism</param> /// <param name="baseKeyHandle">Handle of base key</param> /// <param name="attributes">Attributes for the new key</param> /// <returns>Handle of derived key</returns> public ObjectHandle DeriveKey(Mechanism mechanism, ObjectHandle baseKeyHandle, List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (baseKeyHandle == null) throw new ArgumentNullException("baseKeyHandle"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CK_ATTRIBUTE[] template = null; ulong templateLen = 0; if (attributes != null) { template = new CK_ATTRIBUTE[attributes.Count]; for (int i = 0; i < attributes.Count; i++) template[i] = attributes[i].CkAttribute; templateLen = Convert.ToUInt64(attributes.Count); } ulong derivedKey = CK.CK_INVALID_HANDLE; CKR rv = _p11.C_DeriveKey(_sessionId, ref ckMechanism, baseKeyHandle.ObjectId, template, templateLen, ref derivedKey); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DeriveKey", rv); return new ObjectHandle(derivedKey); }
/// <summary> /// Creates attribute of given type with value copied from managed byte array to the newly allocated unmanaged memory /// </summary> /// <param name="type">Attribute type</param> /// <param name="value">Attribute value</param> /// <returns>Attribute of given type with specified value</returns> private static CK_ATTRIBUTE _CreateAttribute(ulong type, byte[] value) { CK_ATTRIBUTE attribute = new CK_ATTRIBUTE(); attribute.type = type; if (value != null) { attribute.value = UnmanagedMemory.Allocate(value.Length); UnmanagedMemory.Write(attribute.value, value); attribute.valueLen = Convert.ToUInt64(value.Length); } else { attribute.value = IntPtr.Zero; attribute.valueLen = 0; } return attribute; }
/// <summary> /// Copies an object, creating a new object for the copy /// </summary> /// <param name="objectHandle">Handle of object to be copied</param> /// <param name="attributes">New values for any attributes of the object that can ordinarily be modified</param> /// <returns>Handle of copied object</returns> public ObjectHandle CopyObject(ObjectHandle objectHandle, List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); ulong objectId = CK.CK_INVALID_HANDLE; CK_ATTRIBUTE[] template = null; ulong templateLength = 0; if (attributes != null) { templateLength = Convert.ToUInt64(attributes.Count); template = new CK_ATTRIBUTE[templateLength]; for (int i = 0; i < Convert.ToInt32(templateLength); i++) template[i] = attributes[i].CkAttribute; } CKR rv = _p11.C_CopyObject(_sessionId, objectHandle.ObjectId, template, templateLength, ref objectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_CopyObject", rv); return new ObjectHandle(objectId); }
public void _01_BasicObjectFindingTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) Assert.Inconclusive("Test cannot be executed on this platform"); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) Assert.Fail(rv.ToString()); // Find first slot with token present ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Login as normal user rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Let's create two objects so we can find something ulong objectId1 = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11, session, ref objectId1); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); ulong objectId2 = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11, session, ref objectId2); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Prepare attribute template that defines search criteria CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[2]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_DATA); template[1] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); // Initialize searching rv = pkcs11.C_FindObjectsInit(session, template, Convert.ToUInt64(template.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Get search results ulong foundObjectCount = 0; ulong[] foundObjectIds = new ulong[2]; foundObjectIds[0] = CK.CK_INVALID_HANDLE; foundObjectIds[1] = CK.CK_INVALID_HANDLE; rv = pkcs11.C_FindObjects(session, foundObjectIds, Convert.ToUInt64(foundObjectIds.Length), ref foundObjectCount); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Terminate searching rv = pkcs11.C_FindObjectsFinal(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Do something interesting with found objects Assert.IsTrue((foundObjectIds[0] != CK.CK_INVALID_HANDLE) && (foundObjectIds[1] != CK.CK_INVALID_HANDLE)); // 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; } rv = pkcs11.C_DestroyObject(session, objectId2); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_DestroyObject(session, objectId1); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); } }
/// <summary> /// Reads value of attribute and returns it as NativeULong /// </summary> /// <param name="attribute">Attribute whose value should be read</param> /// <param name="value">Location that receives attribute value</param> public static void ConvertValue(ref CK_ATTRIBUTE attribute, out NativeULong value) { byte[] bytes = ConvertValue(ref attribute); value = ConvertUtils.UInt64FromBytes(bytes); }