From abe21a3f983c8ec9873a7c2c339a71fd46a2cfea Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 28 Apr 2025 22:14:11 +0200 Subject: [PATCH 1/3] Fix comments in encryption/decryption headers Signed-off-by: Jakub Jelen --- cryptoki/src/session/message_decryption.rs | 2 +- cryptoki/src/session/message_encryption.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cryptoki/src/session/message_decryption.rs b/cryptoki/src/session/message_decryption.rs index 1d9bae8b..53de5294 100644 --- a/cryptoki/src/session/message_decryption.rs +++ b/cryptoki/src/session/message_decryption.rs @@ -1,6 +1,6 @@ // Copyright 2025 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 -//! Encrypting data +//! Decrypting messages use crate::context::Function; use crate::error::{Result, Rv}; diff --git a/cryptoki/src/session/message_encryption.rs b/cryptoki/src/session/message_encryption.rs index 5288339a..58b14d6d 100644 --- a/cryptoki/src/session/message_encryption.rs +++ b/cryptoki/src/session/message_encryption.rs @@ -1,6 +1,6 @@ // Copyright 2025 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 -//! Encrypting data +//! Encrypting messages use crate::context::Function; use crate::error::{Result, Rv}; From 1c838633fcf54ea39c81eac9b27b0aae24479b03 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 2 May 2025 14:05:31 +0200 Subject: [PATCH 2/3] eddsa: Fix doc string for EddsaParams Signed-off-by: Jakub Jelen --- cryptoki/src/mechanism/eddsa.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cryptoki/src/mechanism/eddsa.rs b/cryptoki/src/mechanism/eddsa.rs index 0471933a..90d9be7d 100644 --- a/cryptoki/src/mechanism/eddsa.rs +++ b/cryptoki/src/mechanism/eddsa.rs @@ -120,7 +120,7 @@ impl EddsaParams<'_> { /// /// # Arguments /// - /// * `params` - The CK_EDDSA_PARAMS structure. + /// * `scheme` - The EdDSA signature scheme. /// /// # Returns /// From 3188b15dfb66f6b52dabf33cecbe225913e6f3e7 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 29 Apr 2025 10:48:35 +0200 Subject: [PATCH 3/3] Implement message sign/verify functions Signed-off-by: Jakub Jelen --- cryptoki/src/mechanism/mechanism_info.rs | 18 +- cryptoki/src/session/message_signing.rs | 246 +++++++++++++++++++++++ cryptoki/src/session/mod.rs | 1 + 3 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 cryptoki/src/session/message_signing.rs diff --git a/cryptoki/src/mechanism/mechanism_info.rs b/cryptoki/src/mechanism/mechanism_info.rs index d20b957d..9ed89bad 100644 --- a/cryptoki/src/mechanism/mechanism_info.rs +++ b/cryptoki/src/mechanism/mechanism_info.rs @@ -31,6 +31,8 @@ bitflags! { const EC_COMPRESS = CKF_EC_COMPRESS; const MESSAGE_ENCRYPT = CKF_MESSAGE_ENCRYPT; const MESSAGE_DECRYPT = CKF_MESSAGE_DECRYPT; + const MESSAGE_SIGN = CKF_MESSAGE_SIGN; + const MESSAGE_VERIFY = CKF_MESSAGE_VERIFY; const MULTI_MESSAGE = CKF_MULTI_MESSAGE; } } @@ -246,6 +248,20 @@ impl MechanismInfo { self.flags.contains(MechanismInfoFlags::MESSAGE_DECRYPT) } + /// True if the mechanism can be used to sign messages + /// + /// See [`Session::sign_message`](crate::session::Session::sign_message) + pub fn message_sign(&self) -> bool { + self.flags.contains(MechanismInfoFlags::MESSAGE_SIGN) + } + + /// True if the mechanism can be used to verify signed messages + /// + /// See [`Session::decrypt`](crate::session::Session::verify_message) + pub fn message_verify(&self) -> bool { + self.flags.contains(MechanismInfoFlags::MESSAGE_VERIFY) + } + /// True if the mechanism can be used with encrypt/decrypt_message_begin API. /// One of message_* flag must also be set. /// @@ -294,7 +310,7 @@ HW | ENCRYPT | DECRYPT | DIGEST | SIGN | SIGN_RECOVER | VERIFY | \ VERIFY_RECOVER | GENERATE | GENERATE_KEY_PAIR | WRAP | UNWRAP | DERIVE | \ EXTENSION | EC_F_P | EC_F_2M | EC_ECPARAMETERS | EC_NAMEDCURVE | \ EC_OID | EC_UNCOMPRESS | EC_COMPRESS | MESSAGE_ENCRYPT | MESSAGE_DECRYPT | \ -MULTI_MESSAGE"; +MESSAGE_SIGN | MESSAGE_VERIFY | MULTI_MESSAGE"; let all = MechanismInfoFlags::all(); let observed = format!("{all:#?}"); println!("{observed}"); diff --git a/cryptoki/src/session/message_signing.rs b/cryptoki/src/session/message_signing.rs new file mode 100644 index 00000000..67700052 --- /dev/null +++ b/cryptoki/src/session/message_signing.rs @@ -0,0 +1,246 @@ +// Copyright 2025 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +//! Message Signing/Verification and authentication functions + +use crate::context::Function; +use crate::error::{Result, Rv}; +use crate::mechanism::{Mechanism, MessageParam}; +use crate::object::ObjectHandle; +use crate::session::Session; +use cryptoki_sys::*; +use std::convert::TryInto; + +impl Session { + /// Prepare a session for one or more Message-based signature using the same mechanism and key + pub fn message_sign_init(&self, mechanism: &Mechanism, key: ObjectHandle) -> Result<()> { + let mut mechanism: CK_MECHANISM = mechanism.into(); + + unsafe { + Rv::from(get_pkcs11!(self.client(), C_MessageSignInit)( + self.handle(), + &mut mechanism as CK_MECHANISM_PTR, + key.handle(), + )) + .into_result(Function::MessageSignInit)?; + } + + Ok(()) + } + + /// Sign a message in single part + pub fn sign_message(&self, param: &MessageParam, data: &[u8]) -> Result> { + let mut signature_len = 0; + + // Get the output buffer length + unsafe { + Rv::from(get_pkcs11!(self.client(), C_SignMessage)( + self.handle(), + param.as_ptr(), + param.len(), + data.as_ptr() as *mut u8, + data.len().try_into()?, + std::ptr::null_mut(), + &mut signature_len, + )) + .into_result(Function::SignMessage)?; + } + + let mut signature = vec![0; signature_len.try_into()?]; + + unsafe { + Rv::from(get_pkcs11!(self.client(), C_SignMessage)( + self.handle(), + param.as_ptr(), + param.len(), + data.as_ptr() as *mut u8, + data.len().try_into()?, + signature.as_mut_ptr(), + &mut signature_len, + )) + .into_result(Function::SignMessage)?; + } + + signature.resize(signature_len.try_into()?, 0); + + Ok(signature) + } + + /// Begin multi-part message signature operation + pub fn sign_message_begin(&self, param: MessageParam) -> Result<()> { + unsafe { + Rv::from(get_pkcs11!(self.client(), C_SignMessageBegin)( + self.handle(), + param.as_ptr(), + param.len(), + )) + .into_result(Function::SignMessageBegin) + } + } + + /// Continue mutli-part message signature operation + pub fn sign_message_next( + &self, + param: MessageParam, + data: &[u8], + end: bool, + ) -> Result>> { + if !end { + // Just pass in the data + unsafe { + Rv::from(get_pkcs11!(self.client(), C_SignMessageNext)( + self.handle(), + param.as_ptr(), + param.len(), + data.as_ptr() as *mut u8, + data.len().try_into()?, + std::ptr::null_mut(), + std::ptr::null_mut(), + )) + .into_result(Function::SignMessageNext)?; + } + return Ok(None); + } + let mut signature_len = 0; + unsafe { + Rv::from(get_pkcs11!(self.client(), C_SignMessageNext)( + self.handle(), + param.as_ptr(), + param.len(), + data.as_ptr() as *mut u8, + data.len().try_into()?, + std::ptr::null_mut(), + &mut signature_len, + )) + .into_result(Function::SignMessageNext)?; + } + + let mut signature = vec![0; signature_len.try_into()?]; + + unsafe { + Rv::from(get_pkcs11!(self.client(), C_SignMessageNext)( + self.handle(), + param.as_ptr(), + param.len(), + data.as_ptr() as *mut u8, + data.len().try_into()?, + signature.as_mut_ptr(), + &mut signature_len, + )) + .into_result(Function::SignMessageNext)?; + } + + signature.resize(signature_len.try_into()?, 0); + + Ok(Some(signature)) + } + + /// Finalize mutli-part message signature process + pub fn message_sign_final(&self) -> Result<()> { + unsafe { + Rv::from(get_pkcs11!(self.client(), C_MessageSignFinal)( + self.handle(), + )) + .into_result(Function::MessageSignFinal) + } + } + + /// Prepare a session for one or more Message-based verifications using the same mechanism and key + pub fn message_verify_init(&self, mechanism: &Mechanism, key: ObjectHandle) -> Result<()> { + let mut mechanism: CK_MECHANISM = mechanism.into(); + + unsafe { + Rv::from(get_pkcs11!(self.client(), C_MessageVerifyInit)( + self.handle(), + &mut mechanism as CK_MECHANISM_PTR, + key.handle(), + )) + .into_result(Function::MessageVerifyInit)?; + } + + Ok(()) + } + + /// Verify message in single-part + pub fn verify_message( + &self, + param: &MessageParam, + data: &[u8], + signature: &[u8], + ) -> Result<()> { + unsafe { + Rv::from(get_pkcs11!(self.client(), C_VerifyMessage)( + self.handle(), + param.as_ptr(), + param.len(), + data.as_ptr() as *mut u8, + data.len().try_into()?, + signature.as_ptr() as *mut u8, + signature.len().try_into()?, + )) + .into_result(Function::VerifyMessage)?; + } + Ok(()) + } + + /// Begin multi-part message signature verification operation + pub fn verify_message_begin(&self, param: MessageParam) -> Result<()> { + unsafe { + Rv::from(get_pkcs11!(self.client(), C_VerifyMessageBegin)( + self.handle(), + param.as_ptr(), + param.len(), + )) + .into_result(Function::VerifyMessageBegin) + } + } + + /// Continue mutli-part message signature verification operation + pub fn verify_message_next( + &self, + param: MessageParam, + data: &[u8], + signature: Option<&[u8]>, + ) -> Result<()> { + match signature { + None => { + // Just pass in the data + unsafe { + Rv::from(get_pkcs11!(self.client(), C_VerifyMessageNext)( + self.handle(), + param.as_ptr(), + param.len(), + data.as_ptr() as *mut u8, + data.len().try_into()?, + std::ptr::null_mut(), + 0, + )) + .into_result(Function::VerifyMessageNext)?; + } + return Ok(()); + } + Some(s) => unsafe { + Rv::from(get_pkcs11!(self.client(), C_VerifyMessageNext)( + self.handle(), + param.as_ptr(), + param.len(), + data.as_ptr() as *mut u8, + data.len().try_into()?, + s.as_ptr() as *mut u8, + s.len().try_into()?, + )) + .into_result(Function::VerifyMessageNext)?; + }, + } + Ok(()) + } + + /// Finalize mutli-part message signature verification process + pub fn message_verify_final(&self) -> Result<()> { + unsafe { + Rv::from(get_pkcs11!(self.client(), C_MessageVerifyFinal)( + self.handle(), + )) + .into_result(Function::MessageVerifyFinal) + } + } +} diff --git a/cryptoki/src/session/mod.rs b/cryptoki/src/session/mod.rs index bf05fde2..ec3e3110 100644 --- a/cryptoki/src/session/mod.rs +++ b/cryptoki/src/session/mod.rs @@ -14,6 +14,7 @@ mod encryption; mod key_management; mod message_decryption; mod message_encryption; +mod message_signing; mod object_management; mod random; mod session_info;