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 /// 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_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}; 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;