/// <summary> /// Signs multi-part data, where the signature is an appendix to the data /// </summary> /// <param name="mechanism">Signature mechanism</param> /// <param name="keyHandle">Signature key</param> /// <param name="inputStream">Input stream from which data should be read</param> /// <returns>Signature</returns> public byte[] Sign(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); return Sign(mechanism, keyHandle, inputStream, 4096); }
/// <summary> /// Decrypts single-part data /// </summary> /// <param name="mechanism">Decryption mechanism</param> /// <param name="keyHandle">Handle of the decryption key</param> /// <param name="encryptedData">Data to be decrypted</param> /// <returns>Decrypted data</returns> public byte[] Decrypt(Mechanism mechanism, ObjectHandle keyHandle, byte[] encryptedData) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (encryptedData == null) throw new ArgumentNullException("encryptedData"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CKR rv = _p11.C_DecryptInit(_sessionId, ref ckMechanism, keyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptInit", rv); ulong decryptedDataLen = 0; rv = _p11.C_Decrypt(_sessionId, encryptedData, Convert.ToUInt64(encryptedData.Length), null, ref decryptedDataLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_Decrypt", rv); byte[] decryptedData = new byte[decryptedDataLen]; rv = _p11.C_Decrypt(_sessionId, encryptedData, Convert.ToUInt64(encryptedData.Length), decryptedData, ref decryptedDataLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_Decrypt", rv); if (decryptedData.Length != Convert.ToInt32(decryptedDataLen)) Array.Resize(ref decryptedData, Convert.ToInt32(decryptedDataLen)); return decryptedData; }
/// <summary> /// Decrypts multi-part data /// </summary> /// <param name="mechanism">Decryption mechanism</param> /// <param name="keyHandle">Handle of the decryption key</param> /// <param name="inputStream">Input stream from which encrypted data should be read</param> /// <param name="outputStream">Output stream where decrypted data should be written</param> /// <param name="bufferLength">Size of read buffer in bytes</param> public void Decrypt(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream, Stream outputStream, int bufferLength) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); if (bufferLength < 1) throw new ArgumentException("Value has to be positive number", "bufferLength"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CKR rv = _p11.C_DecryptInit(_sessionId, ref ckMechanism, keyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptInit", rv); byte[] encryptedPart = new byte[bufferLength]; byte[] part = new byte[bufferLength]; ulong partLen = Convert.ToUInt64(part.Length); int bytesRead = 0; while ((bytesRead = inputStream.Read(encryptedPart, 0, encryptedPart.Length)) > 0) { partLen = Convert.ToUInt64(part.Length); rv = _p11.C_DecryptUpdate(_sessionId, encryptedPart, Convert.ToUInt64(bytesRead), part, ref partLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptUpdate", rv); outputStream.Write(part, 0, Convert.ToInt32(partLen)); } byte[] lastPart = null; ulong lastPartLen = 0; rv = _p11.C_DecryptFinal(_sessionId, null, ref lastPartLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptFinal", rv); lastPart = new byte[lastPartLen]; rv = _p11.C_DecryptFinal(_sessionId, lastPart, ref lastPartLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptFinal", rv); if (lastPartLen > 0) outputStream.Write(lastPart, 0, Convert.ToInt32(lastPartLen)); }
/// <summary> /// Gets the size of an object in bytes. /// </summary> /// <param name="objectHandle">Handle of object</param> /// <returns>Size of an object in bytes</returns> public ulong GetObjectSize(ObjectHandle objectHandle) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); ulong objectSize = 0; CKR rv = _p11.C_GetObjectSize(_sessionId, objectHandle.ObjectId, ref objectSize); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_GetObjectSize", rv); return objectSize; }
/// <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; }
/// <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> /// 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); }
/// <summary> /// Verifies signature of data, where the data can be recovered from the signature /// </summary> /// <param name="mechanism">Verification mechanism;</param> /// <param name="keyHandle">Verification key</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> /// <returns>Data recovered from the signature</returns> public byte[] VerifyRecover(Mechanism mechanism, ObjectHandle keyHandle, byte[] signature, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (signature == null) throw new ArgumentNullException("signature"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CKR rv = _p11.C_VerifyRecoverInit(_sessionId, ref ckMechanism, keyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_VerifyRecoverInit", rv); ulong dataLen = 0; rv = _p11.C_VerifyRecover(_sessionId, signature, Convert.ToUInt64(signature.Length), null, ref dataLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_VerifyRecover", rv); byte[] data = new byte[dataLen]; rv = _p11.C_VerifyRecover(_sessionId, signature, Convert.ToUInt64(signature.Length), data, ref dataLen); if (rv == CKR.CKR_OK) isValid = true; else if (rv == CKR.CKR_SIGNATURE_INVALID) isValid = false; else throw new Pkcs11Exception("C_VerifyRecover", rv); if (data.Length != Convert.ToInt32(dataLen)) Array.Resize(ref data, Convert.ToInt32(dataLen)); return data; }
/// <summary> /// Digests and decrypts data /// </summary> /// <param name="digestingMechanism">Digesting mechanism</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="keyHandle">Handle of the decryption key</param> /// <param name="data">Data to be processed</param> /// <param name="digest">Digest</param> /// <param name="decryptedData">Decrypted data</param> public void DecryptDigest(Mechanism digestingMechanism, Mechanism decryptionMechanism, ObjectHandle keyHandle, byte[] data, out byte[] digest, out byte[] decryptedData) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (digestingMechanism == null) throw new ArgumentNullException("digestingMechanism"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (data == null) throw new ArgumentNullException("data"); using (MemoryStream inputMemoryStream = new MemoryStream(data), outputMemorySteam = new MemoryStream()) { digest = DecryptDigest(digestingMechanism, decryptionMechanism, keyHandle, inputMemoryStream, outputMemorySteam); decryptedData = outputMemorySteam.ToArray(); } }
/// <summary> /// Verifies a signature of data, where the signature is an appendix to the data /// </summary> /// <param name="mechanism">Verification mechanism;</param> /// <param name="keyHandle">Verification key</param> /// <param name="inputStream">Input stream from which data that was signed should be read</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> public void Verify(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream, byte[] signature, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (signature == null) throw new ArgumentNullException("signature"); Verify(mechanism, keyHandle, inputStream, signature, out isValid, 4096); }
/// <summary> /// Verifies a signature of data, where the signature is an appendix to the data /// </summary> /// <param name="mechanism">Verification mechanism;</param> /// <param name="keyHandle">Verification key</param> /// <param name="inputStream">Input stream from which data that was signed should be read</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> /// <param name="bufferLength">Size of read buffer in bytes</param> public void Verify(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream, byte[] signature, out bool isValid, int bufferLength) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (signature == null) throw new ArgumentNullException("signature"); if (bufferLength < 1) throw new ArgumentException("Value has to be positive number", "bufferLength"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CKR rv = _p11.C_VerifyInit(_sessionId, ref ckMechanism, keyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_VerifyInit", rv); byte[] part = new byte[bufferLength]; int bytesRead = 0; while ((bytesRead = inputStream.Read(part, 0, part.Length)) > 0) { rv = _p11.C_VerifyUpdate(_sessionId, part, Convert.ToUInt64(bytesRead)); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_VerifyUpdate", rv); } rv = _p11.C_VerifyFinal(_sessionId, signature, Convert.ToUInt64(signature.Length)); if (rv == CKR.CKR_OK) isValid = true; else if (rv == CKR.CKR_SIGNATURE_INVALID) isValid = false; else throw new Pkcs11Exception("C_VerifyFinal", rv); }
/// <summary> /// Verifies a signature of data, where the signature is an appendix to the data /// </summary> /// <param name="mechanism">Verification mechanism;</param> /// <param name="keyHandle">Verification key</param> /// <param name="data">Data that was signed</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> public void Verify(Mechanism mechanism, ObjectHandle keyHandle, byte[] data, byte[] signature, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (data == null) throw new ArgumentNullException("data"); if (signature == null) throw new ArgumentNullException("signature"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CKR rv = _p11.C_VerifyInit(_sessionId, ref ckMechanism, keyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_VerifyInit", rv); rv = _p11.C_Verify(_sessionId, data, Convert.ToUInt64(data.Length), signature, Convert.ToUInt64(signature.Length)); if (rv == CKR.CKR_OK) isValid = true; else if (rv == CKR.CKR_SIGNATURE_INVALID) isValid = false; else throw new Pkcs11Exception("C_Verify", rv); }
/// <summary> /// Signs single-part data, where the data can be recovered from the signature /// </summary> /// <param name="mechanism">Signature mechanism</param> /// <param name="keyHandle">Signature key</param> /// <param name="data">Data to be signed</param> /// <returns>Signature</returns> public byte[] SignRecover(Mechanism mechanism, ObjectHandle keyHandle, byte[] data) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (data == null) throw new ArgumentNullException("data"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CKR rv = _p11.C_SignRecoverInit(_sessionId, ref ckMechanism, keyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignRecoverInit", rv); ulong signatureLen = 0; rv = _p11.C_SignRecover(_sessionId, data, Convert.ToUInt64(data.Length), null, ref signatureLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignRecover", rv); byte[] signature = new byte[signatureLen]; rv = _p11.C_SignRecover(_sessionId, data, Convert.ToUInt64(data.Length), signature, ref signatureLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignRecover", rv); if (signature.Length != Convert.ToInt32(signatureLen)) Array.Resize(ref signature, Convert.ToInt32(signatureLen)); return signature; }
/// <summary> /// Signs multi-part data, where the signature is an appendix to the data /// </summary> /// <param name="mechanism">Signature mechanism</param> /// <param name="keyHandle">Signature key</param> /// <param name="inputStream">Input stream from which data should be read</param> /// <param name="bufferLength">Size of read buffer in bytes</param> /// <returns>Signature</returns> public byte[] Sign(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream, int bufferLength) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (bufferLength < 1) throw new ArgumentException("Value has to be positive number", "bufferLength"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CKR rv = _p11.C_SignInit(_sessionId, ref ckMechanism, keyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignInit", rv); byte[] part = new byte[bufferLength]; int bytesRead = 0; while ((bytesRead = inputStream.Read(part, 0, part.Length)) > 0) { rv = _p11.C_SignUpdate(_sessionId, part, Convert.ToUInt64(bytesRead)); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignUpdate", rv); } ulong signatureLen = 0; rv = _p11.C_SignFinal(_sessionId, null, ref signatureLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignFinal", rv); byte[] signature = new byte[signatureLen]; rv = _p11.C_SignFinal(_sessionId, signature, ref signatureLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignFinal", rv); if (signature.Length != Convert.ToInt32(signatureLen)) Array.Resize(ref signature, Convert.ToInt32(signatureLen)); return signature; }
/// <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> /// Digests and decrypts data /// </summary> /// <param name="digestingMechanism">Digesting mechanism</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="keyHandle">Handle of the decryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where decrypted data should be written</param> /// <returns>Digest</returns> public byte[] DecryptDigest(Mechanism digestingMechanism, Mechanism decryptionMechanism, ObjectHandle keyHandle, Stream inputStream, Stream outputStream) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (digestingMechanism == null) throw new ArgumentNullException("digestingMechanism"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); return DecryptDigest(digestingMechanism, decryptionMechanism, keyHandle, inputStream, outputStream, 4096); }
/// <summary> /// Wraps (i.e., encrypts) a private or secret key /// </summary> /// <param name="mechanism">Wrapping mechanism</param> /// <param name="wrappingKeyHandle">Handle of wrapping key</param> /// <param name="keyHandle">Handle of key to be wrapped</param> /// <returns>Wrapped key</returns> public byte[] WrapKey(Mechanism mechanism, ObjectHandle wrappingKeyHandle, ObjectHandle keyHandle) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (wrappingKeyHandle == null) throw new ArgumentNullException("wrappingKeyHandle"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; ulong wrappedKeyLen = 0; CKR rv = _p11.C_WrapKey(_sessionId, ref ckMechanism, wrappingKeyHandle.ObjectId, keyHandle.ObjectId, null, ref wrappedKeyLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_WrapKey", rv); byte[] wrappedKey = new byte[wrappedKeyLen]; rv = _p11.C_WrapKey(_sessionId, ref ckMechanism, wrappingKeyHandle.ObjectId, keyHandle.ObjectId, wrappedKey, ref wrappedKeyLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_WrapKey", rv); if (wrappedKey.Length != Convert.ToInt32(wrappedKeyLen)) Array.Resize(ref wrappedKey, Convert.ToInt32(wrappedKeyLen)); return wrappedKey; }
/// <summary> /// Signs and encrypts data /// </summary> /// <param name="signingMechanism">Signing mechanism</param> /// <param name="signingKeyHandle">Handle of the signing key</param> /// <param name="encryptionMechanism">Encryption mechanism</param> /// <param name="encryptionKeyHandle">Handle of the encryption key</param> /// <param name="data">Data to be processed</param> /// <param name="signature">Signature</param> /// <param name="encryptedData">Encrypted data</param> public void SignEncrypt(Mechanism signingMechanism, ObjectHandle signingKeyHandle, Mechanism encryptionMechanism, ObjectHandle encryptionKeyHandle, byte[] data, out byte[] signature, out byte[] encryptedData) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (signingMechanism == null) throw new ArgumentNullException("signingMechanism"); if (signingKeyHandle == null) throw new ArgumentNullException("signingKeyHandle"); if (encryptionMechanism == null) throw new ArgumentNullException("encryptionMechanism"); if (encryptionKeyHandle == null) throw new ArgumentNullException("encryptionKeyHandle"); if (data == null) throw new ArgumentNullException("data"); using (MemoryStream inputMemoryStream = new MemoryStream(data), outputMemorySteam = new MemoryStream()) { signature = SignEncrypt(signingMechanism, signingKeyHandle, encryptionMechanism, encryptionKeyHandle, inputMemoryStream, outputMemorySteam); encryptedData = outputMemorySteam.ToArray(); } }
/// <summary> /// Restores the cryptographic operations state of a session from an array of bytes obtained with GetOperationState /// </summary> /// <param name="state">Array of bytes obtained with GetOperationState</param> /// <param name="encryptionKey">CK_INVALID_HANDLE or handle to the key which will be used for an ongoing encryption or decryption operation in the restored session</param> /// <param name="authenticationKey">CK_INVALID_HANDLE or handle to the key which will be used for an ongoing signature, MACing, or verification operation in the restored session</param> public void SetOperationState(byte[] state, ObjectHandle encryptionKey, ObjectHandle authenticationKey) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (state == null) throw new ArgumentNullException("state"); if (encryptionKey == null) throw new ArgumentNullException("encryptionKey"); if (authenticationKey == null) throw new ArgumentNullException("authenticationKey"); CKR rv = _p11.C_SetOperationState(_sessionId, state, Convert.ToUInt64(state.Length), encryptionKey.ObjectId, authenticationKey.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SetOperationState", rv); }
/// <summary> /// Signs and encrypts data /// </summary> /// <param name="signingMechanism">Signing mechanism</param> /// <param name="signingKeyHandle">Handle of the signing key</param> /// <param name="encryptionMechanism">Encryption mechanism</param> /// <param name="encryptionKeyHandle">Handle of the encryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where encrypted data should be written</param> /// <returns>Signature</returns> public byte[] SignEncrypt(Mechanism signingMechanism, ObjectHandle signingKeyHandle, Mechanism encryptionMechanism, ObjectHandle encryptionKeyHandle, Stream inputStream, Stream outputStream) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (signingMechanism == null) throw new ArgumentNullException("signingMechanism"); if (signingKeyHandle == null) throw new ArgumentNullException("signingKeyHandle"); if (encryptionMechanism == null) throw new ArgumentNullException("encryptionMechanism"); if (encryptionKeyHandle == null) throw new ArgumentNullException("encryptionKeyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); return SignEncrypt(signingMechanism, signingKeyHandle, encryptionMechanism, encryptionKeyHandle, inputStream, outputStream, 4096); }
/// <summary> /// Destroys an object /// </summary> /// <param name="objectHandle">Handle of object to be destroyed</param> public void DestroyObject(ObjectHandle objectHandle) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); CKR rv = _p11.C_DestroyObject(_sessionId, objectHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DestroyObject", rv); }
/// <summary> /// Signs and encrypts data /// </summary> /// <param name="signingMechanism">Signing mechanism</param> /// <param name="signingKeyHandle">Handle of the signing key</param> /// <param name="encryptionMechanism">Encryption mechanism</param> /// <param name="encryptionKeyHandle">Handle of the encryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where encrypted data should be written</param> /// <param name="bufferLength">Size of read buffer in bytes</param> /// <returns>Signature</returns> public byte[] SignEncrypt(Mechanism signingMechanism, ObjectHandle signingKeyHandle, Mechanism encryptionMechanism, ObjectHandle encryptionKeyHandle, Stream inputStream, Stream outputStream, int bufferLength) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (signingMechanism == null) throw new ArgumentNullException("signingMechanism"); if (signingKeyHandle == null) throw new ArgumentNullException("signingKeyHandle"); if (encryptionMechanism == null) throw new ArgumentNullException("encryptionMechanism"); if (encryptionKeyHandle == null) throw new ArgumentNullException("encryptionKeyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); if (bufferLength < 1) throw new ArgumentException("Value has to be positive number", "bufferLength"); CK_MECHANISM ckSigningMechanism = signingMechanism.CkMechanism; CKR rv = _p11.C_SignInit(_sessionId, ref ckSigningMechanism, signingKeyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignInit", rv); CK_MECHANISM ckEncryptionMechanism = encryptionMechanism.CkMechanism; rv = _p11.C_EncryptInit(_sessionId, ref ckEncryptionMechanism, encryptionKeyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_EncryptInit", rv); byte[] part = new byte[bufferLength]; byte[] encryptedPart = new byte[bufferLength]; ulong encryptedPartLen = Convert.ToUInt64(encryptedPart.Length); int bytesRead = 0; while ((bytesRead = inputStream.Read(part, 0, part.Length)) > 0) { encryptedPartLen = Convert.ToUInt64(encryptedPart.Length); rv = _p11.C_SignEncryptUpdate(_sessionId, part, Convert.ToUInt64(bytesRead), encryptedPart, ref encryptedPartLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignEncryptUpdate", rv); outputStream.Write(encryptedPart, 0, Convert.ToInt32(encryptedPartLen)); } byte[] lastEncryptedPart = null; ulong lastEncryptedPartLen = 0; rv = _p11.C_EncryptFinal(_sessionId, null, ref lastEncryptedPartLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_EncryptFinal", rv); lastEncryptedPart = new byte[lastEncryptedPartLen]; rv = _p11.C_EncryptFinal(_sessionId, lastEncryptedPart, ref lastEncryptedPartLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_EncryptFinal", rv); if (lastEncryptedPartLen > 0) outputStream.Write(lastEncryptedPart, 0, Convert.ToInt32(lastEncryptedPartLen)); ulong signatureLen = 0; rv = _p11.C_SignFinal(_sessionId, null, ref signatureLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignFinal", rv); byte[] signature = new byte[signatureLen]; rv = _p11.C_SignFinal(_sessionId, signature, ref signatureLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_SignFinal", rv); if (signature.Length != Convert.ToInt32(signatureLen)) Array.Resize(ref signature, Convert.ToInt32(signatureLen)); return signature; }
/// <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<CKA> 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"); List<ulong> ulongAttributes = new List<ulong>(); foreach (CKA attribute in attributes) ulongAttributes.Add(Convert.ToUInt64((uint)attribute)); return GetAttributeValue(objectHandle, ulongAttributes); }
/// <summary> /// Decrypts data and verifies a signature of data /// </summary> /// <param name="verificationMechanism">Verification mechanism</param> /// <param name="verificationKeyHandle">Handle of the verification key</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="decryptionKeyHandle">Handle of the decryption key</param> /// <param name="data">Data to be processed</param> /// <param name="signature">Signature</param> /// <param name="decryptedData">Decrypted data</param> /// <param name="isValid">Flag indicating whether signature is valid</param> public void DecryptVerify(Mechanism verificationMechanism, ObjectHandle verificationKeyHandle, Mechanism decryptionMechanism, ObjectHandle decryptionKeyHandle, byte[] data, byte[] signature, out byte[] decryptedData, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (verificationMechanism == null) throw new ArgumentNullException("verificationMechanism"); if (verificationKeyHandle == null) throw new ArgumentNullException("verificationKeyHandle"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (decryptionKeyHandle == null) throw new ArgumentNullException("decryptionKeyHandle"); if (data == null) throw new ArgumentNullException("data"); if (signature == null) throw new ArgumentNullException("signature"); using (MemoryStream inputMemoryStream = new MemoryStream(data), outputMemorySteam = new MemoryStream()) { DecryptVerify(verificationMechanism, verificationKeyHandle, decryptionMechanism, decryptionKeyHandle, inputMemoryStream, outputMemorySteam, signature, out isValid); decryptedData = outputMemorySteam.ToArray(); } }
/// <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> /// Decrypts data and verifies a signature of data /// </summary> /// <param name="verificationMechanism">Verification mechanism</param> /// <param name="verificationKeyHandle">Handle of the verification key</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="decryptionKeyHandle">Handle of the decryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where decrypted data should be written</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> public void DecryptVerify(Mechanism verificationMechanism, ObjectHandle verificationKeyHandle, Mechanism decryptionMechanism, ObjectHandle decryptionKeyHandle, Stream inputStream, Stream outputStream, byte[] signature, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (verificationMechanism == null) throw new ArgumentNullException("verificationMechanism"); if (verificationKeyHandle == null) throw new ArgumentNullException("verificationKeyHandle"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (decryptionKeyHandle == null) throw new ArgumentNullException("decryptionKeyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); if (signature == null) throw new ArgumentNullException("signature"); DecryptVerify(verificationMechanism, verificationKeyHandle, decryptionMechanism, decryptionKeyHandle, inputStream, outputStream, signature, out isValid, 4096); }
/// <summary> /// Decrypts multi-part data /// </summary> /// <param name="mechanism">Decryption mechanism</param> /// <param name="keyHandle">Handle of the decryption key</param> /// <param name="inputStream">Input stream from which encrypted data should be read</param> /// <param name="outputStream">Output stream where decrypted data should be written</param> public void Decrypt(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream, Stream outputStream) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); Decrypt(mechanism, keyHandle, inputStream, outputStream, 4096); }
/// <summary> /// Decrypts data and verifies a signature of data /// </summary> /// <param name="verificationMechanism">Verification mechanism</param> /// <param name="verificationKeyHandle">Handle of the verification key</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="decryptionKeyHandle">Handle of the decryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where decrypted data should be written</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> /// <param name="bufferLength">Size of read buffer in bytes</param> public void DecryptVerify(Mechanism verificationMechanism, ObjectHandle verificationKeyHandle, Mechanism decryptionMechanism, ObjectHandle decryptionKeyHandle, Stream inputStream, Stream outputStream, byte[] signature, out bool isValid, int bufferLength) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (verificationMechanism == null) throw new ArgumentNullException("verificationMechanism"); if (verificationKeyHandle == null) throw new ArgumentNullException("verificationKeyHandle"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (decryptionKeyHandle == null) throw new ArgumentNullException("decryptionKeyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); if (signature == null) throw new ArgumentNullException("signature"); if (bufferLength < 1) throw new ArgumentException("Value has to be positive number", "bufferLength"); CK_MECHANISM ckVerificationMechanism = verificationMechanism.CkMechanism; CKR rv = _p11.C_VerifyInit(_sessionId, ref ckVerificationMechanism, verificationKeyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_VerifyInit", rv); CK_MECHANISM ckDecryptionMechanism = decryptionMechanism.CkMechanism; rv = _p11.C_DecryptInit(_sessionId, ref ckDecryptionMechanism, decryptionKeyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptInit", rv); byte[] encryptedPart = new byte[bufferLength]; byte[] part = new byte[bufferLength]; ulong partLen = Convert.ToUInt64(part.Length); int bytesRead = 0; while ((bytesRead = inputStream.Read(encryptedPart, 0, encryptedPart.Length)) > 0) { partLen = Convert.ToUInt64(part.Length); rv = _p11.C_DecryptVerifyUpdate(_sessionId, encryptedPart, Convert.ToUInt64(bytesRead), part, ref partLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptVerifyUpdate", rv); outputStream.Write(part, 0, Convert.ToInt32(partLen)); } byte[] lastPart = null; ulong lastPartLen = 0; rv = _p11.C_DecryptFinal(_sessionId, null, ref lastPartLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptFinal", rv); lastPart = new byte[lastPartLen]; rv = _p11.C_DecryptFinal(_sessionId, lastPart, ref lastPartLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DecryptFinal", rv); if (lastPartLen > 0) outputStream.Write(lastPart, 0, Convert.ToInt32(lastPartLen)); rv = _p11.C_VerifyFinal(_sessionId, signature, Convert.ToUInt64(signature.Length)); if (rv == CKR.CKR_OK) isValid = true; else if (rv == CKR.CKR_SIGNATURE_INVALID) isValid = false; else throw new Pkcs11Exception("C_VerifyFinal", rv); }
/// <summary> /// Digests the value of a secret key /// </summary> /// <param name="mechanism">Digesting mechanism</param> /// <param name="keyHandle">Handle of the secret key to be digested</param> /// <returns>Digest</returns> public byte[] DigestKey(Mechanism mechanism, ObjectHandle keyHandle) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); CK_MECHANISM ckMechanism = mechanism.CkMechanism; CKR rv = _p11.C_DigestInit(_sessionId, ref ckMechanism); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DigestInit", rv); rv = _p11.C_DigestKey(_sessionId, keyHandle.ObjectId); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DigestKey", rv); ulong digestLen = 0; rv = _p11.C_DigestFinal(_sessionId, null, ref digestLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DigestFinal", rv); byte[] digest = new byte[digestLen]; rv = _p11.C_DigestFinal(_sessionId, digest, ref digestLen); if (rv != CKR.CKR_OK) throw new Pkcs11Exception("C_DigestFinal", rv); if (digest.Length != Convert.ToInt32(digestLen)) Array.Resize(ref digest, Convert.ToInt32(digestLen)); return digest; }
/// <summary> /// Generates asymetric key pair. /// </summary> /// <param name='session'>Read-write session with user logged in</param> /// <param name='publicKeyHandle'>Output parameter for public key object handle</param> /// <param name='privateKeyHandle'>Output parameter for private key object handle</param> public static void GenerateKeyPair(Session session, out ObjectHandle publicKeyHandle, out ObjectHandle privateKeyHandle) { // The CKA_ID attribute is intended as a means of distinguishing multiple key pairs held by the same subject byte[] ckaId = session.GenerateRandom(20); // Prepare attribute template of new public key List<ObjectAttribute> publicKeyAttributes = new List<ObjectAttribute>(); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, Settings.ApplicationName)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY_RECOVER, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_WRAP, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS_BITS, 1024)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 })); // Prepare attribute template of new private key List<ObjectAttribute> privateKeyAttributes = new List<ObjectAttribute>(); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, Settings.ApplicationName)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN_RECOVER, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true)); // Specify key generation mechanism Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN); // Generate key pair session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle); }