>,
}
impl Pkcs11 {
/// Instantiate a new context from the path of a PKCS11 dynamic library implementation.
pub fn new(filename: P) -> Result
where
P: AsRef,
{
unsafe {
let pkcs11_lib =
cryptoki_sys::Pkcs11::new(filename.as_ref()).map_err(Error::LibraryLoading)?;
let mut list = mem::MaybeUninit::uninit();
Rv::from(pkcs11_lib.C_GetFunctionList(list.as_mut_ptr())).into_result()?;
let list_ptr = *list.as_ptr();
Ok(Pkcs11 {
impl_: Arc::new(Pkcs11Impl {
_pkcs11_lib: pkcs11_lib,
function_list: *list_ptr,
}),
initialized: Arc::new(RwLock::new(false)),
})
}
}
/// Initialize the PKCS11 library
pub fn initialize(&self, init_args: CInitializeArgs) -> Result<()> {
let mut init_lock = self
.initialized
.as_ref()
.write()
.expect("lock not to be poisoned");
if *init_lock {
Err(Error::AlreadyInitialized)?
}
initialize(self, init_args).map(|_| *init_lock = true)
}
/// Check whether the PKCS11 library has been initialized
pub fn is_initialized(&self) -> bool {
*self
.initialized
.as_ref()
.read()
.expect("lock not to be poisoned")
}
/// Finalize the PKCS11 library. Indicates that the application no longer needs to use PKCS11.
/// The library is also automatically finalized on drop.
pub fn finalize(self) {}
/// Returns the information about the library
pub fn get_library_info(&self) -> Result {
get_library_info(self)
}
/// Check whether a given PKCS11 spec-defined function is supported by this implementation
pub fn is_fn_supported(&self, function: Function) -> bool {
is_fn_supported(self, function)
}
}
cryptoki-0.6.1/src/context/session_management.rs 0000644 0000000 0000000 00000003032 10461020230 0020172 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Session management functions
use cryptoki_sys::{CKF_RW_SESSION, CKF_SERIAL_SESSION};
use crate::context::Pkcs11;
use crate::error::{Result, Rv};
use crate::session::Session;
use crate::slot::Slot;
use std::convert::TryInto;
impl Pkcs11 {
#[inline(always)]
fn open_session(&self, slot_id: Slot, read_write: bool) -> Result {
let mut session_handle = 0;
let flags = if read_write {
CKF_SERIAL_SESSION | CKF_RW_SESSION
} else {
CKF_SERIAL_SESSION
};
unsafe {
Rv::from(get_pkcs11!(self, C_OpenSession)(
slot_id.try_into()?,
flags,
// TODO: abstract those types or create new functions for callbacks
std::ptr::null_mut(),
None,
&mut session_handle,
))
.into_result()?;
}
Ok(Session::new(session_handle, self.clone()))
}
/// Open a new Read-Only session
///
/// For a Read-Write session, use `open_rw_session`
///
/// Note: No callback is set when opening the session.
pub fn open_ro_session(&self, slot_id: Slot) -> Result {
self.open_session(slot_id, false)
}
/// Open a new Read/Write session
///
/// Note: No callback is set when opening the session.
pub fn open_rw_session(&self, slot_id: Slot) -> Result {
self.open_session(slot_id, true)
}
}
cryptoki-0.6.1/src/context/slot_token_management.rs 0000644 0000000 0000000 00000014604 10461020230 0020677 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Slot and token management functions
use crate::error::{Result, Rv};
use crate::label_from_str;
use crate::mechanism::{MechanismInfo, MechanismType};
use crate::slot::{Slot, SlotInfo, TokenInfo};
use crate::types::AuthPin;
use crate::{
context::Pkcs11,
error::{Error, RvError},
};
use cryptoki_sys::{
CKF_DONT_BLOCK, CK_BBOOL, CK_FALSE, CK_FLAGS, CK_MECHANISM_INFO, CK_SLOT_ID, CK_SLOT_INFO,
CK_TOKEN_INFO, CK_TRUE,
};
use secrecy::ExposeSecret;
use std::convert::{TryFrom, TryInto};
use crate::error::RvError::BufferTooSmall;
impl Pkcs11 {
#[inline(always)]
fn get_slots(&self, with_token: CK_BBOOL) -> Result> {
let mut slot_count = 0;
let rval = unsafe {
get_pkcs11!(self, C_GetSlotList)(with_token, std::ptr::null_mut(), &mut slot_count)
};
Rv::from(rval).into_result()?;
let mut slots;
loop {
slots = vec![0; slot_count as usize];
let rval = unsafe {
get_pkcs11!(self, C_GetSlotList)(with_token, slots.as_mut_ptr(), &mut slot_count)
};
// Account for a race condition between the call to get the
// slot_count and the last call in which the number of slots grew.
// In this case, slot_count will have been updated to the larger amount
// and we want to loop again with a resized buffer.
if !matches!(Rv::from(rval), Rv::Error(BufferTooSmall)) {
// Account for other possible error types
Rv::from(rval).into_result()?;
// Otherwise, we have a valid list to process
break;
}
}
// Account for the same race condition, but with a shrinking slot_count
slots.truncate(slot_count as usize);
Ok(slots.into_iter().map(Slot::new).collect())
}
/// Get all slots available with a token
pub fn get_slots_with_token(&self) -> Result> {
self.get_slots(CK_TRUE)
}
/// Get all slots
pub fn get_all_slots(&self) -> Result> {
self.get_slots(CK_FALSE)
}
/// Get all slots available with a token
pub fn get_slots_with_initialized_token(&self) -> Result> {
let slots = self.get_slots_with_token()?;
slots
.into_iter()
.filter_map(|slot| match self.get_token_info(slot) {
Ok(token_info) => {
if token_info.token_initialized() {
Some(Ok(slot))
} else {
None
}
}
Err(e) => Some(Err(e)),
})
.collect()
}
/// Initialize a token
///
/// Currently will use an empty label for all tokens.
pub fn init_token(&self, slot: Slot, pin: &AuthPin, label: &str) -> Result<()> {
let label = label_from_str(label);
unsafe {
Rv::from(get_pkcs11!(self, C_InitToken)(
slot.try_into()?,
pin.expose_secret().as_ptr() as *mut u8,
pin.expose_secret().len().try_into()?,
label.as_ptr() as *mut u8,
))
.into_result()
}
}
/// Returns the slot info
pub fn get_slot_info(&self, slot: Slot) -> Result {
unsafe {
let mut slot_info = CK_SLOT_INFO::default();
Rv::from(get_pkcs11!(self, C_GetSlotInfo)(
slot.try_into()?,
&mut slot_info,
))
.into_result()?;
Ok(SlotInfo::from(slot_info))
}
}
/// Returns information about a specific token
pub fn get_token_info(&self, slot: Slot) -> Result {
unsafe {
let mut token_info = CK_TOKEN_INFO::default();
Rv::from(get_pkcs11!(self, C_GetTokenInfo)(
slot.try_into()?,
&mut token_info,
))
.into_result()?;
TokenInfo::try_from(token_info)
}
}
/// Get all mechanisms support by a slot
pub fn get_mechanism_list(&self, slot: Slot) -> Result> {
let mut mechanism_count = 0;
unsafe {
Rv::from(get_pkcs11!(self, C_GetMechanismList)(
slot.try_into()?,
std::ptr::null_mut(),
&mut mechanism_count,
))
.into_result()?;
}
let mut mechanisms = vec![0; mechanism_count.try_into()?];
unsafe {
Rv::from(get_pkcs11!(self, C_GetMechanismList)(
slot.try_into()?,
mechanisms.as_mut_ptr(),
&mut mechanism_count,
))
.into_result()?;
}
// Truncate mechanisms if count decreased.
mechanisms.truncate(mechanism_count.try_into()?);
Ok(mechanisms
.into_iter()
.filter_map(|type_| type_.try_into().ok())
.collect())
}
/// Get detailed information about a mechanism for a slot
pub fn get_mechanism_info(&self, slot: Slot, type_: MechanismType) -> Result {
unsafe {
let mut mechanism_info = CK_MECHANISM_INFO::default();
Rv::from(get_pkcs11!(self, C_GetMechanismInfo)(
slot.try_into()?,
type_.into(),
&mut mechanism_info,
))
.into_result()?;
Ok(MechanismInfo::from(mechanism_info))
}
}
fn wait_for_slot_event_impl(&self, flags: CK_FLAGS) -> Result {
unsafe {
let mut slot: CK_SLOT_ID = 0;
let wait_for_slot_event = get_pkcs11!(self, C_WaitForSlotEvent);
let rv = wait_for_slot_event(flags, &mut slot, std::ptr::null_mut());
Rv::from(rv).into_result()?;
Ok(Slot::new(slot))
}
}
/// Wait for slot events (insertion or removal of a token)
pub fn wait_for_slot_event(&self) -> Result {
self.wait_for_slot_event_impl(0)
}
/// Get the latest slot event (insertion or removal of a token)
pub fn get_slot_event(&self) -> Result> {
match self.wait_for_slot_event_impl(CKF_DONT_BLOCK) {
Err(Error::Pkcs11(RvError::NoEvent)) => Ok(None),
Ok(slot) => Ok(Some(slot)),
Err(x) => Err(x),
}
}
}
cryptoki-0.6.1/src/error/mod.rs 0000644 0000000 0000000 00000010453 10461020230 0014544 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Pkcs11 return codes and crate Result/Error types
mod rv;
mod rv_error;
pub use rv::*;
pub use rv_error::*;
use std::fmt;
#[derive(Debug)]
/// Main error type
pub enum Error {
/// Any error that happens during library loading of the PKCS#11 module is encompassed under
/// this error. It is a direct forward of the underlying error from libloading.
LibraryLoading(libloading::Error),
/// All PKCS#11 functions that return non-zero translate to this error.
Pkcs11(RvError),
/// This error marks a feature that is not yet supported by the PKCS11 Rust abstraction layer.
NotSupported,
/// Error happening while converting types
TryFromInt(std::num::TryFromIntError),
/// Error when converting a slice to an array
TryFromSlice(std::array::TryFromSliceError),
/// Error when converting a numerical str to an integral value
ParseInt(core::num::ParseIntError),
/// Error converting into a type assuming valid UTF-8
Utf8(std::str::Utf8Error),
/// Error with nul characters in Strings
NulError(std::ffi::NulError),
/// Calling a PKCS11 function that is a NULL function pointer.
NullFunctionPointer,
/// The value is not one of those expected.
InvalidValue,
/// The PIN was not set before logging in.
PinNotSet,
/// The PKCS11 library has already been initialized
AlreadyInitialized,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::LibraryLoading(e) => write!(f, "libloading error ({e})"),
Error::Pkcs11(e) => write!(f, "PKCS11 error: {e}"),
Error::NotSupported => write!(f, "Feature not supported"),
Error::TryFromInt(e) => write!(f, "Conversion between integers failed ({e})"),
Error::TryFromSlice(e) => write!(f, "Error converting slice to array ({e})"),
Error::ParseInt(e) => write!(f, "Error parsing string as integer ({e})"),
Error::Utf8(e) => write!(f, "Invalid UTF-8 ({e})"),
Error::NulError(e) => write!(f, "An interior nul byte was found ({e})"),
Error::NullFunctionPointer => write!(f, "Calling a NULL function pointer"),
Error::InvalidValue => write!(f, "The value is not one of the expected options"),
Error::PinNotSet => write!(f, "Pin has not been set before trying to log in"),
Error::AlreadyInitialized => write!(f, "PKCS11 library has already been initialized"),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::LibraryLoading(e) => Some(e),
Error::TryFromInt(e) => Some(e),
Error::TryFromSlice(e) => Some(e),
Error::ParseInt(e) => Some(e),
Error::Utf8(e) => Some(e),
Error::NulError(e) => Some(e),
Error::Pkcs11(_)
| Error::NotSupported
| Error::NullFunctionPointer
| Error::PinNotSet
| Error::InvalidValue
| Error::AlreadyInitialized => None,
}
}
}
impl From for Error {
fn from(err: libloading::Error) -> Error {
Error::LibraryLoading(err)
}
}
impl From for Error {
fn from(err: std::num::TryFromIntError) -> Error {
Error::TryFromInt(err)
}
}
impl From for Error {
fn from(err: std::array::TryFromSliceError) -> Error {
Error::TryFromSlice(err)
}
}
impl From for Error {
fn from(err: core::num::ParseIntError) -> Error {
Error::ParseInt(err)
}
}
impl From for Error {
fn from(err: std::str::Utf8Error) -> Error {
Error::Utf8(err)
}
}
impl From for Error {
fn from(err: std::ffi::NulError) -> Error {
Error::NulError(err)
}
}
impl From for Error {
fn from(_err: std::convert::Infallible) -> Error {
unreachable!()
}
}
impl From for Error {
fn from(rv_error: RvError) -> Self {
Error::Pkcs11(rv_error)
}
}
/// Main Result type
pub type Result = core::result::Result;
cryptoki-0.6.1/src/error/rv.rs 0000644 0000000 0000000 00000020043 10461020230 0014410 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Function types
use super::{Error, Result, RvError};
use cryptoki_sys::*;
use log::error;
#[derive(Copy, Clone, Debug)]
/// Return value of a PKCS11 function
pub enum Rv {
/// The function exited successfully
Ok,
/// There was an error
Error(RvError),
}
impl From for Rv {
fn from(ck_rv: CK_RV) -> Self {
match ck_rv {
CKR_OK => Rv::Ok,
CKR_CANCEL => Rv::Error(RvError::Cancel),
CKR_HOST_MEMORY => Rv::Error(RvError::HostMemory),
CKR_SLOT_ID_INVALID => Rv::Error(RvError::SlotIdInvalid),
CKR_GENERAL_ERROR => Rv::Error(RvError::GeneralError),
CKR_FUNCTION_FAILED => Rv::Error(RvError::FunctionFailed),
CKR_ARGUMENTS_BAD => Rv::Error(RvError::ArgumentsBad),
CKR_NO_EVENT => Rv::Error(RvError::NoEvent),
CKR_NEED_TO_CREATE_THREADS => Rv::Error(RvError::NeedToCreateThreads),
CKR_CANT_LOCK => Rv::Error(RvError::CantLock),
CKR_ATTRIBUTE_READ_ONLY => Rv::Error(RvError::AttributeReadOnly),
CKR_ATTRIBUTE_SENSITIVE => Rv::Error(RvError::AttributeSensitive),
CKR_ATTRIBUTE_TYPE_INVALID => Rv::Error(RvError::AttributeTypeInvalid),
CKR_ATTRIBUTE_VALUE_INVALID => Rv::Error(RvError::AttributeValueInvalid),
CKR_ACTION_PROHIBITED => Rv::Error(RvError::ActionProhibited),
CKR_DATA_INVALID => Rv::Error(RvError::DataInvalid),
CKR_DATA_LEN_RANGE => Rv::Error(RvError::DataLenRange),
CKR_DEVICE_ERROR => Rv::Error(RvError::DeviceError),
CKR_DEVICE_MEMORY => Rv::Error(RvError::DeviceMemory),
CKR_DEVICE_REMOVED => Rv::Error(RvError::DeviceRemoved),
CKR_ENCRYPTED_DATA_INVALID => Rv::Error(RvError::EncryptedDataInvalid),
CKR_ENCRYPTED_DATA_LEN_RANGE => Rv::Error(RvError::EncryptedDataLenRange),
CKR_FUNCTION_CANCELED => Rv::Error(RvError::FunctionCanceled),
CKR_FUNCTION_NOT_PARALLEL => Rv::Error(RvError::FunctionNotParallel),
CKR_FUNCTION_NOT_SUPPORTED => Rv::Error(RvError::FunctionNotSupported),
CKR_CURVE_NOT_SUPPORTED => Rv::Error(RvError::CurveNotSupported),
CKR_KEY_HANDLE_INVALID => Rv::Error(RvError::KeyHandleInvalid),
CKR_KEY_SIZE_RANGE => Rv::Error(RvError::KeySizeRange),
CKR_KEY_TYPE_INCONSISTENT => Rv::Error(RvError::KeyTypeInconsistent),
CKR_KEY_NOT_NEEDED => Rv::Error(RvError::KeyNotNeeded),
CKR_KEY_CHANGED => Rv::Error(RvError::KeyChanged),
CKR_KEY_NEEDED => Rv::Error(RvError::KeyNeeded),
CKR_KEY_INDIGESTIBLE => Rv::Error(RvError::KeyIndigestible),
CKR_KEY_FUNCTION_NOT_PERMITTED => Rv::Error(RvError::KeyFunctionNotPermitted),
CKR_KEY_NOT_WRAPPABLE => Rv::Error(RvError::KeyNotWrappable),
CKR_KEY_UNEXTRACTABLE => Rv::Error(RvError::KeyUnextractable),
CKR_MECHANISM_INVALID => Rv::Error(RvError::MechanismInvalid),
CKR_MECHANISM_PARAM_INVALID => Rv::Error(RvError::MechanismParamInvalid),
CKR_OBJECT_HANDLE_INVALID => Rv::Error(RvError::ObjectHandleInvalid),
CKR_OPERATION_ACTIVE => Rv::Error(RvError::OperationActive),
CKR_OPERATION_NOT_INITIALIZED => Rv::Error(RvError::OperationNotInitialized),
CKR_PIN_INCORRECT => Rv::Error(RvError::PinIncorrect),
CKR_PIN_INVALID => Rv::Error(RvError::PinInvalid),
CKR_PIN_LEN_RANGE => Rv::Error(RvError::PinLenRange),
CKR_PIN_EXPIRED => Rv::Error(RvError::PinExpired),
CKR_PIN_LOCKED => Rv::Error(RvError::PinLocked),
CKR_SESSION_CLOSED => Rv::Error(RvError::SessionClosed),
CKR_SESSION_COUNT => Rv::Error(RvError::SessionCount),
CKR_SESSION_HANDLE_INVALID => Rv::Error(RvError::SessionHandleInvalid),
CKR_SESSION_PARALLEL_NOT_SUPPORTED => Rv::Error(RvError::SessionParallelNotSupported),
CKR_SESSION_READ_ONLY => Rv::Error(RvError::SessionReadOnly),
CKR_SESSION_EXISTS => Rv::Error(RvError::SessionExists),
CKR_SESSION_READ_ONLY_EXISTS => Rv::Error(RvError::SessionReadOnlyExists),
CKR_SESSION_READ_WRITE_SO_EXISTS => Rv::Error(RvError::SessionReadWriteSoExists),
CKR_SIGNATURE_INVALID => Rv::Error(RvError::SignatureInvalid),
CKR_SIGNATURE_LEN_RANGE => Rv::Error(RvError::SignatureLenRange),
CKR_TEMPLATE_INCOMPLETE => Rv::Error(RvError::TemplateIncomplete),
CKR_TEMPLATE_INCONSISTENT => Rv::Error(RvError::TemplateInconsistent),
CKR_TOKEN_NOT_PRESENT => Rv::Error(RvError::TokenNotPresent),
CKR_TOKEN_NOT_RECOGNIZED => Rv::Error(RvError::TokenNotRecognized),
CKR_TOKEN_WRITE_PROTECTED => Rv::Error(RvError::TokenWriteProtected),
CKR_UNWRAPPING_KEY_HANDLE_INVALID => Rv::Error(RvError::UnwrappingKeyHandleInvalid),
CKR_UNWRAPPING_KEY_SIZE_RANGE => Rv::Error(RvError::UnwrappingKeySizeRange),
CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT => {
Rv::Error(RvError::UnwrappingKeyTypeInconsistent)
}
CKR_USER_ALREADY_LOGGED_IN => Rv::Error(RvError::UserAlreadyLoggedIn),
CKR_USER_NOT_LOGGED_IN => Rv::Error(RvError::UserNotLoggedIn),
CKR_USER_PIN_NOT_INITIALIZED => Rv::Error(RvError::UserPinNotInitialized),
CKR_USER_TYPE_INVALID => Rv::Error(RvError::UserTypeInvalid),
CKR_USER_ANOTHER_ALREADY_LOGGED_IN => Rv::Error(RvError::UserAnotherAlreadyLoggedIn),
CKR_USER_TOO_MANY_TYPES => Rv::Error(RvError::UserTooManyTypes),
CKR_WRAPPED_KEY_INVALID => Rv::Error(RvError::WrappedKeyInvalid),
CKR_WRAPPED_KEY_LEN_RANGE => Rv::Error(RvError::WrappedKeyLenRange),
CKR_WRAPPING_KEY_HANDLE_INVALID => Rv::Error(RvError::WrappingKeyHandleInvalid),
CKR_WRAPPING_KEY_SIZE_RANGE => Rv::Error(RvError::WrappingKeySizeRange),
CKR_WRAPPING_KEY_TYPE_INCONSISTENT => Rv::Error(RvError::WrappingKeyTypeInconsistent),
CKR_RANDOM_SEED_NOT_SUPPORTED => Rv::Error(RvError::RandomSeedNotSupported),
CKR_RANDOM_NO_RNG => Rv::Error(RvError::RandomNoRng),
CKR_DOMAIN_PARAMS_INVALID => Rv::Error(RvError::DomainParamsInvalid),
CKR_BUFFER_TOO_SMALL => Rv::Error(RvError::BufferTooSmall),
CKR_SAVED_STATE_INVALID => Rv::Error(RvError::SavedStateInvalid),
CKR_INFORMATION_SENSITIVE => Rv::Error(RvError::InformationSensitive),
CKR_STATE_UNSAVEABLE => Rv::Error(RvError::StateUnsaveable),
CKR_CRYPTOKI_NOT_INITIALIZED => Rv::Error(RvError::CryptokiNotInitialized),
CKR_CRYPTOKI_ALREADY_INITIALIZED => Rv::Error(RvError::CryptokiAlreadyInitialized),
CKR_MUTEX_BAD => Rv::Error(RvError::MutexBad),
CKR_MUTEX_NOT_LOCKED => Rv::Error(RvError::MutexNotLocked),
CKR_NEW_PIN_MODE => Rv::Error(RvError::NewPinMode),
CKR_NEXT_OTP => Rv::Error(RvError::NextOtp),
CKR_EXCEEDED_MAX_ITERATIONS => Rv::Error(RvError::ExceededMaxIterations),
CKR_FIPS_SELF_TEST_FAILED => Rv::Error(RvError::FipsSelfTestFailed),
CKR_LIBRARY_LOAD_FAILED => Rv::Error(RvError::LibraryLoadFailed),
CKR_PIN_TOO_WEAK => Rv::Error(RvError::PinTooWeak),
CKR_PUBLIC_KEY_INVALID => Rv::Error(RvError::PublicKeyInvalid),
CKR_FUNCTION_REJECTED => Rv::Error(RvError::FunctionRejected),
CKR_VENDOR_DEFINED => Rv::Error(RvError::VendorDefined),
other => {
error!(
"Can not find a corresponding error for {}, converting to GeneralError.",
other
);
Rv::Error(RvError::GeneralError)
}
}
}
}
impl Rv {
/// Convert the return value into a standard Result type
pub fn into_result(self) -> Result<()> {
match self {
Rv::Ok => Ok(()),
Rv::Error(rv_error) => Err(Error::Pkcs11(rv_error)),
}
}
}
cryptoki-0.6.1/src/error/rv_error.rs 0000644 0000000 0000000 00000137303 10461020230 0015631 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Function types
use std::fmt;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// Description of a return value error
pub enum RvError {
/// When a function executing in serial with an application decides to give the application a chance to do some work, it calls an application-supplied function with a CKN_SURRENDER callback (see Section 5.16). If the callback returns the value CKR_CANCEL, then the function aborts and returns CKR_FUNCTION_CANCELED.
Cancel,
/// The computer that the Cryptoki library is running on has insufficient memory to perform the requested function.
HostMemory,
/// The specified slot ID is not valid.
SlotIdInvalid,
/// Some horrible, unrecoverable error has occurred. In the worst case, it is possible that the function only partially succeeded, and that the computer and/or token is in an inconsistent state.
GeneralError,
/// The requested function could not be performed, but detailed information about why not is not available in this error return. If the failed function uses a session, it is possible that the CK_SESSION_INFO structure that can be obtained by calling C_GetSessionInfo will hold useful information about what happened in its ulDeviceError field. In any event, although the function call failed, the situation is not necessarily totally hopeless, as it is likely to be when CKR_GENERAL_ERROR is returned. Depending on what the root cause of the error actually was, it is possible that an attempt to make the exact same function call again would succeed.
FunctionFailed,
/// This is a rather generic error code which indicates that the arguments supplied to the Cryptoki function were in some way not appropriate.
ArgumentsBad,
/// This value can only be returned by C_GetSlotEvent. It is returned when C_GetSlotEvent is called in non-blocking mode and there are no new slot events to return.
NoEvent,
/// This value can only be returned by C_Initialize. It is returned when two conditions hold: 1. The application called C_Initialize in a way which tells the Cryptoki library that application threads executing calls to the library cannot use native operating system methods to spawn new threads. 2. The library cannot function properly without being able to spawn new threads in the above fashion.
NeedToCreateThreads,
/// This value can only be returned by C_Initialize. It means that the type of locking requested by the application for thread-safety is not available in this library, and so the application cannot make use of this library in the specified fashion.
CantLock,
/// An attempt was made to set a value for an attribute which may not be set by the application, or which may not be modified by the application. See Section 4.1 for more information.
AttributeReadOnly,
/// An attempt was made to obtain the value of an attribute of an object which cannot be satisfied because the object is either sensitive or un-extractable.
AttributeSensitive,
/// An invalid attribute type was specified in a template. See Section 4.1 for more information.
AttributeTypeInvalid,
/// An invalid value was specified for a particular attribute in a template. See Section 4.1 for more information.
AttributeValueInvalid,
/// This value can only be returned by C_CopyObject, C_SetAttributeValue and C_DestroyObject. It denotes that the action may not be taken, either because of underlying policy restrictions on the token, or because the object has the the relevant CKA_COPYABLE, CKA_MODIFIABLE or CKA_DESTROYABLE policy attribute set to CK_FALSE.
ActionProhibited,
/// The plaintext input data to a cryptographic operation is invalid. This return value has lower priority than CKR_DATA_LEN_RANGE.
DataInvalid,
/// The plaintext input data to a cryptographic operation has a bad length. Depending on the operation’s mechanism, this could mean that the plaintext data is too short, too long, or is not a multiple of some particular block size. This return value has higher priority than CKR_DATA_INVALID.
DataLenRange,
/// Some problem has occurred with the token and/or slot. This error code can be returned by more than just the functions mentioned above; in particular, it is possible for C_GetSlotInfo to return CKR_DEVICE_ERROR.
DeviceError,
/// The token does not have sufficient memory to perform the requested function.
DeviceMemory,
/// The token was removed from its slot during the execution of the function.
DeviceRemoved,
/// The encrypted input to a decryption operation has been determined to be invalid ciphertext. This return value has lower priority than CKR_ENCRYPTED_DATA_LEN_RANGE.
EncryptedDataInvalid,
/// The ciphertext input to a decryption operation has been determined to be invalid ciphertext solely on the basis of its length. Depending on the operation’s mechanism, this could mean that the ciphertext is too short, too long, or is not a multiple of some particular block size. This return value has higher priority than CKR_ENCRYPTED_DATA_INVALID.
EncryptedDataLenRange,
/// The function was canceled in mid-execution. This happens to a cryptographic function if the function makes a CKN_SURRENDER application callback which returns CKR_CANCEL (see CKR_CANCEL). It also happens to a function that performs PIN entry through a protected path. The method used to cancel a protected path PIN entry operation is device dependent.
FunctionCanceled,
/// There is currently no function executing in parallel in the specified session. This is a legacy error code which is only returned by the legacy functions C_GetFunctionStatus and C_CancelFunction.
FunctionNotParallel,
/// The requested function is not supported by this Cryptoki library. Even unsupported functions in the Cryptoki API should have a “stub” in the library; this stub should simply return the value CKR_FUNCTION_NOT_SUPPORTED.
FunctionNotSupported,
/// This curve is not supported by this token. Used with Elliptic Curve mechanisms.
CurveNotSupported,
/// The specified key handle is not valid. It may be the case that the specified handle is a valid handle for an object which is not a key. We reiterate here that 0 is never a valid key handle.
KeyHandleInvalid,
/// Although the requested keyed cryptographic operation could in principle be carried out, this Cryptoki library (or the token) is unable to actually do it because the supplied key‘s size is outside the range of key sizes that it can handle.
KeySizeRange,
/// The specified key is not the correct type of key to use with the specified mechanism. This return value has a higher priority than CKR_KEY_FUNCTION_NOT_PERMITTED.
KeyTypeInconsistent,
/// An extraneous key was supplied to C_SetOperationState. For example, an attempt was made to restore a session that had been performing a message digesting operation, and an encryption key was supplied.
KeyNotNeeded,
/// This value is only returned by C_SetOperationState. It indicates that one of the keys specified is not the same key that was being used in the original saved session.
KeyChanged,
/// This value is only returned by C_SetOperationState. It indicates that the session state cannot be restored because C_SetOperationState needs to be supplied with one or more keys that were being used in the original saved session.
KeyNeeded,
/// This error code can only be returned by C_DigestKey. It indicates that the value of the specified key cannot be digested for some reason (perhaps the key isn’t a secret key, or perhaps the token simply can’t digest this kind of key).
KeyIndigestible,
/// An attempt has been made to use a key for a cryptographic purpose that the key’s attributes are not set to allow it to do. For example, to use a key for performing encryption, that key MUST have its CKA_ENCRYPT attribute set to CK_TRUE (the fact that the key MUST have a CKA_ENCRYPT attribute implies that the key cannot be a private key). This return value has lower priority than CKR_KEY_TYPE_INCONSISTENT.
KeyFunctionNotPermitted,
/// Although the specified private or secret key does not have its CKA_EXTRACTABLE attribute set to CK_FALSE, Cryptoki (or the token) is unable to wrap the key as requested (possibly the token can only wrap a given key with certain types of keys, and the wrapping key specified is not one of these types). Compare with CKR_KEY_UNEXTRACTABLE.
KeyNotWrappable,
/// The specified private or secret key can’t be wrapped because its CKA_EXTRACTABLE attribute is set to CK_FALSE. Compare with CKR_KEY_NOT_WRAPPABLE.
KeyUnextractable,
/// An invalid mechanism was specified to the cryptographic operation. This error code is an appropriate return value if an unknown mechanism was specified or if the mechanism specified cannot be used in the selected token with the selected function.
MechanismInvalid,
/// Invalid parameters were supplied to the mechanism specified to the cryptographic operation. Which parameter values are supported by a given mechanism can vary from token to token.
MechanismParamInvalid,
/// The specified object handle is not valid. We reiterate here that 0 is never a valid object handle.
ObjectHandleInvalid,
/// There is already an active operation (or combination of active operations) which prevents Cryptoki from activating the specified operation. For example, an active object-searching operation would prevent Cryptoki from activating an encryption operation with C_EncryptInit. Or, an active digesting operation and an active encryption operation would prevent Cryptoki from activating a signature operation. Or, on a token which doesn’t support simultaneous dual cryptographic operations in a session (see the description of the CKF_DUAL_CRYPTO_OPERATIONS flag in the CK_TOKEN_INFO structure), an active signature operation would prevent Cryptoki from activating an encryption operation.
OperationActive,
/// There is no active operation of an appropriate type in the specified session. For example, an application cannot call C_Encrypt in a session without having called C_EncryptInit first to activate an encryption operation.
OperationNotInitialized,
/// The specified PIN is incorrect, i.e., does not match the PIN stored on the token. More generally-- when authentication to the token involves something other than a PIN-- the attempt to authenticate the user has failed.
PinIncorrect,
/// The specified PIN has invalid characters in it. This return code only applies to functions which attempt to set a PIN.
PinInvalid,
/// The specified PIN is too long or too short. This return code only applies to functions which attempt to set a PIN.
PinLenRange,
/// The specified PIN has expired, and the requested operation cannot be carried out unless C_SetPIN is called to change the PIN value. Whether or not the normal user’s PIN on a token ever expires varies from token to token.
PinExpired,
/// The specified PIN is “locked”, and cannot be used. That is, because some particular number of failed authentication attempts has been reached, the token is unwilling to permit further attempts at authentication. Depending on the token, the specified PIN may or may not remain locked indefinitely.
PinLocked,
/// The session was closed during the execution of the function. Note that, as stated in [PKCS11-UG], the behavior of Cryptoki is undefined if multiple threads of an application attempt to access a common Cryptoki session simultaneously. Therefore, there is actually no guarantee that a function invocation could ever return the value CKR_SESSION_CLOSED. An example of multiple threads accessing a common session simultaneously is where one thread is using a session when another thread closes that same session.
SessionClosed,
/// This value can only be returned by C_OpenSession. It indicates that the attempt to open a session failed, either because the token has too many sessions already open, or because the token has too many read/write sessions already open.
SessionCount,
/// The specified session handle was invalid at the time that the function was invoked. Note that this can happen if the session’s token is removed before the function invocation, since removing a token closes all sessions with it.
SessionHandleInvalid,
/// The specified token does not support parallel sessions. This is a legacy error code—in Cryptoki Version 2.01 and up, no token supports parallel sessions. CKR_SESSION_PARALLEL_NOT_SUPPORTED can only be returned by C_OpenSession, and it is only returned when C_OpenSession is called in a particular `deprecated` way.
SessionParallelNotSupported,
/// The specified session was unable to accomplish the desired action because it is a read-only session. This return value has lower priority than CKR_TOKEN_WRITE_PROTECTED.
SessionReadOnly,
/// This value can only be returned by C_InitToken. It indicates that a session with the token is already open, and so the token cannot be initialized.
SessionExists,
/// A read-only session already exists, and so the SO cannot be logged in.
SessionReadOnlyExists,
/// A read/write SO session already exists, and so a read-only session cannot be opened.
SessionReadWriteSoExists,
/// The provided signature/MAC is invalid. This return value has lower priority than CKR_SIGNATURE_LEN_RANGE.
SignatureInvalid,
/// The provided signature/MAC can be seen to be invalid solely on the basis of its length. This return value has higher priority than CKR_SIGNATURE_INVALID.
SignatureLenRange,
/// The template specified for creating an object is incomplete, and lacks some necessary attributes. See Section 4.1 for more information.
TemplateIncomplete,
/// The template specified for creating an object has conflicting attributes. See Section 4.1 for more information.
TemplateInconsistent,
/// The token was not present in its slot at the time that the function was invoked.
TokenNotPresent,
/// The Cryptoki library and/or slot does not recognize the token in the slot.
TokenNotRecognized,
/// The requested action could not be performed because the token is write-protected. This return value has higher priority than CKR_SESSION_READ_ONLY.
TokenWriteProtected,
/// This value can only be returned by C_UnwrapKey. It indicates that the key handle specified to be used to unwrap another key is not valid.
UnwrappingKeyHandleInvalid,
/// This value can only be returned by C_UnwrapKey. It indicates that although the requested unwrapping operation could in principle be carried out, this Cryptoki library (or the token) is unable to actually do it because the supplied key’s size is outside the range of key sizes that it can handle.
UnwrappingKeySizeRange,
/// This value can only be returned by C_UnwrapKey. It indicates that the type of the key specified to unwrap another key is not consistent with the mechanism specified for unwrapping.
UnwrappingKeyTypeInconsistent,
/// This value can only be returned by C_Login. It indicates that the specified user cannot be logged into the session, because it is already logged into the session. For example, if an application has an open SO session, and it attempts to log the SO into it, it will receive this error code.
UserAlreadyLoggedIn,
/// The desired action cannot be performed because the appropriate user (or an appropriate user) is not logged in. One example is that a session cannot be logged out unless it is logged in. Another example is that a private object cannot be created on a token unless the session attempting to create it is logged in as the normal user. A final example is that cryptographic operations on certain tokens cannot be performed unless the normal user is logged in.
UserNotLoggedIn,
/// This value can only be returned by C_Login. It indicates that the normal user’s PIN has not yet been initialized with C_InitPIN.
UserPinNotInitialized,
/// An invalid value was specified as a CK_USER_TYPE. Valid types are CKU_SO, CKU_USER, and CKU_CONTEXT_SPECIFIC.
UserTypeInvalid,
/// This value can only be returned by C_Login. It indicates that the specified user cannot be logged into the session, because another user is already logged into the session. For example, if an application has an open SO session, and it attempts to log the normal user into it, it will receive this error code.
UserAnotherAlreadyLoggedIn,
/// An attempt was made to have more distinct users simultaneously logged into the token than the token and/or library permits. For example, if some application has an open SO session, and another application attempts to log the normal user into a session, the attempt may return this error. It is not required to, however. Only if the simultaneous distinct users cannot be supported does C_Login have to return this value. Note that this error code generalizes to true multi-user tokens.
UserTooManyTypes,
/// This value can only be returned by C_UnwrapKey. It indicates that the provided wrapped key is not valid. If a call is made to C_UnwrapKey to unwrap a particular type of key (i.e., some particular key type is specified in the template provided to C_UnwrapKey), and the wrapped key provided to C_UnwrapKey is recognizably not a wrapped key of the proper type, then C_UnwrapKey should return CKR_WRAPPED_KEY_INVALID. This return value has lower priority than CKR_WRAPPED_KEY_LEN_RANGE.
WrappedKeyInvalid,
/// This value can only be returned by C_UnwrapKey. It indicates that the provided wrapped key can be seen to be invalid solely on the basis of its length. This return value has higher priority than CKR_WRAPPED_KEY_INVALID.
WrappedKeyLenRange,
/// This value can only be returned by C_WrapKey. It indicates that the key handle specified to be used to wrap another key is not valid.
WrappingKeyHandleInvalid,
/// This value can only be returned by C_WrapKey. It indicates that although the requested wrapping operation could in principle be carried out, this Cryptoki library (or the token) is unable to actually do it because the supplied wrapping key’s size is outside the range of key sizes that it can handle.
WrappingKeySizeRange,
/// This value can only be returned by C_WrapKey. It indicates that the type of the key specified to wrap another key is not consistent with the mechanism specified for wrapping.
WrappingKeyTypeInconsistent,
/// This value can only be returned by C_SeedRandom. It indicates that the token’s random number generator does not accept seeding from an application. This return value has lower priority than CKR_RANDOM_NO_RNG.
RandomSeedNotSupported,
/// This value can be returned by C_SeedRandom and C_GenerateRandom. It indicates that the specified token doesn’t have a random number generator. This return value has higher priority than CKR_RANDOM_SEED_NOT_SUPPORTED.
RandomNoRng,
/// Invalid or unsupported domain parameters were supplied to the function. Which representation methods of domain parameters are supported by a given mechanism can vary from token to token.
DomainParamsInvalid,
/// The output of the function is too large to fit in the supplied buffer.
BufferTooSmall,
/// This value can only be returned by C_SetOperationState. It indicates that the supplied saved cryptographic operations state is invalid, and so it cannot be restored to the specified session.
SavedStateInvalid,
/// The information requested could not be obtained because the token considers it sensitive, and is not able or willing to reveal it.
InformationSensitive,
/// The cryptographic operations state of the specified session cannot be saved for some reason (possibly the token is simply unable to save the current state). This return value has lower priority than CKR_OPERATION_NOT_INITIALIZED.
StateUnsaveable,
/// This value can be returned by any function other than C_Initialize and C_GetFunctionList. It indicates that the function cannot be executed because the Cryptoki library has not yet been initialized by a call to C_Initialize.
CryptokiNotInitialized,
/// This value can only be returned by C_Initialize. It means that the Cryptoki library has already been initialized (by a previous call to C_Initialize which did not have a matching C_Finalize call).
CryptokiAlreadyInitialized,
/// This error code can be returned by mutex-handling functions that are passed a bad mutex object as an argument. Unfortunately, it is possible for such a function not to recognize a bad mutex object. There is therefore no guarantee that such a function will successfully detect bad mutex objects and return this value.
MutexBad,
/// This error code can be returned by mutex-unlocking functions. It indicates that the mutex supplied to the mutex-unlocking function was not locked.
MutexNotLocked,
/// CKR_NEW_PIN_MODE
NewPinMode,
/// CKR_NEXT_OTP
NextOtp,
/// An iterative algorithm (for key pair generation, domain parameter generation etc.) failed because we have exceeded the maximum number of iterations. This error code has precedence over CKR_FUNCTION_FAILED. Examples of iterative algorithms include DSA signature generation (retry if either r = 0 or s = 0) and generation of DSA primes p and q specified in FIPS 186-4.
ExceededMaxIterations,
/// A FIPS 140-2 power-up self-test or conditional self-test failed. The token entered an error state. Future calls to cryptographic functions on the token will return CKR_GENERAL_ERROR. CKR_FIPS_SELF_TEST_FAILED has a higher precedence over CKR_GENERAL_ERROR. This error may be returned by C_Initialize, if a power-up self-test failed, by C_GenerateRandom or C_SeedRandom, if the continuous random number generator test failed, or by C_GenerateKeyPair, if the pair-wise consistency test failed.
FipsSelfTestFailed,
/// The Cryptoki library could not load a dependent shared library.
LibraryLoadFailed,
/// The specified PIN is too weak so that it could be easy to guess. If the PIN is too short, CKR_PIN_LEN_RANGE should be returned instead. This return code only applies to functions which attempt to set a PIN.
PinTooWeak,
/// The public key fails a public key validation. For example, an EC public key fails the public key validation specified in Section 5.2.2 of ANSI X9.62. This error code may be returned by C_CreateObject, when the public key is created, or by C_VerifyInit or C_VerifyRecoverInit, when the public key is used. It may also be returned by C_DeriveKey, in preference to CKR_MECHANISM_PARAM_INVALID, if the other party's public key specified in the mechanism's parameters is invalid.
PublicKeyInvalid,
/// The signature request is rejected by the user.
FunctionRejected,
/// CKR_VENDOR_DEFINED
VendorDefined,
}
impl fmt::Display for RvError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RvError::Cancel => write!(f, "When a function executing in serial with an application decides to give the application a chance to do some work, it calls an application-supplied function with a CKN_SURRENDER callback (see Section 5.16). If the callback returns the value CKR_CANCEL, then the function aborts and returns CKR_FUNCTION_CANCELED."),
RvError::HostMemory => write!(f, "The computer that the Cryptoki library is running on has insufficient memory to perform the requested function."),
RvError::SlotIdInvalid => write!(f, "The specified slot ID is not valid."),
RvError::GeneralError => write!(f, "Some horrible, unrecoverable error has occurred. In the worst case, it is possible that the function only partially succeeded, and that the computer and/or token is in an inconsistent state."),
RvError::FunctionFailed => write!(f, "The requested function could not be performed, but detailed information about why not is not available in this error return. If the failed function uses a session, it is possible that the CK_SESSION_INFO structure that can be obtained by calling C_GetSessionInfo will hold useful information about what happened in its ulDeviceError field. In any event, although the function call failed, the situation is not necessarily totally hopeless, as it is likely to be when CKR_GENERAL_ERROR is returned. Depending on what the root cause of the error actually was, it is possible that an attempt to make the exact same function call again would succeed."),
RvError::ArgumentsBad => write!(f, "This is a rather generic error code which indicates that the arguments supplied to the Cryptoki function were in some way not appropriate."),
RvError::NoEvent => write!(f, "This value can only be returned by C_GetSlotEvent. It is returned when C_GetSlotEvent is called in non-blocking mode and there are no new slot events to return."),
RvError::NeedToCreateThreads => write!(f, "This value can only be returned by C_Initialize. It is returned when two conditions hold: 1. The application called C_Initialize in a way which tells the Cryptoki library that application threads executing calls to the library cannot use native operating system methods to spawn new threads. 2. The library cannot function properly without being able to spawn new threads in the above fashion."),
RvError::CantLock => write!(f, "This value can only be returned by C_Initialize. It means that the type of locking requested by the application for thread-safety is not available in this library, and so the application cannot make use of this library in the specified fashion."),
RvError::AttributeReadOnly => write!(f, "An attempt was made to set a value for an attribute which may not be set by the application, or which may not be modified by the application. See Section 4.1 for more information."),
RvError::AttributeSensitive => write!(f, "An attempt was made to obtain the value of an attribute of an object which cannot be satisfied because the object is either sensitive or un-extractable."),
RvError::AttributeTypeInvalid => write!(f, "An invalid attribute type was specified in a template. See Section 4.1 for more information."),
RvError::AttributeValueInvalid => write!(f, "An invalid value was specified for a particular attribute in a template. See Section 4.1 for more information."),
RvError::ActionProhibited => write!(f, " This value can only be returned by C_CopyObject, C_SetAttributeValue and C_DestroyObject. It denotes that the action may not be taken, either because of underlying policy restrictions on the token, or because the object has the the relevant CKA_COPYABLE, CKA_MODIFIABLE or CKA_DESTROYABLE policy attribute set to CK_FALSE."),
RvError::DataInvalid => write!(f, "The plaintext input data to a cryptographic operation is invalid. This return value has lower priority than CKR_DATA_LEN_RANGE."),
RvError::DataLenRange => write!(f, "The plaintext input data to a cryptographic operation has a bad length. Depending on the operation’s mechanism, this could mean that the plaintext data is too short, too long, or is not a multiple of some particular block size. This return value has higher priority than CKR_DATA_INVALID."),
RvError::DeviceError => write!(f, "Some problem has occurred with the token and/or slot. This error code can be returned by more than just the functions mentioned above; in particular, it is possible for C_GetSlotInfo to return CKR_DEVICE_ERROR."),
RvError::DeviceMemory => write!(f, "The token does not have sufficient memory to perform the requested function."),
RvError::DeviceRemoved => write!(f, "The token was removed from its slot during the execution of the function."),
RvError::EncryptedDataInvalid => write!(f, "The encrypted input to a decryption operation has been determined to be invalid ciphertext. This return value has lower priority than CKR_ENCRYPTED_DATA_LEN_RANGE."),
RvError::EncryptedDataLenRange => write!(f, "The ciphertext input to a decryption operation has been determined to be invalid ciphertext solely on the basis of its length. Depending on the operation’s mechanism, this could mean that the ciphertext is too short, too long, or is not a multiple of some particular block size. This return value has higher priority than CKR_ENCRYPTED_DATA_INVALID."),
RvError::FunctionCanceled => write!(f, "The function was canceled in mid-execution. This happens to a cryptographic function if the function makes a CKN_SURRENDER application callback which returns CKR_CANCEL (see CKR_CANCEL). It also happens to a function that performs PIN entry through a protected path. The method used to cancel a protected path PIN entry operation is device dependent."),
RvError::FunctionNotParallel => write!(f, "There is currently no function executing in parallel in the specified session. This is a legacy error code which is only returned by the legacy functions C_GetFunctionStatus and C_CancelFunction."),
RvError::FunctionNotSupported => write!(f, "The requested function is not supported by this Cryptoki library. Even unsupported functions in the Cryptoki API should have a “stub” in the library; this stub should simply return the value CKR_FUNCTION_NOT_SUPPORTED."),
RvError::CurveNotSupported => write!(f, " This curve is not supported by this token. Used with Elliptic Curve mechanisms."),
RvError::KeyHandleInvalid => write!(f, "The specified key handle is not valid. It may be the case that the specified handle is a valid handle for an object which is not a key. We reiterate here that 0 is never a valid key handle."),
RvError::KeySizeRange => write!(f, "Although the requested keyed cryptographic operation could in principle be carried out, this Cryptoki library (or the token) is unable to actually do it because the supplied key‘s size is outside the range of key sizes that it can handle."),
RvError::KeyTypeInconsistent => write!(f, "The specified key is not the correct type of key to use with the specified mechanism. This return value has a higher priority than CKR_KEY_FUNCTION_NOT_PERMITTED."),
RvError::KeyNotNeeded => write!(f, "An extraneous key was supplied to C_SetOperationState. For example, an attempt was made to restore a session that had been performing a message digesting operation, and an encryption key was supplied."),
RvError::KeyChanged => write!(f, "This value is only returned by C_SetOperationState. It indicates that one of the keys specified is not the same key that was being used in the original saved session."),
RvError::KeyNeeded => write!(f, "This value is only returned by C_SetOperationState. It indicates that the session state cannot be restored because C_SetOperationState needs to be supplied with one or more keys that were being used in the original saved session."),
RvError::KeyIndigestible => write!(f, "This error code can only be returned by C_DigestKey. It indicates that the value of the specified key cannot be digested for some reason (perhaps the key isn’t a secret key, or perhaps the token simply can’t digest this kind of key)."),
RvError::KeyFunctionNotPermitted => write!(f, "An attempt has been made to use a key for a cryptographic purpose that the key’s attributes are not set to allow it to do. For example, to use a key for performing encryption, that key MUST have its CKA_ENCRYPT attribute set to CK_TRUE (the fact that the key MUST have a CKA_ENCRYPT attribute implies that the key cannot be a private key). This return value has lower priority than CKR_KEY_TYPE_INCONSISTENT."),
RvError::KeyNotWrappable => write!(f, "Although the specified private or secret key does not have its CKA_EXTRACTABLE attribute set to CK_FALSE, Cryptoki (or the token) is unable to wrap the key as requested (possibly the token can only wrap a given key with certain types of keys, and the wrapping key specified is not one of these types). Compare with CKR_KEY_UNEXTRACTABLE."),
RvError::KeyUnextractable => write!(f, "The specified private or secret key can’t be wrapped because its CKA_EXTRACTABLE attribute is set to CK_FALSE. Compare with CKR_KEY_NOT_WRAPPABLE."),
RvError::MechanismInvalid => write!(f, "An invalid mechanism was specified to the cryptographic operation. This error code is an appropriate return value if an unknown mechanism was specified or if the mechanism specified cannot be used in the selected token with the selected function."),
RvError::MechanismParamInvalid => write!(f, "Invalid parameters were supplied to the mechanism specified to the cryptographic operation. Which parameter values are supported by a given mechanism can vary from token to token."),
RvError::ObjectHandleInvalid => write!(f, "The specified object handle is not valid. We reiterate here that 0 is never a valid object handle."),
RvError::OperationActive => write!(f, "There is already an active operation (or combination of active operations) which prevents Cryptoki from activating the specified operation. For example, an active object-searching operation would prevent Cryptoki from activating an encryption operation with C_EncryptInit. Or, an active digesting operation and an active encryption operation would prevent Cryptoki from activating a signature operation. Or, on a token which doesn’t support simultaneous dual cryptographic operations in a session (see the description of the CKF_DUAL_CRYPTO_OPERATIONS flag in the CK_TOKEN_INFO structure), an active signature operation would prevent Cryptoki from activating an encryption operation."),
RvError::OperationNotInitialized => write!(f, "There is no active operation of an appropriate type in the specified session. For example, an application cannot call C_Encrypt in a session without having called C_EncryptInit first to activate an encryption operation."),
RvError::PinIncorrect => write!(f, "The specified PIN is incorrect, i.e., does not match the PIN stored on the token. More generally-- when authentication to the token involves something other than a PIN-- the attempt to authenticate the user has failed."),
RvError::PinInvalid => write!(f, "The specified PIN has invalid characters in it. This return code only applies to functions which attempt to set a PIN."),
RvError::PinLenRange => write!(f, "The specified PIN is too long or too short. This return code only applies to functions which attempt to set a PIN."),
RvError::PinExpired => write!(f, "The specified PIN has expired, and the requested operation cannot be carried out unless C_SetPIN is called to change the PIN value. Whether or not the normal user’s PIN on a token ever expires varies from token to token."),
RvError::PinLocked => write!(f, "The specified PIN is “locked”, and cannot be used. That is, because some particular number of failed authentication attempts has been reached, the token is unwilling to permit further attempts at authentication. Depending on the token, the specified PIN may or may not remain locked indefinitely."),
RvError::SessionClosed => write!(f, "The session was closed during the execution of the function. Note that, as stated in [PKCS11-UG], the behavior of Cryptoki is undefined if multiple threads of an application attempt to access a common Cryptoki session simultaneously. Therefore, there is actually no guarantee that a function invocation could ever return the value CKR_SESSION_CLOSED. An example of multiple threads accessing a common session simultaneously is where one thread is using a session when another thread closes that same session."),
RvError::SessionCount => write!(f, "This value can only be returned by C_OpenSession. It indicates that the attempt to open a session failed, either because the token has too many sessions already open, or because the token has too many read/write sessions already open."),
RvError::SessionHandleInvalid => write!(f, "The specified session handle was invalid at the time that the function was invoked. Note that this can happen if the session’s token is removed before the function invocation, since removing a token closes all sessions with it."),
RvError::SessionParallelNotSupported => write!(f, "The specified token does not support parallel sessions. This is a legacy error code—in Cryptoki Version 2.01 and up, no token supports parallel sessions. CKR_SESSION_PARALLEL_NOT_SUPPORTED can only be returned by C_OpenSession, and it is only returned when C_OpenSession is called in a particular [deprecated] way."),
RvError::SessionReadOnly => write!(f, "The specified session was unable to accomplish the desired action because it is a read-only session. This return value has lower priority than CKR_TOKEN_WRITE_PROTECTED."),
RvError::SessionExists => write!(f, "This value can only be returned by C_InitToken. It indicates that a session with the token is already open, and so the token cannot be initialized."),
RvError::SessionReadOnlyExists => write!(f, "A read-only session already exists, and so the SO cannot be logged in."),
RvError::SessionReadWriteSoExists => write!(f, "A read/write SO session already exists, and so a read-only session cannot be opened."),
RvError::SignatureInvalid => write!(f, "The provided signature/MAC is invalid. This return value has lower priority than CKR_SIGNATURE_LEN_RANGE."),
RvError::SignatureLenRange => write!(f, "The provided signature/MAC can be seen to be invalid solely on the basis of its length. This return value has higher priority than CKR_SIGNATURE_INVALID."),
RvError::TemplateIncomplete => write!(f, "The template specified for creating an object is incomplete, and lacks some necessary attributes. See Section 4.1 for more information."),
RvError::TemplateInconsistent => write!(f, "The template specified for creating an object has conflicting attributes. See Section 4.1 for more information."),
RvError::TokenNotPresent => write!(f, "The token was not present in its slot at the time that the function was invoked."),
RvError::TokenNotRecognized => write!(f, "The Cryptoki library and/or slot does not recognize the token in the slot."),
RvError::TokenWriteProtected => write!(f, "The requested action could not be performed because the token is write-protected. This return value has higher priority than CKR_SESSION_READ_ONLY."),
RvError::UnwrappingKeyHandleInvalid => write!(f, "This value can only be returned by C_UnwrapKey. It indicates that the key handle specified to be used to unwrap another key is not valid."),
RvError::UnwrappingKeySizeRange => write!(f, "This value can only be returned by C_UnwrapKey. It indicates that although the requested unwrapping operation could in principle be carried out, this Cryptoki library (or the token) is unable to actually do it because the supplied key’s size is outside the range of key sizes that it can handle."),
RvError::UnwrappingKeyTypeInconsistent => write!(f, "This value can only be returned by C_UnwrapKey. It indicates that the type of the key specified to unwrap another key is not consistent with the mechanism specified for unwrapping."),
RvError::UserAlreadyLoggedIn => write!(f, "This value can only be returned by C_Login. It indicates that the specified user cannot be logged into the session, because it is already logged into the session. For example, if an application has an open SO session, and it attempts to log the SO into it, it will receive this error code."),
RvError::UserNotLoggedIn => write!(f, "The desired action cannot be performed because the appropriate user (or an appropriate user) is not logged in. One example is that a session cannot be logged out unless it is logged in. Another example is that a private object cannot be created on a token unless the session attempting to create it is logged in as the normal user. A final example is that cryptographic operations on certain tokens cannot be performed unless the normal user is logged in."),
RvError::UserPinNotInitialized => write!(f, "This value can only be returned by C_Login. It indicates that the normal user’s PIN has not yet been initialized with C_InitPIN."),
RvError::UserTypeInvalid => write!(f, "An invalid value was specified as a CK_USER_TYPE. Valid types are CKU_SO, CKU_USER, and CKU_CONTEXT_SPECIFIC."),
RvError::UserAnotherAlreadyLoggedIn => write!(f, "This value can only be returned by C_Login. It indicates that the specified user cannot be logged into the session, because another user is already logged into the session. For example, if an application has an open SO session, and it attempts to log the normal user into it, it will receive this error code."),
RvError::UserTooManyTypes => write!(f, "An attempt was made to have more distinct users simultaneously logged into the token than the token and/or library permits. For example, if some application has an open SO session, and another application attempts to log the normal user into a session, the attempt may return this error. It is not required to, however. Only if the simultaneous distinct users cannot be supported does C_Login have to return this value. Note that this error code generalizes to true multi-user tokens."),
RvError::WrappedKeyInvalid => write!(f, "This value can only be returned by C_UnwrapKey. It indicates that the provided wrapped key is not valid. If a call is made to C_UnwrapKey to unwrap a particular type of key (i.e., some particular key type is specified in the template provided to C_UnwrapKey), and the wrapped key provided to C_UnwrapKey is recognizably not a wrapped key of the proper type, then C_UnwrapKey should return CKR_WRAPPED_KEY_INVALID. This return value has lower priority than CKR_WRAPPED_KEY_LEN_RANGE."),
RvError::WrappedKeyLenRange => write!(f, "This value can only be returned by C_UnwrapKey. It indicates that the provided wrapped key can be seen to be invalid solely on the basis of its length. This return value has higher priority than CKR_WRAPPED_KEY_INVALID."),
RvError::WrappingKeyHandleInvalid => write!(f, "This value can only be returned by C_WrapKey. It indicates that the key handle specified to be used to wrap another key is not valid."),
RvError::WrappingKeySizeRange => write!(f, "This value can only be returned by C_WrapKey. It indicates that although the requested wrapping operation could in principle be carried out, this Cryptoki library (or the token) is unable to actually do it because the supplied wrapping key’s size is outside the range of key sizes that it can handle."),
RvError::WrappingKeyTypeInconsistent => write!(f, "This value can only be returned by C_WrapKey. It indicates that the type of the key specified to wrap another key is not consistent with the mechanism specified for wrapping."),
RvError::RandomSeedNotSupported => write!(f, "This value can only be returned by C_SeedRandom. It indicates that the token’s random number generator does not accept seeding from an application. This return value has lower priority than CKR_RANDOM_NO_RNG."),
RvError::RandomNoRng => write!(f, "This value can be returned by C_SeedRandom and C_GenerateRandom. It indicates that the specified token doesn’t have a random number generator. This return value has higher priority than CKR_RANDOM_SEED_NOT_SUPPORTED."),
RvError::DomainParamsInvalid => write!(f, "Invalid or unsupported domain parameters were supplied to the function. Which representation methods of domain parameters are supported by a given mechanism can vary from token to token."),
RvError::BufferTooSmall => write!(f, "The output of the function is too large to fit in the supplied buffer."),
RvError::SavedStateInvalid => write!(f, "This value can only be returned by C_SetOperationState. It indicates that the supplied saved cryptographic operations state is invalid, and so it cannot be restored to the specified session."),
RvError::InformationSensitive => write!(f, "The information requested could not be obtained because the token considers it sensitive, and is not able or willing to reveal it."),
RvError::StateUnsaveable => write!(f, "The cryptographic operations state of the specified session cannot be saved for some reason (possibly the token is simply unable to save the current state). This return value has lower priority than CKR_OPERATION_NOT_INITIALIZED."),
RvError::CryptokiNotInitialized => write!(f, "This value can be returned by any function other than C_Initialize and C_GetFunctionList. It indicates that the function cannot be executed because the Cryptoki library has not yet been initialized by a call to C_Initialize."),
RvError::CryptokiAlreadyInitialized => write!(f, "This value can only be returned by C_Initialize. It means that the Cryptoki library has already been initialized (by a previous call to C_Initialize which did not have a matching C_Finalize call)."),
RvError::MutexBad => write!(f, "This error code can be returned by mutex-handling functions that are passed a bad mutex object as an argument. Unfortunately, it is possible for such a function not to recognize a bad mutex object. There is therefore no guarantee that such a function will successfully detect bad mutex objects and return this value."),
RvError::MutexNotLocked => write!(f, "This error code can be returned by mutex-unlocking functions. It indicates that the mutex supplied to the mutex-unlocking function was not locked."),
RvError::NewPinMode => write!(f, "CKR_NEW_PIN_MODE"),
RvError::NextOtp => write!(f, "CKR_NEXT_OTP"),
RvError::ExceededMaxIterations => write!(f, "An iterative algorithm (for key pair generation, domain parameter generation etc.) failed because we have exceeded the maximum number of iterations. This error code has precedence over CKR_FUNCTION_FAILED. Examples of iterative algorithms include DSA signature generation (retry if either r = 0 or s = 0) and generation of DSA primes p and q specified in FIPS 186-4."),
RvError::FipsSelfTestFailed => write!(f, "A FIPS 140-2 power-up self-test or conditional self-test failed. The token entered an error state. Future calls to cryptographic functions on the token will return CKR_GENERAL_ERROR. CKR_FIPS_SELF_TEST_FAILED has a higher precedence over CKR_GENERAL_ERROR. This error may be returned by C_Initialize, if a power-up self-test failed, by C_GenerateRandom or C_SeedRandom, if the continuous random number generator test failed, or by C_GenerateKeyPair, if the pair-wise consistency test failed."),
RvError::LibraryLoadFailed => write!(f, "The Cryptoki library could not load a dependent shared library."),
RvError::PinTooWeak => write!(f, "The specified PIN is too weak so that it could be easy to guess. If the PIN is too short, CKR_PIN_LEN_RANGE should be returned instead. This return code only applies to functions which attempt to set a PIN."),
RvError::PublicKeyInvalid => write!(f, "The public key fails a public key validation. For example, an EC public key fails the public key validation specified in Section 5.2.2 of ANSI X9.62. This error code may be returned by C_CreateObject, when the public key is created, or by C_VerifyInit or C_VerifyRecoverInit, when the public key is used. It may also be returned by C_DeriveKey, in preference to CKR_MECHANISM_PARAM_INVALID, if the other party's public key specified in the mechanism's parameters is invalid."),
RvError::FunctionRejected => write!(f, "The signature request is rejected by the user."),
RvError::VendorDefined => write!(f, "CKR_VENDOR_DEFINED"),
}
}
}
cryptoki-0.6.1/src/lib.rs 0000644 0000000 0000000 00000005603 10461020230 0013403 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Rust PKCS11 new abstraction
//!
//! The items in the new module only expose idiomatic and safe Rust types and functions to
//! interface with the PKCS11 API. All the PKCS11 items might not be implemented but everything
//! that is implemented is safe.
//!
//! The modules under `new` follow the structure of the PKCS11 document version 2.40 available [here](http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html).
//!
//! # Conformance Notes
//!
//! Throughout this crate, many functions and other items include additional
//! "**Conformance**" notes. These notes may provide guarantees about behavior or
//! additional, contextual information. In all cases, such items pertain
//! to information from the PKCS#11 standard and are contingent on the provider
//! being accessed through this crate conforming to that standard. That is, this
//! crate is permitted to *assume* these guarantees, and is does not necessarily
//! check for or enforce them itself.
// This list comes from
// https://github.com/rust-unofficial/patterns/blob/master/anti_patterns/deny-warnings.md
#![allow(renamed_and_removed_lints, unknown_lints)]
#![deny(bad_style,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
no_mangle_generic_items,
overflowing_literals,
path_statements ,
patterns_in_fns_without_body,
private_bounds,
private_in_public,
private_interfaces,
renamed_and_removed_lints,
unconditional_recursion,
unnameable_types,
unused,
unused_allocation,
unused_comparisons,
unused_parens,
while_true,
missing_debug_implementations,
missing_copy_implementations,
missing_docs,
// Useful to cast to raw pointers
//trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results)]
// Warning: The context module defines the
// get_pkcs11() macro, which must be defined before
// any modules that use it are declared.
#[macro_use]
pub mod context;
pub mod error;
pub mod mechanism;
pub mod object;
pub mod session;
pub mod slot;
pub mod types;
use cryptoki_sys::CK_UTF8CHAR;
fn string_from_blank_padded(field: &[CK_UTF8CHAR]) -> String {
let decoded_str = String::from_utf8_lossy(field);
decoded_str.trim_end_matches(' ').to_string()
}
fn label_from_str(label: &str) -> [CK_UTF8CHAR; 32] {
let mut lab: [CK_UTF8CHAR; 32] = [32; 32];
let mut i = 0;
for c in label.chars() {
if i + c.len_utf8() <= 32 {
let mut buf = [0; 4];
let bytes = c.encode_utf8(&mut buf).as_bytes();
for b in bytes {
lab[i] = *b;
i += 1;
}
} else {
break;
}
}
lab
}
cryptoki-0.6.1/src/mechanism/aead.rs 0000644 0000000 0000000 00000006355 10461020230 0015500 0 ustar 0000000 0000000 // Copyright 2023 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! AEAD block cipher mechanism types
use crate::types::Ulong;
use cryptoki_sys::*;
use std::convert::TryInto;
use std::marker::PhantomData;
use std::slice;
/// Parameters for AES-GCM.
#[derive(Debug, Clone, Copy)]
#[repr(transparent)]
pub struct GcmParams<'a> {
inner: CK_GCM_PARAMS,
_marker: PhantomData<&'a [u8]>,
}
impl<'a> GcmParams<'a> {
/// Construct GCM parameters.
///
/// # Arguments
///
/// `iv` - The initialization vector. This must be non-empty. In PKCS#11
/// 2.40, the maximum length of the IV is 256 bytes. A 12-byte IV may be
/// processed more efficiently than other lengths.
///
/// `aad` - The additional authenticated data. This data is authenticated
/// but not encrypted. This may be between 0 and 2^32-1 bytes.
///
/// `tag_bits` - The length, in **bits**, of the authentication tag. Must
/// be between 0 and 128. The tag is appended to the end of the
/// ciphertext.
///
/// # Panics
///
/// This function panics if the length of `iv` or `aad` does not
/// fit into an [Ulong].
pub fn new(iv: &'a [u8], aad: &'a [u8], tag_bits: Ulong) -> Self {
// The ulIvBits parameter seems to be missing from the 2.40 spec,
// although it is included in the header file. In [1], OASIS clarified
// that the header file is normative. In 3.0, they added the parameter
// to the spec, but it seems to be unused:
//
// > Do not use ulIvBits to specify the length of the initialization
// > vector, but ulIvLen instead.
//
// Further, in v3.0, the IV is permitted to be up to 2^32-1 bytes,
// which would cause ulIvBits to overflow on platforms where
// sizeof(CK_ULONG) = 4.
//
// In light of all this, we include ulIvBits in the struct, but always
// set it to zero.
//
// [1]: https://www.oasis-open.org/committees/document.php?document_id=58032&wg_abbrev=pkcs11
GcmParams {
inner: CK_GCM_PARAMS {
pIv: iv.as_ptr() as *mut _,
ulIvLen: iv
.len()
.try_into()
.expect("iv length does not fit in CK_ULONG"),
ulIvBits: 0,
pAAD: aad.as_ptr() as *mut _,
ulAADLen: aad
.len()
.try_into()
.expect("aad length does not fit in CK_ULONG"),
ulTagBits: tag_bits.into(),
},
_marker: PhantomData,
}
}
/// The initialization vector.
pub fn iv(&self) -> &'a [u8] {
// SAFETY: In the constructor, the IV always comes from a &'a [u8]
unsafe { slice::from_raw_parts(self.inner.pIv, self.inner.ulIvLen as _) }
}
/// The additional authenticated data.
pub fn aad(&self) -> &'a [u8] {
// SAEFTY: In the constructor, the AAD always comes from a &'a [u8]
unsafe { slice::from_raw_parts(self.inner.pAAD, self.inner.ulAADLen as _) }
}
/// The length, in bits, of the authentication tag.
pub fn tag_bits(&self) -> Ulong {
self.inner.ulTagBits.into()
}
}
cryptoki-0.6.1/src/mechanism/elliptic_curve.rs 0000644 0000000 0000000 00000007063 10461020230 0017614 0 ustar 0000000 0000000 //! ECDH mechanism types
use crate::types::Ulong;
use cryptoki_sys::*;
use std::convert::TryInto;
use std::marker::PhantomData;
use std::ptr;
/// ECDH derivation parameters.
///
/// The elliptic curve Diffie-Hellman (ECDH) key derivation mechanism
/// is a mechanism for key derivation based on the Diffie-Hellman
/// version of the elliptic curve key agreement scheme, as defined in
/// ANSI X9.63, where each party contributes one key pair all using
/// the same EC domain parameters.
///
/// This structure wraps a `CK_ECDH1_DERIVE_PARAMS` structure.
#[derive(Copy, Debug, Clone)]
#[repr(C)]
pub struct Ecdh1DeriveParams<'a> {
/// Key derivation function
kdf: CK_EC_KDF_TYPE,
/// Length of the optional shared data used by some of the key
/// derivation functions
shared_data_len: Ulong,
/// Address of the optional data or `std::ptr::null()` of there is
/// no shared data
shared_data: *const u8,
/// Length of the other party's public key
public_data_len: Ulong,
/// Pointer to the other party public key
public_data: *const u8,
/// Marker type to ensure we don't outlive shared and public data
_marker: PhantomData<&'a [u8]>,
}
impl<'a> Ecdh1DeriveParams<'a> {
/// Construct ECDH derivation parameters.
///
/// # Arguments
///
/// * `kdf` - The key derivation function to use.
///
/// * `public_data` - The other party's public key. A token MUST be able
/// to accept this value encoded as a raw octet string (as per section
/// A.5.2 of ANSI X9.62). A token MAY, in addition, support accepting
/// this value as a DER-encoded `ECPoint` (as per section E.6 of ANSI
/// X9.62) i.e. the same as a `CKA_EC_POINT` encoding. The calling
/// application is responsible for converting the offered public key to the
/// compressed or uncompressed forms of these encodings if the token does
/// not support the offered form.
pub fn new(kdf: EcKdf<'a>, public_data: &'a [u8]) -> Self {
Self {
kdf: kdf.kdf_type,
shared_data_len: kdf
.shared_data
.map_or(0, <[u8]>::len)
.try_into()
.expect("usize can not fit in CK_ULONG"),
shared_data: kdf.shared_data.map_or(ptr::null(), <[u8]>::as_ptr),
public_data_len: public_data
.len()
.try_into()
.expect("usize can not fit in CK_ULONG"),
public_data: public_data.as_ptr(),
_marker: PhantomData,
}
}
}
/// Key Derivation Function applied to derive keying data from a shared secret.
///
/// The key derivation function will be used by the EC key agreement schemes.
///
/// The lifetime parameter represents the lifetime of the shared data used by
/// the KDF. In the current version of this crate, only the null KDF is
/// supported, which takes no shared data. Therefore `'a` can always be inferred
/// `'static`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EcKdf<'a> {
kdf_type: CK_EC_KDF_TYPE,
shared_data: Option<&'a [u8]>,
}
impl<'a> EcKdf<'a> {
/// The null transformation. The derived key value is produced by
/// taking bytes from the left of the agreed value. The new key
/// size is limited to the size of the agreed value.
pub fn null() -> Self {
Self {
kdf_type: CKD_NULL,
shared_data: None,
}
}
// The intention here is to be able to support other methods with
// shared data, without it being a breaking change, by just adding
// additional constructors here.
}
cryptoki-0.6.1/src/mechanism/mechanism_info.rs 0000644 0000000 0000000 00000022060 10461020230 0017554 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Mechanism info and associated flags
use bitflags::bitflags;
use cryptoki_sys::*;
use std::fmt::Debug;
bitflags! {
struct MechanismInfoFlags: CK_FLAGS {
const HW = CKF_HW;
const ENCRYPT = CKF_ENCRYPT;
const DECRYPT = CKF_DECRYPT;
const DIGEST = CKF_DIGEST;
const SIGN = CKF_SIGN;
const SIGN_RECOVER = CKF_SIGN_RECOVER;
const VERIFY = CKF_VERIFY;
const VERIFY_RECOVER = CKF_VERIFY_RECOVER;
const GENERATE = CKF_GENERATE;
const GENERATE_KEY_PAIR = CKF_GENERATE_KEY_PAIR;
const WRAP = CKF_WRAP;
const UNWRAP = CKF_UNWRAP;
const DERIVE = CKF_DERIVE;
const EXTENSION = CKF_EXTENSION;
const EC_F_P = CKF_EC_F_P;
const EC_F_2M = CKF_EC_F_2M;
const EC_ECPARAMETERS = CKF_EC_ECPARAMETERS;
const EC_NAMEDCURVE = CKF_EC_NAMEDCURVE;
const EC_UNCOMPRESS = CKF_EC_UNCOMPRESS;
const EC_COMPRESS = CKF_EC_COMPRESS;
}
}
/// Information about a particular mechanism
#[derive(Debug, Clone, Copy)]
pub struct MechanismInfo {
min_key_size: usize,
max_key_size: usize,
flags: MechanismInfoFlags,
}
impl MechanismInfo {
/// The minimum size of the key for the mechanism
///
/// **[Conformance](crate#conformance-notes):**
/// Whether this is measured in bits or in bytes is mechanism-dependent.
/// For some mechanisms, this field may be meaningless and take any value.
pub fn min_key_size(&self) -> usize {
self.min_key_size
}
/// The maximum size of the key for the mechanism
///
/// **[Conformance](crate#conformance-notes):**
/// Whether this is measured in bits or in bytes is mechanism-dependent
/// For some mechanisms, this field may be meaningless and take any value.
pub fn max_key_size(&self) -> usize {
self.max_key_size
}
/// True if the mechanism is performed by the device; false if the
/// mechanism is performed in software
pub fn hardware(&self) -> bool {
self.flags.contains(MechanismInfoFlags::HW)
}
/// True if the mechanism can be used to encrypt data
///
/// See [`Session::encrypt`](crate::session::Session::encrypt)
pub fn encrypt(&self) -> bool {
self.flags.contains(MechanismInfoFlags::ENCRYPT)
}
/// True if the mechanism can be used to decrypt encrypted data
///
/// See [`Session::decrypt`](crate::session::Session::decrypt)
pub fn decrypt(&self) -> bool {
self.flags.contains(MechanismInfoFlags::DECRYPT)
}
/// True if the mechanism can be used to digest a message
///
// TODO See [`Session::digest`](crate::session::Session::digest)
pub fn digest(&self) -> bool {
self.flags.contains(MechanismInfoFlags::DIGEST)
}
/// True if the mechanism can be used to digitally sign data
///
/// See [`Session::sign`](crate::session::Session::sign)
pub fn sign(&self) -> bool {
self.flags.contains(MechanismInfoFlags::SIGN)
}
/// True if the mechanism can be used to digitally data which can be
/// recovered from the signature
///
// TODO See [`Session::sign_recover`](crate::session::Session::sign_recover)
pub fn sign_recover(&self) -> bool {
self.flags.contains(MechanismInfoFlags::SIGN_RECOVER)
}
/// True if the mechanism can be used to verify a digital signature
///
/// See [`Session::verify`](crate::session::Session::verify)
pub fn verify(&self) -> bool {
self.flags.contains(MechanismInfoFlags::VERIFY)
}
/// True if the mechanism can be used to verify a digital signature and
/// recover the signed data
///
// TODO See [`Session::verify_recover`](crate::session::Session::verify_recover)
pub fn verify_recover(&self) -> bool {
self.flags.contains(MechanismInfoFlags::VERIFY_RECOVER)
}
/// True if the mechanism can be used to generate a secret key
///
// TODO See [`Session::generate`](crate::session::Session::generate)
pub fn generate(&self) -> bool {
self.flags.contains(MechanismInfoFlags::GENERATE)
}
/// True if the mechanism can be used to generate a public/private key pair
///
/// See [`Session::generate_key_pair`](crate::session::Session::generate_key_pair))
pub fn generate_key_pair(&self) -> bool {
self.flags.contains(MechanismInfoFlags::GENERATE_KEY_PAIR)
}
/// True if the mechanism can be used to wrap (encrypt) a key
///
// TODO See [`Session::wrap`](crate::session::Session::wrap))
pub fn wrap(&self) -> bool {
self.flags.contains(MechanismInfoFlags::WRAP)
}
/// True if the mechanism can be used to unwrap (decrypt) a key
///
// TODO See [`Session::unwrap`](crate::session::Session::unwrap))
pub fn unwrap(&self) -> bool {
self.flags.contains(MechanismInfoFlags::UNWRAP)
}
/// True if the mechanism can be used to derive a key from a base key
///
// TODO See [`Session::derive`](crate::session::Session::derive))
pub fn derive(&self) -> bool {
self.flags.contains(MechanismInfoFlags::DERIVE)
}
/// True if there is an extension to the flags; false if no extensions
///
/// **[Conformance](crate#conformance-notes):**
/// This *must* be false for PKCS#11 v2.40
pub fn extension(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EXTENSION)
}
/// True if the mechanism can be used to with elliptic curve domain
/// parameters over ***Fp ***
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_f_p`](Self::ec_f_p) and
/// [`ec_f_2m`](Self::ec_f_2m) must be `true`
pub fn ec_f_p(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_F_P)
}
/// True if the mechanism can be used with elliptic curve domain parameters
/// over ***F2m ***
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_f_p`](Self::ec_f_p) and
/// [`ec_f_2m`](Self::ec_f_2m) must be `true`
pub fn ec_f_2m(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_F_2M)
}
/// True if the mechanism supports specifying elliptic curve domain
/// parameters explicitly
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_from_parameters`](Self::ec_from_parameters) and
/// [`ec_from_named_curve`](Self::ec_from_named_curve) must be `true`
pub fn ec_from_parameters(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_ECPARAMETERS)
}
/// True if the mechanism supports specifying elliptic curve domain
/// parameters with a named curve
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_from_parameters`](Self::ec_from_parameters) and
/// [`ec_from_named_curve`](Self::ec_from_named_curve) must be `true`
pub fn ec_from_named_curve(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_NAMEDCURVE)
}
/// True if the mechanism can be used with elliptic curve points in
/// uncompressed form
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_uncompressed`](Self::ec_uncompressed) and
/// [`ec_compressed`](Self::ec_compressed) must be `true`
pub fn ec_uncompressed(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_UNCOMPRESS)
}
/// True if the mechanism can be used with elliptic curve points in
/// compressed form
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_uncompressed`](Self::ec_uncompressed) and
/// [`ec_compressed`](Self::ec_compressed) must be `true`
pub fn ec_compressed(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_COMPRESS)
}
}
#[doc(hidden)]
impl From for MechanismInfo {
fn from(val: CK_MECHANISM_INFO) -> Self {
Self {
min_key_size: val.ulMinKeySize as usize,
max_key_size: val.ulMaxKeySize as usize,
flags: MechanismInfoFlags::from_bits_truncate(val.flags),
}
}
}
#[cfg(test)]
mod test {
use super::{MechanismInfo, MechanismInfoFlags};
#[test]
fn debug_flags_all() {
let expected = "\
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_UNCOMPRESS | EC_COMPRESS";
let all = MechanismInfoFlags::all();
let observed = format!("{all:#?}");
println!("{observed}");
assert_eq!(observed, expected);
}
#[test]
fn debug_info() {
let info = MechanismInfo {
min_key_size: 16,
max_key_size: 4096,
flags: MechanismInfoFlags::empty(),
};
let expected = r#"MechanismInfo {
min_key_size: 16,
max_key_size: 4096,
flags: (empty),
}"#;
let observed = format!("{info:#?}");
assert_eq!(observed, expected);
}
}
cryptoki-0.6.1/src/mechanism/mod.rs 0000644 0000000 0000000 00000147254 10461020230 0015371 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Data types for mechanisms
pub mod aead;
pub mod elliptic_curve;
mod mechanism_info;
pub mod rsa;
use crate::error::Error;
use cryptoki_sys::*;
use log::error;
use std::convert::{TryFrom, TryInto};
use std::ffi::c_void;
use std::fmt::Formatter;
use std::ops::Deref;
use std::ptr::null_mut;
pub use mechanism_info::MechanismInfo;
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
// transparent so that a vector of MechanismType should have the same layout than a vector of
// CK_MECHANISM_TYPE.
/// Type of a mechanism
#[repr(transparent)]
pub struct MechanismType {
val: CK_MECHANISM_TYPE,
}
impl MechanismType {
// AES
/// AES key generation mechanism
pub const AES_KEY_GEN: MechanismType = MechanismType {
val: CKM_AES_KEY_GEN,
};
/// AES-CBC mechanism
///
/// For encryption, the message length must be a multiple of the block
/// size. For wrapping, the mechanism encrypts the value of the key,
/// padded on the trailing end with up to block size minus one null bytes.
/// For unwrapping, the result is truncated according to the key type and
/// the length provided by the template.
pub const AES_CBC: MechanismType = MechanismType { val: CKM_AES_CBC };
/// AES-CBC with PKCS#7 padding mechanism
///
/// The plaintext may be any size. The PKCS#7 padding allows the length of
/// the plaintext to be recovered from the ciphertext. Therefore no length
/// should be provided when unwrapping keys with this mechanism.
pub const AES_CBC_PAD: MechanismType = MechanismType {
val: CKM_AES_CBC_PAD,
};
/// AES-ECB mechanism
pub const AES_ECB: MechanismType = MechanismType { val: CKM_AES_ECB };
/// AES key wrap mechanism. This mechanism can only wrap a key or encrypt a block of data
/// whose length is a multiple of the AES Key Wrap algorithm block size.
pub const AES_KEY_WRAP: MechanismType = MechanismType {
val: CKM_AES_KEY_WRAP,
};
/// AES key wrap mechanism. This mechanism can wrap a key or encrypt a block of data of any
/// length. It does the padding detailed in PKCS#7 of inputs.
pub const AES_KEY_WRAP_PAD: MechanismType = MechanismType {
val: CKM_AES_KEY_WRAP_PAD,
};
/// AES-GCM mechanism
pub const AES_GCM: MechanismType = MechanismType { val: CKM_AES_GCM };
// RSA
/// PKCS #1 RSA key pair generation mechanism
pub const RSA_PKCS_KEY_PAIR_GEN: MechanismType = MechanismType {
val: CKM_RSA_PKCS_KEY_PAIR_GEN,
};
/// Multi-purpose mechanism based on the RSA public-key cryptosystem and the block formats
/// initially defined in PKCS #1 v1.5
pub const RSA_PKCS: MechanismType = MechanismType { val: CKM_RSA_PKCS };
/// Mechanism based on the RSA public-key cryptosystem and the PSS block format defined in PKCS
/// #1
pub const RSA_PKCS_PSS: MechanismType = MechanismType {
val: CKM_RSA_PKCS_PSS,
};
/// Multi-purpose mechanism based on the RSA public-key cryptosystem and the OAEP block format
/// defined in PKCS #1
pub const RSA_PKCS_OAEP: MechanismType = MechanismType {
val: CKM_RSA_PKCS_OAEP,
};
/// Multi-purpose mechanism based on the RSA public-key cryptosystem. This is so-called "raw"
/// RSA, as assumed in X.509.
pub const RSA_X_509: MechanismType = MechanismType { val: CKM_RSA_X_509 };
// DES
/// DES
/// Note that DES is deprecated. See section 2, p. 6.
pub const DES_KEY_GEN: MechanismType = MechanismType {
val: CKM_DES_KEY_GEN,
};
/// DES2
/// Note that DES2 is deprecated. See section 2, p. 6.
pub const DES2_KEY_GEN: MechanismType = MechanismType {
val: CKM_DES2_KEY_GEN,
};
/// DES3
/// Note that DES3 is deprecated. See section 2, p. 6.
pub const DES3_KEY_GEN: MechanismType = MechanismType {
val: CKM_DES3_KEY_GEN,
};
/// DES-CBC mechanism.
///
/// For encryption, the message length must be a multiple of the block
/// size. For wrapping, the mechanism encrypts the value of the key,
/// padded on the trailing end with up to block size minus one null bytes.
/// For unwrapping, the result is truncated according to the key type and
/// the length provided by the template.
pub const DES_CBC: MechanismType = MechanismType { val: CKM_DES_CBC };
/// DES3-CBC mechanism.
///
/// For encryption, the message length must be a multiple of the block
/// size. For wrapping, the mechanism encrypts the value of the key,
/// padded on the trailing end with up to block size minus one null bytes.
/// For unwrapping, the result is truncated according to the key type and
/// the length provided by the template.
pub const DES3_CBC: MechanismType = MechanismType { val: CKM_DES3_CBC };
/// DES-CBC with PKCS#7 padding mechanism
///
/// The plaintext may be any size. The PKCS#7 padding allows the length of
/// the plaintext to be recovered from the ciphertext. Therefore no length
/// should be provided when unwrapping keys with this mechanism.
pub const DES_CBC_PAD: MechanismType = MechanismType {
val: CKM_DES_CBC_PAD,
};
/// DES3-CBC with PKCS#7 padding mechanism
///
/// The plaintext may be any size. The PKCS#7 padding allows the length of
/// the plaintext to be recovered from the ciphertext. Therefore no length
/// should be provided when unwrapping keys with this mechanism.
pub const DES3_CBC_PAD: MechanismType = MechanismType {
val: CKM_DES3_CBC_PAD,
};
/// DES ECB
/// Note that DES is deprecated. See section 2, p. 6.
pub const DES_ECB: MechanismType = MechanismType { val: CKM_DES_ECB };
/// DES3 ECB
/// Note that DES3 is deprecated. See section 2, p. 6.
pub const DES3_ECB: MechanismType = MechanismType { val: CKM_DES3_ECB };
// ECC
/// EC key pair generation mechanism
pub const ECC_KEY_PAIR_GEN: MechanismType = MechanismType {
val: CKM_EC_KEY_PAIR_GEN,
};
/// EC edwards key pair generation mechanism
pub const ECC_EDWARDS_KEY_PAIR_GEN: MechanismType = MechanismType {
val: CKM_EC_EDWARDS_KEY_PAIR_GEN,
};
/// EC montgomery key pair generation mechanism
pub const ECC_MONTGOMERY_KEY_PAIR_GEN: MechanismType = MechanismType {
val: CKM_EC_MONTGOMERY_KEY_PAIR_GEN,
};
/// EDDSA mechanism
///
/// Note: EdDSA is not part of the PKCS#11 v2.40 standard and as
/// such may not be understood by the backend. It is included here
/// because some vendor implementations support it through the
/// v2.40 interface.
pub const EDDSA: MechanismType = MechanismType { val: CKM_EDDSA };
/// ECDH key derivation mechanism
pub const ECDH1_DERIVE: MechanismType = MechanismType {
val: CKM_ECDH1_DERIVE,
};
/// ECDSA mechanism
pub const ECDSA: MechanismType = MechanismType { val: CKM_ECDSA };
/// ECDSA with SHA-1 mechanism
pub const ECDSA_SHA1: MechanismType = MechanismType {
val: CKM_ECDSA_SHA1,
};
/// ECDSA with SHA-224 mechanism
pub const ECDSA_SHA224: MechanismType = MechanismType {
val: CKM_ECDSA_SHA224,
};
/// ECDSA with SHA-256 mechanism
pub const ECDSA_SHA256: MechanismType = MechanismType {
val: CKM_ECDSA_SHA256,
};
/// ECDSA with SHA-384 mechanism
pub const ECDSA_SHA384: MechanismType = MechanismType {
val: CKM_ECDSA_SHA384,
};
/// ECDSA with SHA-512 mechanism
pub const ECDSA_SHA512: MechanismType = MechanismType {
val: CKM_ECDSA_SHA512,
};
// SHA-n
/// SHA-1 mechanism
pub const SHA1: MechanismType = MechanismType { val: CKM_SHA_1 };
/// SHA-224 mechanism
pub const SHA224: MechanismType = MechanismType { val: CKM_SHA224 };
/// SHA-256 mechanism
pub const SHA256: MechanismType = MechanismType { val: CKM_SHA256 };
/// SHA-384 mechanism
pub const SHA384: MechanismType = MechanismType { val: CKM_SHA384 };
/// SHA-512 mechanism
pub const SHA512: MechanismType = MechanismType { val: CKM_SHA512 };
// SHAn-RSA-PKCS
/// SHA1-RSA-PKCS mechanism
pub const SHA1_RSA_PKCS: MechanismType = MechanismType {
val: CKM_SHA1_RSA_PKCS,
};
/// SHA224-RSA-PKCS mechanism
pub const SHA224_RSA_PKCS: MechanismType = MechanismType {
val: CKM_SHA224_RSA_PKCS,
};
/// SHA256-RSA-PKCS mechanism
pub const SHA256_RSA_PKCS: MechanismType = MechanismType {
val: CKM_SHA256_RSA_PKCS,
};
/// SHA384-RSA-PKCS mechanism
pub const SHA384_RSA_PKCS: MechanismType = MechanismType {
val: CKM_SHA384_RSA_PKCS,
};
/// SHA512-RSA-PKCS mechanism
pub const SHA512_RSA_PKCS: MechanismType = MechanismType {
val: CKM_SHA512_RSA_PKCS,
};
// SHAn-RSA-PKCS-PSS
/// SHA1-RSA-PKCS-PSS mechanism
pub const SHA1_RSA_PKCS_PSS: MechanismType = MechanismType {
val: CKM_SHA1_RSA_PKCS_PSS,
};
/// SHA256-RSA-PKCS-PSS mechanism
pub const SHA256_RSA_PKCS_PSS: MechanismType = MechanismType {
val: CKM_SHA256_RSA_PKCS_PSS,
};
/// SHA384-RSA-PKCS-PSS mechanism
pub const SHA384_RSA_PKCS_PSS: MechanismType = MechanismType {
val: CKM_SHA384_RSA_PKCS_PSS,
};
/// SHA512-RSA-PKCS-PSS mechanism
pub const SHA512_RSA_PKCS_PSS: MechanismType = MechanismType {
val: CKM_SHA512_RSA_PKCS_PSS,
};
pub(crate) fn stringify(mech: CK_MECHANISM_TYPE) -> String {
match mech {
CKM_RSA_PKCS_KEY_PAIR_GEN => String::from(stringify!(CKM_RSA_PKCS_KEY_PAIR_GEN)),
CKM_RSA_PKCS => String::from(stringify!(CKM_RSA_PKCS)),
CKM_RSA_9796 => String::from(stringify!(CKM_RSA_9796)),
CKM_RSA_X_509 => String::from(stringify!(CKM_RSA_X_509)),
CKM_MD2_RSA_PKCS => String::from(stringify!(CKM_MD2_RSA_PKCS)),
CKM_MD5_RSA_PKCS => String::from(stringify!(CKM_MD5_RSA_PKCS)),
CKM_SHA1_RSA_PKCS => String::from(stringify!(CKM_SHA1_RSA_PKCS)),
CKM_RIPEMD128_RSA_PKCS => String::from(stringify!(CKM_RIPEMD128_RSA_PKCS)),
CKM_RIPEMD160_RSA_PKCS => String::from(stringify!(CKM_RIPEMD160_RSA_PKCS)),
CKM_RSA_PKCS_OAEP => String::from(stringify!(CKM_RSA_PKCS_OAEP)),
CKM_RSA_X9_31_KEY_PAIR_GEN => String::from(stringify!(CKM_RSA_X9_31_KEY_PAIR_GEN)),
CKM_RSA_X9_31 => String::from(stringify!(CKM_RSA_X9_31)),
CKM_SHA1_RSA_X9_31 => String::from(stringify!(CKM_SHA1_RSA_X9_31)),
CKM_RSA_PKCS_PSS => String::from(stringify!(CKM_RSA_PKCS_PSS)),
CKM_SHA1_RSA_PKCS_PSS => String::from(stringify!(CKM_SHA1_RSA_PKCS_PSS)),
CKM_DSA_KEY_PAIR_GEN => String::from(stringify!(CKM_DSA_KEY_PAIR_GEN)),
CKM_DSA => String::from(stringify!(CKM_DSA)),
CKM_DSA_SHA1 => String::from(stringify!(CKM_DSA_SHA1)),
CKM_DSA_SHA224 => String::from(stringify!(CKM_DSA_SHA224)),
CKM_DSA_SHA256 => String::from(stringify!(CKM_DSA_SHA256)),
CKM_DSA_SHA384 => String::from(stringify!(CKM_DSA_SHA384)),
CKM_DSA_SHA512 => String::from(stringify!(CKM_DSA_SHA512)),
CKM_DH_PKCS_KEY_PAIR_GEN => String::from(stringify!(CKM_DH_PKCS_KEY_PAIR_GEN)),
CKM_DH_PKCS_DERIVE => String::from(stringify!(CKM_DH_PKCS_DERIVE)),
CKM_X9_42_DH_KEY_PAIR_GEN => String::from(stringify!(CKM_X9_42_DH_KEY_PAIR_GEN)),
CKM_X9_42_DH_DERIVE => String::from(stringify!(CKM_X9_42_DH_DERIVE)),
CKM_X9_42_DH_HYBRID_DERIVE => String::from(stringify!(CKM_X9_42_DH_HYBRID_DERIVE)),
CKM_X9_42_MQV_DERIVE => String::from(stringify!(CKM_X9_42_MQV_DERIVE)),
CKM_SHA256_RSA_PKCS => String::from(stringify!(CKM_SHA256_RSA_PKCS)),
CKM_SHA384_RSA_PKCS => String::from(stringify!(CKM_SHA384_RSA_PKCS)),
CKM_SHA512_RSA_PKCS => String::from(stringify!(CKM_SHA512_RSA_PKCS)),
CKM_SHA256_RSA_PKCS_PSS => String::from(stringify!(CKM_SHA256_RSA_PKCS_PSS)),
CKM_SHA384_RSA_PKCS_PSS => String::from(stringify!(CKM_SHA384_RSA_PKCS_PSS)),
CKM_SHA512_RSA_PKCS_PSS => String::from(stringify!(CKM_SHA512_RSA_PKCS_PSS)),
CKM_SHA512_224 => String::from(stringify!(CKM_SHA512_224)),
CKM_SHA512_224_HMAC => String::from(stringify!(CKM_SHA512_224_HMAC)),
CKM_SHA512_224_HMAC_GENERAL => String::from(stringify!(CKM_SHA512_224_HMAC_GENERAL)),
CKM_SHA512_224_KEY_DERIVATION => {
String::from(stringify!(CKM_SHA512_224_KEY_DERIVATION))
}
CKM_SHA512_256 => String::from(stringify!(CKM_SHA512_256)),
CKM_SHA512_256_HMAC => String::from(stringify!(CKM_SHA512_256_HMAC)),
CKM_SHA512_256_HMAC_GENERAL => String::from(stringify!(CKM_SHA512_256_HMAC_GENERAL)),
CKM_SHA512_256_KEY_DERIVATION => {
String::from(stringify!(CKM_SHA512_256_KEY_DERIVATION))
}
CKM_SHA512_T => String::from(stringify!(CKM_SHA512_T)),
CKM_SHA512_T_HMAC => String::from(stringify!(CKM_SHA512_T_HMAC)),
CKM_SHA512_T_HMAC_GENERAL => String::from(stringify!(CKM_SHA512_T_HMAC_GENERAL)),
CKM_SHA512_T_KEY_DERIVATION => String::from(stringify!(CKM_SHA512_T_KEY_DERIVATION)),
CKM_RC2_KEY_GEN => String::from(stringify!(CKM_RC2_KEY_GEN)),
CKM_RC2_ECB => String::from(stringify!(CKM_RC2_ECB)),
CKM_RC2_CBC => String::from(stringify!(CKM_RC2_CBC)),
CKM_RC2_MAC => String::from(stringify!(CKM_RC2_MAC)),
CKM_RC2_MAC_GENERAL => String::from(stringify!(CKM_RC2_MAC_GENERAL)),
CKM_RC2_CBC_PAD => String::from(stringify!(CKM_RC2_CBC_PAD)),
CKM_RC4_KEY_GEN => String::from(stringify!(CKM_RC4_KEY_GEN)),
CKM_RC4 => String::from(stringify!(CKM_RC4)),
CKM_DES_KEY_GEN => String::from(stringify!(CKM_DES_KEY_GEN)),
CKM_DES_ECB => String::from(stringify!(CKM_DES_ECB)),
CKM_DES_CBC => String::from(stringify!(CKM_DES_CBC)),
CKM_DES_MAC => String::from(stringify!(CKM_DES_MAC)),
CKM_DES_MAC_GENERAL => String::from(stringify!(CKM_DES_MAC_GENERAL)),
CKM_DES_CBC_PAD => String::from(stringify!(CKM_DES_CBC_PAD)),
CKM_DES2_KEY_GEN => String::from(stringify!(CKM_DES2_KEY_GEN)),
CKM_DES3_KEY_GEN => String::from(stringify!(CKM_DES3_KEY_GEN)),
CKM_DES3_ECB => String::from(stringify!(CKM_DES3_ECB)),
CKM_DES3_CBC => String::from(stringify!(CKM_DES3_CBC)),
CKM_DES3_MAC => String::from(stringify!(CKM_DES3_MAC)),
CKM_DES3_MAC_GENERAL => String::from(stringify!(CKM_DES3_MAC_GENERAL)),
CKM_DES3_CBC_PAD => String::from(stringify!(CKM_DES3_CBC_PAD)),
CKM_DES3_CMAC_GENERAL => String::from(stringify!(CKM_DES3_CMAC_GENERAL)),
CKM_DES3_CMAC => String::from(stringify!(CKM_DES3_CMAC)),
CKM_CDMF_KEY_GEN => String::from(stringify!(CKM_CDMF_KEY_GEN)),
CKM_CDMF_ECB => String::from(stringify!(CKM_CDMF_ECB)),
CKM_CDMF_CBC => String::from(stringify!(CKM_CDMF_CBC)),
CKM_CDMF_MAC => String::from(stringify!(CKM_CDMF_MAC)),
CKM_CDMF_MAC_GENERAL => String::from(stringify!(CKM_CDMF_MAC_GENERAL)),
CKM_CDMF_CBC_PAD => String::from(stringify!(CKM_CDMF_CBC_PAD)),
CKM_DES_OFB64 => String::from(stringify!(CKM_DES_OFB64)),
CKM_DES_OFB8 => String::from(stringify!(CKM_DES_OFB8)),
CKM_DES_CFB64 => String::from(stringify!(CKM_DES_CFB64)),
CKM_DES_CFB8 => String::from(stringify!(CKM_DES_CFB8)),
CKM_MD2 => String::from(stringify!(CKM_MD2)),
CKM_MD2_HMAC => String::from(stringify!(CKM_MD2_HMAC)),
CKM_MD2_HMAC_GENERAL => String::from(stringify!(CKM_MD2_HMAC_GENERAL)),
CKM_MD5 => String::from(stringify!(CKM_MD5)),
CKM_MD5_HMAC => String::from(stringify!(CKM_MD5_HMAC)),
CKM_MD5_HMAC_GENERAL => String::from(stringify!(CKM_MD5_HMAC_GENERAL)),
CKM_SHA_1 => String::from(stringify!(CKM_SHA_1)),
CKM_SHA_1_HMAC => String::from(stringify!(CKM_SHA_1_HMAC)),
CKM_SHA_1_HMAC_GENERAL => String::from(stringify!(CKM_SHA_1_HMAC_GENERAL)),
CKM_RIPEMD128 => String::from(stringify!(CKM_RIPEMD128)),
CKM_RIPEMD128_HMAC => String::from(stringify!(CKM_RIPEMD128_HMAC)),
CKM_RIPEMD128_HMAC_GENERAL => String::from(stringify!(CKM_RIPEMD128_HMAC_GENERAL)),
CKM_RIPEMD160 => String::from(stringify!(CKM_RIPEMD160)),
CKM_RIPEMD160_HMAC => String::from(stringify!(CKM_RIPEMD160_HMAC)),
CKM_RIPEMD160_HMAC_GENERAL => String::from(stringify!(CKM_RIPEMD160_HMAC_GENERAL)),
CKM_SHA256 => String::from(stringify!(CKM_SHA256)),
CKM_SHA256_HMAC => String::from(stringify!(CKM_SHA256_HMAC)),
CKM_SHA256_HMAC_GENERAL => String::from(stringify!(CKM_SHA256_HMAC_GENERAL)),
CKM_SHA384 => String::from(stringify!(CKM_SHA384)),
CKM_SHA384_HMAC => String::from(stringify!(CKM_SHA384_HMAC)),
CKM_SHA384_HMAC_GENERAL => String::from(stringify!(CKM_SHA384_HMAC_GENERAL)),
CKM_SHA512 => String::from(stringify!(CKM_SHA512)),
CKM_SHA512_HMAC => String::from(stringify!(CKM_SHA512_HMAC)),
CKM_SHA512_HMAC_GENERAL => String::from(stringify!(CKM_SHA512_HMAC_GENERAL)),
CKM_SECURID_KEY_GEN => String::from(stringify!(CKM_SECURID_KEY_GEN)),
CKM_SECURID => String::from(stringify!(CKM_SECURID)),
CKM_HOTP_KEY_GEN => String::from(stringify!(CKM_HOTP_KEY_GEN)),
CKM_HOTP => String::from(stringify!(CKM_HOTP)),
CKM_ACTI => String::from(stringify!(CKM_ACTI)),
CKM_ACTI_KEY_GEN => String::from(stringify!(CKM_ACTI_KEY_GEN)),
CKM_CAST_KEY_GEN => String::from(stringify!(CKM_CAST_KEY_GEN)),
CKM_CAST_ECB => String::from(stringify!(CKM_CAST_ECB)),
CKM_CAST_CBC => String::from(stringify!(CKM_CAST_CBC)),
CKM_CAST_MAC => String::from(stringify!(CKM_CAST_MAC)),
CKM_CAST_MAC_GENERAL => String::from(stringify!(CKM_CAST_MAC_GENERAL)),
CKM_CAST_CBC_PAD => String::from(stringify!(CKM_CAST_CBC_PAD)),
CKM_CAST3_KEY_GEN => String::from(stringify!(CKM_CAST3_KEY_GEN)),
CKM_CAST3_ECB => String::from(stringify!(CKM_CAST3_ECB)),
CKM_CAST3_CBC => String::from(stringify!(CKM_CAST3_CBC)),
CKM_CAST3_MAC => String::from(stringify!(CKM_CAST3_MAC)),
CKM_CAST3_MAC_GENERAL => String::from(stringify!(CKM_CAST3_MAC_GENERAL)),
CKM_CAST3_CBC_PAD => String::from(stringify!(CKM_CAST3_CBC_PAD)),
CKM_CAST128_KEY_GEN => String::from(stringify!(CKM_CAST128_KEY_GEN)),
CKM_CAST128_ECB => String::from(stringify!(CKM_CAST128_ECB)),
CKM_CAST128_CBC => String::from(stringify!(CKM_CAST128_CBC)),
CKM_CAST128_MAC => String::from(stringify!(CKM_CAST128_MAC)),
CKM_CAST128_MAC_GENERAL => String::from(stringify!(CKM_CAST128_MAC_GENERAL)),
CKM_CAST128_CBC_PAD => String::from(stringify!(CKM_CAST128_CBC_PAD)),
CKM_RC5_KEY_GEN => String::from(stringify!(CKM_RC5_KEY_GEN)),
CKM_RC5_ECB => String::from(stringify!(CKM_RC5_ECB)),
CKM_RC5_CBC => String::from(stringify!(CKM_RC5_CBC)),
CKM_RC5_MAC => String::from(stringify!(CKM_RC5_MAC)),
CKM_RC5_MAC_GENERAL => String::from(stringify!(CKM_RC5_MAC_GENERAL)),
CKM_RC5_CBC_PAD => String::from(stringify!(CKM_RC5_CBC_PAD)),
CKM_IDEA_KEY_GEN => String::from(stringify!(CKM_IDEA_KEY_GEN)),
CKM_IDEA_ECB => String::from(stringify!(CKM_IDEA_ECB)),
CKM_IDEA_CBC => String::from(stringify!(CKM_IDEA_CBC)),
CKM_IDEA_MAC => String::from(stringify!(CKM_IDEA_MAC)),
CKM_IDEA_MAC_GENERAL => String::from(stringify!(CKM_IDEA_MAC_GENERAL)),
CKM_IDEA_CBC_PAD => String::from(stringify!(CKM_IDEA_CBC_PAD)),
CKM_GENERIC_SECRET_KEY_GEN => String::from(stringify!(CKM_GENERIC_SECRET_KEY_GEN)),
CKM_CONCATENATE_BASE_AND_KEY => String::from(stringify!(CKM_CONCATENATE_BASE_AND_KEY)),
CKM_CONCATENATE_BASE_AND_DATA => {
String::from(stringify!(CKM_CONCATENATE_BASE_AND_DATA))
}
CKM_CONCATENATE_DATA_AND_BASE => {
String::from(stringify!(CKM_CONCATENATE_DATA_AND_BASE))
}
CKM_XOR_BASE_AND_DATA => String::from(stringify!(CKM_XOR_BASE_AND_DATA)),
CKM_EXTRACT_KEY_FROM_KEY => String::from(stringify!(CKM_EXTRACT_KEY_FROM_KEY)),
CKM_SSL3_PRE_MASTER_KEY_GEN => String::from(stringify!(CKM_SSL3_PRE_MASTER_KEY_GEN)),
CKM_SSL3_MASTER_KEY_DERIVE => String::from(stringify!(CKM_SSL3_MASTER_KEY_DERIVE)),
CKM_SSL3_KEY_AND_MAC_DERIVE => String::from(stringify!(CKM_SSL3_KEY_AND_MAC_DERIVE)),
CKM_SSL3_MASTER_KEY_DERIVE_DH => {
String::from(stringify!(CKM_SSL3_MASTER_KEY_DERIVE_DH))
}
CKM_TLS_PRE_MASTER_KEY_GEN => String::from(stringify!(CKM_TLS_PRE_MASTER_KEY_GEN)),
CKM_TLS_MASTER_KEY_DERIVE => String::from(stringify!(CKM_TLS_MASTER_KEY_DERIVE)),
CKM_TLS_KEY_AND_MAC_DERIVE => String::from(stringify!(CKM_TLS_KEY_AND_MAC_DERIVE)),
CKM_TLS_MASTER_KEY_DERIVE_DH => String::from(stringify!(CKM_TLS_MASTER_KEY_DERIVE_DH)),
CKM_TLS_PRF => String::from(stringify!(CKM_TLS_PRF)),
CKM_SSL3_MD5_MAC => String::from(stringify!(CKM_SSL3_MD5_MAC)),
CKM_SSL3_SHA1_MAC => String::from(stringify!(CKM_SSL3_SHA1_MAC)),
CKM_MD5_KEY_DERIVATION => String::from(stringify!(CKM_MD5_KEY_DERIVATION)),
CKM_MD2_KEY_DERIVATION => String::from(stringify!(CKM_MD2_KEY_DERIVATION)),
CKM_SHA1_KEY_DERIVATION => String::from(stringify!(CKM_SHA1_KEY_DERIVATION)),
CKM_SHA256_KEY_DERIVATION => String::from(stringify!(CKM_SHA256_KEY_DERIVATION)),
CKM_SHA384_KEY_DERIVATION => String::from(stringify!(CKM_SHA384_KEY_DERIVATION)),
CKM_SHA512_KEY_DERIVATION => String::from(stringify!(CKM_SHA512_KEY_DERIVATION)),
CKM_PBE_MD2_DES_CBC => String::from(stringify!(CKM_PBE_MD2_DES_CBC)),
CKM_PBE_MD5_DES_CBC => String::from(stringify!(CKM_PBE_MD5_DES_CBC)),
CKM_PBE_MD5_CAST_CBC => String::from(stringify!(CKM_PBE_MD5_CAST_CBC)),
CKM_PBE_MD5_CAST3_CBC => String::from(stringify!(CKM_PBE_MD5_CAST3_CBC)),
CKM_PBE_MD5_CAST128_CBC => String::from(stringify!(CKM_PBE_MD5_CAST128_CBC)),
CKM_PBE_SHA1_CAST128_CBC => String::from(stringify!(CKM_PBE_SHA1_CAST128_CBC)),
CKM_PBE_SHA1_RC4_128 => String::from(stringify!(CKM_PBE_SHA1_RC4_128)),
CKM_PBE_SHA1_RC4_40 => String::from(stringify!(CKM_PBE_SHA1_RC4_40)),
CKM_PBE_SHA1_DES3_EDE_CBC => String::from(stringify!(CKM_PBE_SHA1_DES3_EDE_CBC)),
CKM_PBE_SHA1_DES2_EDE_CBC => String::from(stringify!(CKM_PBE_SHA1_DES2_EDE_CBC)),
CKM_PBE_SHA1_RC2_128_CBC => String::from(stringify!(CKM_PBE_SHA1_RC2_128_CBC)),
CKM_PBE_SHA1_RC2_40_CBC => String::from(stringify!(CKM_PBE_SHA1_RC2_40_CBC)),
CKM_PKCS5_PBKD2 => String::from(stringify!(CKM_PKCS5_PBKD2)),
CKM_PBA_SHA1_WITH_SHA1_HMAC => String::from(stringify!(CKM_PBA_SHA1_WITH_SHA1_HMAC)),
CKM_WTLS_PRE_MASTER_KEY_GEN => String::from(stringify!(CKM_WTLS_PRE_MASTER_KEY_GEN)),
CKM_WTLS_MASTER_KEY_DERIVE => String::from(stringify!(CKM_WTLS_MASTER_KEY_DERIVE)),
CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC => {
String::from(stringify!(CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC))
}
CKM_WTLS_PRF => String::from(stringify!(CKM_WTLS_PRF)),
CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE => {
String::from(stringify!(CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE))
}
CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE => {
String::from(stringify!(CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE))
}
CKM_TLS10_MAC_SERVER => String::from(stringify!(CKM_TLS10_MAC_SERVER)),
CKM_TLS10_MAC_CLIENT => String::from(stringify!(CKM_TLS10_MAC_CLIENT)),
CKM_TLS12_MAC => String::from(stringify!(CKM_TLS12_MAC)),
CKM_TLS12_KDF => String::from(stringify!(CKM_TLS12_KDF)),
CKM_TLS12_MASTER_KEY_DERIVE => String::from(stringify!(CKM_TLS12_MASTER_KEY_DERIVE)),
CKM_TLS12_KEY_AND_MAC_DERIVE => String::from(stringify!(CKM_TLS12_KEY_AND_MAC_DERIVE)),
CKM_TLS12_MASTER_KEY_DERIVE_DH => {
String::from(stringify!(CKM_TLS12_MASTER_KEY_DERIVE_DH))
}
CKM_TLS12_KEY_SAFE_DERIVE => String::from(stringify!(CKM_TLS12_KEY_SAFE_DERIVE)),
CKM_TLS_MAC => String::from(stringify!(CKM_TLS_MAC)),
CKM_TLS_KDF => String::from(stringify!(CKM_TLS_KDF)),
CKM_KEY_WRAP_LYNKS => String::from(stringify!(CKM_KEY_WRAP_LYNKS)),
CKM_KEY_WRAP_SET_OAEP => String::from(stringify!(CKM_KEY_WRAP_SET_OAEP)),
CKM_CMS_SIG => String::from(stringify!(CKM_CMS_SIG)),
CKM_KIP_DERIVE => String::from(stringify!(CKM_KIP_DERIVE)),
CKM_KIP_WRAP => String::from(stringify!(CKM_KIP_WRAP)),
CKM_KIP_MAC => String::from(stringify!(CKM_KIP_MAC)),
CKM_CAMELLIA_KEY_GEN => String::from(stringify!(CKM_CAMELLIA_KEY_GEN)),
CKM_CAMELLIA_CTR => String::from(stringify!(CKM_CAMELLIA_CTR)),
CKM_ARIA_KEY_GEN => String::from(stringify!(CKM_ARIA_KEY_GEN)),
CKM_ARIA_ECB => String::from(stringify!(CKM_ARIA_ECB)),
CKM_ARIA_CBC => String::from(stringify!(CKM_ARIA_CBC)),
CKM_ARIA_MAC => String::from(stringify!(CKM_ARIA_MAC)),
CKM_ARIA_MAC_GENERAL => String::from(stringify!(CKM_ARIA_MAC_GENERAL)),
CKM_ARIA_CBC_PAD => String::from(stringify!(CKM_ARIA_CBC_PAD)),
CKM_ARIA_ECB_ENCRYPT_DATA => String::from(stringify!(CKM_ARIA_ECB_ENCRYPT_DATA)),
CKM_ARIA_CBC_ENCRYPT_DATA => String::from(stringify!(CKM_ARIA_CBC_ENCRYPT_DATA)),
CKM_SEED_KEY_GEN => String::from(stringify!(CKM_SEED_KEY_GEN)),
CKM_SEED_ECB => String::from(stringify!(CKM_SEED_ECB)),
CKM_SEED_CBC => String::from(stringify!(CKM_SEED_CBC)),
CKM_SEED_MAC => String::from(stringify!(CKM_SEED_MAC)),
CKM_SEED_MAC_GENERAL => String::from(stringify!(CKM_SEED_MAC_GENERAL)),
CKM_SEED_CBC_PAD => String::from(stringify!(CKM_SEED_CBC_PAD)),
CKM_SEED_ECB_ENCRYPT_DATA => String::from(stringify!(CKM_SEED_ECB_ENCRYPT_DATA)),
CKM_SEED_CBC_ENCRYPT_DATA => String::from(stringify!(CKM_SEED_CBC_ENCRYPT_DATA)),
CKM_SKIPJACK_KEY_GEN => String::from(stringify!(CKM_SKIPJACK_KEY_GEN)),
CKM_SKIPJACK_ECB64 => String::from(stringify!(CKM_SKIPJACK_ECB64)),
CKM_SKIPJACK_CBC64 => String::from(stringify!(CKM_SKIPJACK_CBC64)),
CKM_SKIPJACK_OFB64 => String::from(stringify!(CKM_SKIPJACK_OFB64)),
CKM_SKIPJACK_CFB64 => String::from(stringify!(CKM_SKIPJACK_CFB64)),
CKM_SKIPJACK_CFB32 => String::from(stringify!(CKM_SKIPJACK_CFB32)),
CKM_SKIPJACK_CFB16 => String::from(stringify!(CKM_SKIPJACK_CFB16)),
CKM_SKIPJACK_CFB8 => String::from(stringify!(CKM_SKIPJACK_CFB8)),
CKM_SKIPJACK_WRAP => String::from(stringify!(CKM_SKIPJACK_WRAP)),
CKM_SKIPJACK_PRIVATE_WRAP => String::from(stringify!(CKM_SKIPJACK_PRIVATE_WRAP)),
CKM_SKIPJACK_RELAYX => String::from(stringify!(CKM_SKIPJACK_RELAYX)),
CKM_KEA_KEY_PAIR_GEN => String::from(stringify!(CKM_KEA_KEY_PAIR_GEN)),
CKM_KEA_KEY_DERIVE => String::from(stringify!(CKM_KEA_KEY_DERIVE)),
CKM_FORTEZZA_TIMESTAMP => String::from(stringify!(CKM_FORTEZZA_TIMESTAMP)),
CKM_BATON_KEY_GEN => String::from(stringify!(CKM_BATON_KEY_GEN)),
CKM_BATON_ECB128 => String::from(stringify!(CKM_BATON_ECB128)),
CKM_BATON_ECB96 => String::from(stringify!(CKM_BATON_ECB96)),
CKM_BATON_CBC128 => String::from(stringify!(CKM_BATON_CBC128)),
CKM_BATON_COUNTER => String::from(stringify!(CKM_BATON_COUNTER)),
CKM_BATON_SHUFFLE => String::from(stringify!(CKM_BATON_SHUFFLE)),
CKM_BATON_WRAP => String::from(stringify!(CKM_BATON_WRAP)),
CKM_EC_KEY_PAIR_GEN => String::from(stringify!(CKM_EC_KEY_PAIR_GEN)),
CKM_ECDSA => String::from(stringify!(CKM_ECDSA)),
CKM_ECDSA_SHA1 => String::from(stringify!(CKM_ECDSA_SHA1)),
CKM_ECDSA_SHA224 => String::from(stringify!(CKM_ECDSA_SHA224)),
CKM_ECDSA_SHA256 => String::from(stringify!(CKM_ECDSA_SHA256)),
CKM_ECDSA_SHA384 => String::from(stringify!(CKM_ECDSA_SHA384)),
CKM_ECDSA_SHA512 => String::from(stringify!(CKM_ECDSA_SHA512)),
CKM_ECDH1_DERIVE => String::from(stringify!(CKM_ECDH1_DERIVE)),
CKM_ECDH1_COFACTOR_DERIVE => String::from(stringify!(CKM_ECDH1_COFACTOR_DERIVE)),
CKM_ECMQV_DERIVE => String::from(stringify!(CKM_ECMQV_DERIVE)),
CKM_ECDH_AES_KEY_WRAP => String::from(stringify!(CKM_ECDH_AES_KEY_WRAP)),
CKM_RSA_AES_KEY_WRAP => String::from(stringify!(CKM_RSA_AES_KEY_WRAP)),
CKM_JUNIPER_KEY_GEN => String::from(stringify!(CKM_JUNIPER_KEY_GEN)),
CKM_JUNIPER_ECB128 => String::from(stringify!(CKM_JUNIPER_ECB128)),
CKM_JUNIPER_CBC128 => String::from(stringify!(CKM_JUNIPER_CBC128)),
CKM_JUNIPER_COUNTER => String::from(stringify!(CKM_JUNIPER_COUNTER)),
CKM_JUNIPER_SHUFFLE => String::from(stringify!(CKM_JUNIPER_SHUFFLE)),
CKM_JUNIPER_WRAP => String::from(stringify!(CKM_JUNIPER_WRAP)),
CKM_FASTHASH => String::from(stringify!(CKM_FASTHASH)),
CKM_AES_KEY_GEN => String::from(stringify!(CKM_AES_KEY_GEN)),
CKM_AES_ECB => String::from(stringify!(CKM_AES_ECB)),
CKM_AES_CBC => String::from(stringify!(CKM_AES_CBC)),
CKM_AES_MAC => String::from(stringify!(CKM_AES_MAC)),
CKM_AES_MAC_GENERAL => String::from(stringify!(CKM_AES_MAC_GENERAL)),
CKM_AES_CBC_PAD => String::from(stringify!(CKM_AES_CBC_PAD)),
CKM_AES_CTR => String::from(stringify!(CKM_AES_CTR)),
CKM_AES_GCM => String::from(stringify!(CKM_AES_GCM)),
CKM_AES_CCM => String::from(stringify!(CKM_AES_CCM)),
CKM_AES_CTS => String::from(stringify!(CKM_AES_CTS)),
CKM_AES_CMAC => String::from(stringify!(CKM_AES_CMAC)),
CKM_AES_CMAC_GENERAL => String::from(stringify!(CKM_AES_CMAC_GENERAL)),
CKM_AES_XCBC_MAC => String::from(stringify!(CKM_AES_XCBC_MAC)),
CKM_AES_XCBC_MAC_96 => String::from(stringify!(CKM_AES_XCBC_MAC_96)),
CKM_AES_GMAC => String::from(stringify!(CKM_AES_GMAC)),
CKM_BLOWFISH_KEY_GEN => String::from(stringify!(CKM_BLOWFISH_KEY_GEN)),
CKM_BLOWFISH_CBC => String::from(stringify!(CKM_BLOWFISH_CBC)),
CKM_TWOFISH_KEY_GEN => String::from(stringify!(CKM_TWOFISH_KEY_GEN)),
CKM_TWOFISH_CBC => String::from(stringify!(CKM_TWOFISH_CBC)),
CKM_BLOWFISH_CBC_PAD => String::from(stringify!(CKM_BLOWFISH_CBC_PAD)),
CKM_TWOFISH_CBC_PAD => String::from(stringify!(CKM_TWOFISH_CBC_PAD)),
CKM_DES_ECB_ENCRYPT_DATA => String::from(stringify!(CKM_DES_ECB_ENCRYPT_DATA)),
CKM_DES_CBC_ENCRYPT_DATA => String::from(stringify!(CKM_DES_CBC_ENCRYPT_DATA)),
CKM_DES3_ECB_ENCRYPT_DATA => String::from(stringify!(CKM_DES3_ECB_ENCRYPT_DATA)),
CKM_DES3_CBC_ENCRYPT_DATA => String::from(stringify!(CKM_DES3_CBC_ENCRYPT_DATA)),
CKM_AES_ECB_ENCRYPT_DATA => String::from(stringify!(CKM_AES_ECB_ENCRYPT_DATA)),
CKM_AES_CBC_ENCRYPT_DATA => String::from(stringify!(CKM_AES_CBC_ENCRYPT_DATA)),
CKM_GOSTR3410_KEY_PAIR_GEN => String::from(stringify!(CKM_GOSTR3410_KEY_PAIR_GEN)),
CKM_GOSTR3410 => String::from(stringify!(CKM_GOSTR3410)),
CKM_GOSTR3410_WITH_GOSTR3411 => String::from(stringify!(CKM_GOSTR3410_WITH_GOSTR3411)),
CKM_GOSTR3410_KEY_WRAP => String::from(stringify!(CKM_GOSTR3410_KEY_WRAP)),
CKM_GOSTR3410_DERIVE => String::from(stringify!(CKM_GOSTR3410_DERIVE)),
CKM_GOSTR3411 => String::from(stringify!(CKM_GOSTR3411)),
CKM_GOSTR3411_HMAC => String::from(stringify!(CKM_GOSTR3411_HMAC)),
CKM_GOST28147_KEY_GEN => String::from(stringify!(CKM_GOST28147_KEY_GEN)),
CKM_GOST28147_ECB => String::from(stringify!(CKM_GOST28147_ECB)),
CKM_GOST28147 => String::from(stringify!(CKM_GOST28147)),
CKM_GOST28147_MAC => String::from(stringify!(CKM_GOST28147_MAC)),
CKM_GOST28147_KEY_WRAP => String::from(stringify!(CKM_GOST28147_KEY_WRAP)),
CKM_DSA_PARAMETER_GEN => String::from(stringify!(CKM_DSA_PARAMETER_GEN)),
CKM_DH_PKCS_PARAMETER_GEN => String::from(stringify!(CKM_DH_PKCS_PARAMETER_GEN)),
CKM_X9_42_DH_PARAMETER_GEN => String::from(stringify!(CKM_X9_42_DH_PARAMETER_GEN)),
CKM_DSA_PROBABLISTIC_PARAMETER_GEN => {
String::from(stringify!(CKM_DSA_PROBABLISTIC_PARAMETER_GEN))
}
CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN => {
String::from(stringify!(CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN))
}
CKM_AES_OFB => String::from(stringify!(CKM_AES_OFB)),
CKM_AES_CFB64 => String::from(stringify!(CKM_AES_CFB64)),
CKM_AES_CFB8 => String::from(stringify!(CKM_AES_CFB8)),
CKM_AES_CFB128 => String::from(stringify!(CKM_AES_CFB128)),
CKM_AES_CFB1 => String::from(stringify!(CKM_AES_CFB1)),
CKM_VENDOR_DEFINED => String::from(stringify!(CKM_VENDOR_DEFINED)),
CKM_SHA224 => String::from(stringify!(CKM_SHA224)),
CKM_SHA224_HMAC => String::from(stringify!(CKM_SHA224_HMAC)),
CKM_SHA224_HMAC_GENERAL => String::from(stringify!(CKM_SHA224_HMAC_GENERAL)),
CKM_SHA224_RSA_PKCS => String::from(stringify!(CKM_SHA224_RSA_PKCS)),
CKM_SHA224_RSA_PKCS_PSS => String::from(stringify!(CKM_SHA224_RSA_PKCS_PSS)),
CKM_SHA224_KEY_DERIVATION => String::from(stringify!(CKM_SHA224_KEY_DERIVATION)),
CKM_CAMELLIA_ECB => String::from(stringify!(CKM_CAMELLIA_ECB)),
CKM_CAMELLIA_CBC => String::from(stringify!(CKM_CAMELLIA_CBC)),
CKM_CAMELLIA_MAC => String::from(stringify!(CKM_CAMELLIA_MAC)),
CKM_CAMELLIA_MAC_GENERAL => String::from(stringify!(CKM_CAMELLIA_MAC_GENERAL)),
CKM_CAMELLIA_CBC_PAD => String::from(stringify!(CKM_CAMELLIA_CBC_PAD)),
CKM_CAMELLIA_ECB_ENCRYPT_DATA => {
String::from(stringify!(CKM_CAMELLIA_ECB_ENCRYPT_DATA))
}
CKM_CAMELLIA_CBC_ENCRYPT_DATA => {
String::from(stringify!(CKM_CAMELLIA_CBC_ENCRYPT_DATA))
}
CKM_AES_KEY_WRAP => String::from(stringify!(CKM_AES_KEY_WRAP)),
CKM_AES_KEY_WRAP_PAD => String::from(stringify!(CKM_AES_KEY_WRAP_PAD)),
CKM_RSA_PKCS_TPM_1_1 => String::from(stringify!(CKM_RSA_PKCS_TPM_1_1)),
CKM_RSA_PKCS_OAEP_TPM_1_1 => String::from(stringify!(CKM_RSA_PKCS_OAEP_TPM_1_1)),
CKM_EC_EDWARDS_KEY_PAIR_GEN => String::from(stringify!(CKM_EC_EDWARDS_KEY_PAIR_GEN)),
CKM_EC_MONTGOMERY_KEY_PAIR_GEN => {
String::from(stringify!(CKM_EC_MONTGOMERY_KEY_PAIR_GEN))
}
CKM_EDDSA => String::from(stringify!(CKM_EDDSA)),
_ => format!("unknown {mech:08x}"),
}
}
}
impl std::fmt::Display for MechanismType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", MechanismType::stringify(self.val))
}
}
impl Deref for MechanismType {
type Target = CK_MECHANISM_TYPE;
fn deref(&self) -> &Self::Target {
&self.val
}
}
impl From for CK_MECHANISM_TYPE {
fn from(mechanism_type: MechanismType) -> Self {
*mechanism_type
}
}
impl TryFrom for MechanismType {
type Error = Error;
fn try_from(mechanism_type: CK_MECHANISM_TYPE) -> Result {
match mechanism_type {
CKM_AES_KEY_GEN => Ok(MechanismType::AES_KEY_GEN),
CKM_RSA_PKCS_KEY_PAIR_GEN => Ok(MechanismType::RSA_PKCS_KEY_PAIR_GEN),
CKM_RSA_PKCS => Ok(MechanismType::RSA_PKCS),
CKM_RSA_PKCS_PSS => Ok(MechanismType::RSA_PKCS_PSS),
CKM_RSA_PKCS_OAEP => Ok(MechanismType::RSA_PKCS_OAEP),
CKM_SHA_1 => Ok(MechanismType::SHA1),
CKM_SHA256 => Ok(MechanismType::SHA256),
CKM_SHA384 => Ok(MechanismType::SHA384),
CKM_SHA512 => Ok(MechanismType::SHA512),
CKM_DES3_KEY_GEN => Ok(MechanismType::DES3_KEY_GEN),
CKM_DES3_ECB => Ok(MechanismType::DES3_ECB),
CKM_EC_KEY_PAIR_GEN => Ok(MechanismType::ECC_KEY_PAIR_GEN),
CKM_EC_EDWARDS_KEY_PAIR_GEN => Ok(MechanismType::ECC_EDWARDS_KEY_PAIR_GEN),
CKM_EC_MONTGOMERY_KEY_PAIR_GEN => Ok(MechanismType::ECC_MONTGOMERY_KEY_PAIR_GEN),
CKM_EDDSA => Ok(MechanismType::EDDSA),
CKM_ECDH1_DERIVE => Ok(MechanismType::ECDH1_DERIVE),
CKM_ECDSA => Ok(MechanismType::ECDSA),
CKM_SHA256_RSA_PKCS => Ok(MechanismType::SHA256_RSA_PKCS),
CKM_SHA384_RSA_PKCS => Ok(MechanismType::SHA384_RSA_PKCS),
CKM_SHA512_RSA_PKCS => Ok(MechanismType::SHA512_RSA_PKCS),
other => {
error!("Mechanism type {} is not supported.", other);
Err(Error::NotSupported)
}
}
}
}
#[derive(Copy, Debug, Clone)]
#[non_exhaustive]
/// Type defining a specific mechanism and its parameters
pub enum Mechanism<'a> {
// AES
/// AES key gen mechanism
AesKeyGen,
/// AES-CBC mechanism
///
/// The parameter to this mechanism is the initialization vector.
///
/// For encryption, the message length must be a multiple of the block
/// size. For wrapping, the mechanism encrypts the value of the key,
/// padded on the trailing end with up to block size minus one null bytes.
/// For unwrapping, the result is truncated according to the key type and
/// the length provided by the template.
AesCbc([u8; 16]),
/// AES-CBC with PKCS#7 padding mechanism
///
/// The parameter to this mechanism is the initialization vector.
///
/// The plaintext may be any size. The PKCS#7 padding allows the length of
/// the plaintext to be recovered from the ciphertext. Therefore no length
/// should be provided when unwrapping keys with this mechanism.
AesCbcPad([u8; 16]),
/// AES in ECB mode
AesEcb,
/// AES key wrap
AesKeyWrap,
/// AES key wrap with padding block
AesKeyWrapPad,
/// AES-GCM mechanism
AesGcm(aead::GcmParams<'a>),
// RSA
/// PKCS #1 RSA key pair generation mechanism
RsaPkcsKeyPairGen,
/// Multi-purpose mechanism based on the RSA public-key cryptosystem and the block formats
/// initially defined in PKCS #1 v1.5
RsaPkcs,
/// Mechanism based on the RSA public-key cryptosystem and the PSS block format defined in PKCS
/// #1
RsaPkcsPss(rsa::PkcsPssParams),
/// Multi-purpose mechanism based on the RSA public-key cryptosystem and the OAEP block format
/// defined in PKCS #1
RsaPkcsOaep(rsa::PkcsOaepParams<'a>),
/// Multi-purpose mechanism based on the RSA public-key cryptosystem. This is so-called "raw"
/// RSA, as assumed in X.509.
RsaX509,
// DES
/// DES
DesKeyGen,
/// DES2
Des2KeyGen,
/// DES3
Des3KeyGen,
/// DES-CBC mechanism
///
/// The parameter to this mechanism is the initialization vector.
///
/// For encryption, the message length must be a multiple of the block
/// size. For wrapping, the mechanism encrypts the value of the key,
/// padded on the trailing end with up to block size minus one null bytes.
/// For unwrapping, the result is truncated according to the key type and
/// the length provided by the template.
DesCbc([u8; 8]),
/// DES3-CBC mechanism
///
/// The parameter to this mechanism is the initialization vector.
///
/// For encryption, the message length must be a multiple of the block
/// size. For wrapping, the mechanism encrypts the value of the key,
/// padded on the trailing end with up to block size minus one null bytes.
/// For unwrapping, the result is truncated according to the key type and
/// the length provided by the template.
Des3Cbc([u8; 8]),
/// DES-CBC with PKCS#7 padding mechanism
///
/// The parameter to this mechanism is the initialization vector.
///
/// The plaintext may be any size. The PKCS#7 padding allows the length of
/// the plaintext to be recovered from the ciphertext. Therefore no length
/// should be provided when unwrapping keys with this mechanism.
DesCbcPad([u8; 8]),
/// DES3-CBC with PKCS#7 padding mechanism
///
/// The parameter to this mechanism is the initialization vector.
///
/// The plaintext may be any size. The PKCS#7 padding allows the length of
/// the plaintext to be recovered from the ciphertext. Therefore no length
/// should be provided when unwrapping keys with this mechanism.
Des3CbcPad([u8; 8]),
/// DES ECB
DesEcb,
/// DES3 ECB
Des3Ecb,
// ECC
/// EC key pair generation
EccKeyPairGen,
/// EC edwards key pair generation
EccEdwardsKeyPairGen,
/// EC montgomery key pair generation
EccMontgomeryKeyPairGen,
/// ECDH
Ecdh1Derive(elliptic_curve::Ecdh1DeriveParams<'a>),
/// ECDSA mechanism
Ecdsa,
/// ECDSA with SHA-1 mechanism
EcdsaSha1,
/// ECDSA with SHA-224 mechanism
EcdsaSha224,
/// ECDSA with SHA-256 mechanism
EcdsaSha256,
/// ECDSA with SHA-384 mechanism
EcdsaSha384,
/// ECDSA with SHA-512 mechanism
EcdsaSha512,
/// EDDSA mechanism
///
/// Note: EdDSA is not part of the PKCS#11 v2.40 standard and as
/// such may not be understood by the backend. It is included here
/// because some vendor implementations support it through the
/// v2.40 interface.
Eddsa,
// SHA-n
/// SHA-1 mechanism
Sha1,
/// SHA-224 mechanism
Sha224,
/// SHA-256 mechanism
Sha256,
/// SHA-384 mechanism
Sha384,
/// SHA-512 mechanism
Sha512,
// SHAn-RSA-PKCS
/// SHA1-RSA-PKCS mechanism
Sha1RsaPkcs,
/// SHA224-RSA-PKCS mechanism
Sha224RsaPkcs,
/// SHA256-RSA-PKCS mechanism
Sha256RsaPkcs,
/// SHA384-RSA-PKCS mechanism
Sha384RsaPkcs,
/// SHA512-RSA-PKCS mechanism
Sha512RsaPkcs,
// SHAn-RSA-PKCS-PSS
/// SHA1-RSA-PKCS-PSS mechanism
Sha1RsaPkcsPss(rsa::PkcsPssParams),
/// SHA256-RSA-PKCS-PSS mechanism
Sha256RsaPkcsPss(rsa::PkcsPssParams),
/// SHA256-RSA-PKCS-PSS mechanism
Sha384RsaPkcsPss(rsa::PkcsPssParams),
/// SHA256-RSA-PKCS-PSS mechanism
Sha512RsaPkcsPss(rsa::PkcsPssParams),
}
impl Mechanism<'_> {
/// Get the type of a mechanism
pub fn mechanism_type(&self) -> MechanismType {
match self {
Mechanism::AesKeyGen => MechanismType::AES_KEY_GEN,
Mechanism::AesEcb => MechanismType::AES_ECB,
Mechanism::AesCbc(_) => MechanismType::AES_CBC,
Mechanism::AesCbcPad(_) => MechanismType::AES_CBC_PAD,
Mechanism::AesKeyWrap => MechanismType::AES_KEY_WRAP,
Mechanism::AesKeyWrapPad => MechanismType::AES_KEY_WRAP_PAD,
Mechanism::AesGcm(_) => MechanismType::AES_GCM,
Mechanism::RsaPkcsKeyPairGen => MechanismType::RSA_PKCS_KEY_PAIR_GEN,
Mechanism::RsaPkcs => MechanismType::RSA_PKCS,
Mechanism::RsaPkcsPss(_) => MechanismType::RSA_PKCS_PSS,
Mechanism::RsaPkcsOaep(_) => MechanismType::RSA_PKCS_OAEP,
Mechanism::RsaX509 => MechanismType::RSA_X_509,
Mechanism::DesKeyGen => MechanismType::DES_KEY_GEN,
Mechanism::Des2KeyGen => MechanismType::DES2_KEY_GEN,
Mechanism::Des3KeyGen => MechanismType::DES3_KEY_GEN,
Mechanism::DesCbc(_) => MechanismType::DES_CBC,
Mechanism::Des3Cbc(_) => MechanismType::DES3_CBC,
Mechanism::DesCbcPad(_) => MechanismType::DES_CBC_PAD,
Mechanism::Des3CbcPad(_) => MechanismType::DES3_CBC_PAD,
Mechanism::DesEcb => MechanismType::DES_ECB,
Mechanism::Des3Ecb => MechanismType::DES3_ECB,
Mechanism::EccKeyPairGen => MechanismType::ECC_KEY_PAIR_GEN,
Mechanism::EccEdwardsKeyPairGen => MechanismType::ECC_EDWARDS_KEY_PAIR_GEN,
Mechanism::EccMontgomeryKeyPairGen => MechanismType::ECC_MONTGOMERY_KEY_PAIR_GEN,
Mechanism::Eddsa => MechanismType::EDDSA,
Mechanism::Ecdh1Derive(_) => MechanismType::ECDH1_DERIVE,
Mechanism::Ecdsa => MechanismType::ECDSA,
Mechanism::EcdsaSha1 => MechanismType::ECDSA_SHA1,
Mechanism::EcdsaSha224 => MechanismType::ECDSA_SHA224,
Mechanism::EcdsaSha256 => MechanismType::ECDSA_SHA256,
Mechanism::EcdsaSha384 => MechanismType::ECDSA_SHA384,
Mechanism::EcdsaSha512 => MechanismType::ECDSA_SHA512,
Mechanism::Sha1 => MechanismType::SHA1,
Mechanism::Sha224 => MechanismType::SHA224,
Mechanism::Sha256 => MechanismType::SHA256,
Mechanism::Sha384 => MechanismType::SHA384,
Mechanism::Sha512 => MechanismType::SHA512,
Mechanism::Sha1RsaPkcs => MechanismType::SHA1_RSA_PKCS,
Mechanism::Sha224RsaPkcs => MechanismType::SHA224_RSA_PKCS,
Mechanism::Sha256RsaPkcs => MechanismType::SHA256_RSA_PKCS,
Mechanism::Sha384RsaPkcs => MechanismType::SHA384_RSA_PKCS,
Mechanism::Sha512RsaPkcs => MechanismType::SHA512_RSA_PKCS,
Mechanism::Sha1RsaPkcsPss(_) => MechanismType::SHA1_RSA_PKCS_PSS,
Mechanism::Sha256RsaPkcsPss(_) => MechanismType::SHA256_RSA_PKCS_PSS,
Mechanism::Sha384RsaPkcsPss(_) => MechanismType::SHA384_RSA_PKCS_PSS,
Mechanism::Sha512RsaPkcsPss(_) => MechanismType::SHA512_RSA_PKCS_PSS,
}
}
}
impl From<&Mechanism<'_>> for CK_MECHANISM {
fn from(mech: &Mechanism) -> Self {
let mechanism = mech.mechanism_type().into();
match mech {
// Mechanisms with parameters
Mechanism::AesCbc(params) | Mechanism::AesCbcPad(params) => {
make_mechanism(mechanism, params)
}
Mechanism::DesCbc(params)
| Mechanism::Des3Cbc(params)
| Mechanism::DesCbcPad(params)
| Mechanism::Des3CbcPad(params) => make_mechanism(mechanism, params),
Mechanism::AesGcm(params) => CK_MECHANISM {
mechanism,
pParameter: params as *const _ as *mut c_void,
ulParameterLen: std::mem::size_of::()
.try_into()
.expect("usize can not fit in CK_ULONG"),
},
Mechanism::RsaPkcsPss(params)
| Mechanism::Sha1RsaPkcsPss(params)
| Mechanism::Sha256RsaPkcsPss(params)
| Mechanism::Sha384RsaPkcsPss(params)
| Mechanism::Sha512RsaPkcsPss(params) => make_mechanism(mechanism, params),
Mechanism::RsaPkcsOaep(params) => make_mechanism(mechanism, params),
Mechanism::Ecdh1Derive(params) => make_mechanism(mechanism, params),
// Mechanisms without parameters
Mechanism::AesKeyGen
| Mechanism::AesEcb
| Mechanism::AesKeyWrap
| Mechanism::AesKeyWrapPad
| Mechanism::RsaPkcsKeyPairGen
| Mechanism::RsaPkcs
| Mechanism::RsaX509
| Mechanism::Sha1
| Mechanism::Sha224
| Mechanism::Sha256
| Mechanism::Sha384
| Mechanism::Sha512
| Mechanism::DesKeyGen
| Mechanism::Des2KeyGen
| Mechanism::Des3KeyGen
| Mechanism::DesEcb
| Mechanism::Des3Ecb
| Mechanism::EccKeyPairGen
| Mechanism::EccEdwardsKeyPairGen
| Mechanism::EccMontgomeryKeyPairGen
| Mechanism::Eddsa
| Mechanism::Ecdsa
| Mechanism::EcdsaSha1
| Mechanism::EcdsaSha224
| Mechanism::EcdsaSha256
| Mechanism::EcdsaSha384
| Mechanism::EcdsaSha512
| Mechanism::Sha1RsaPkcs
| Mechanism::Sha224RsaPkcs
| Mechanism::Sha256RsaPkcs
| Mechanism::Sha384RsaPkcs
| Mechanism::Sha512RsaPkcs => CK_MECHANISM {
mechanism,
pParameter: null_mut(),
ulParameterLen: 0,
},
}
}
}
// Make a CK_MECHANISM from mechanism type and parameter
fn make_mechanism(mechanism: CK_MECHANISM_TYPE, param: &T) -> CK_MECHANISM {
CK_MECHANISM {
mechanism,
// SAFETY: Although the type signature says *mut, none of the
// mechanisms we support involve mutating the parameter, so
// this cast is OK.
pParameter: param as *const T as *mut c_void,
ulParameterLen: std::mem::size_of::()
.try_into()
.expect("usize can not fit in CK_ULONG"),
}
}
#[cfg(feature = "psa-crypto-conversions")]
#[allow(deprecated)]
impl TryFrom for Mechanism {
type Error = Error;
fn try_from(alg: psa_crypto::types::algorithm::Algorithm) -> Result {
use psa_crypto::types::algorithm::{
Algorithm, AsymmetricEncryption, AsymmetricSignature, Hash, SignHash,
};
match alg {
Algorithm::Hash(Hash::Sha1) => Ok(Mechanism::Sha1),
Algorithm::Hash(Hash::Sha256) => Ok(Mechanism::Sha256),
Algorithm::Hash(Hash::Sha384) => Ok(Mechanism::Sha384),
Algorithm::Hash(Hash::Sha512) => Ok(Mechanism::Sha512),
Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign { .. })
| Algorithm::AsymmetricEncryption(AsymmetricEncryption::RsaPkcs1v15Crypt { .. }) => {
Ok(Mechanism::RsaPkcs)
}
Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPss {
hash_alg: SignHash::Specific(hash_alg),
}) => Ok(Mechanism::RsaPkcsPss(rsa::PkcsPssParams {
hash_alg: Mechanism::try_from(Algorithm::from(hash_alg))?.mechanism_type(),
mgf: rsa::PkcsMgfType::from_psa_crypto_hash(hash_alg)?,
s_len: hash_alg.hash_length().try_into()?,
})),
Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { .. }) => {
Ok(Mechanism::Ecdsa)
}
Algorithm::AsymmetricEncryption(AsymmetricEncryption::RsaOaep { hash_alg }) => {
Ok(Mechanism::RsaPkcsOaep(rsa::PkcsOaepParams {
hash_alg: Mechanism::try_from(Algorithm::from(hash_alg))?.mechanism_type(),
mgf: rsa::PkcsMgfType::from_psa_crypto_hash(hash_alg)?,
source: rsa::PkcsOaepSourceType::DATA_SPECIFIED,
source_data: std::ptr::null(),
source_data_len: 0.into(),
}))
}
alg => {
error!("{:?} is not a supported algorithm", alg);
Err(Error::NotSupported)
}
}
}
}
cryptoki-0.6.1/src/mechanism/rsa.rs 0000644 0000000 0000000 00000014477 10461020230 0015377 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! RSA mechanism types
use super::{Mechanism, MechanismType};
use crate::error::{Error, Result};
use crate::types::Ulong;
use cryptoki_sys::*;
use log::error;
use std::convert::{TryFrom, TryInto};
use std::ffi::c_void;
use std::marker::PhantomData;
use std::ops::Deref;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
/// Message Generation Function (MGF) applied to a message block when formatting a message block
/// for the PKCS #1 OAEP encryption scheme or the PKCS #1 PSS signature scheme.
pub struct PkcsMgfType {
val: CK_RSA_PKCS_MGF_TYPE,
}
impl PkcsMgfType {
/// MGF1 SHA-1
pub const MGF1_SHA1: PkcsMgfType = PkcsMgfType { val: CKG_MGF1_SHA1 };
/// MGF1 SHA-224
pub const MGF1_SHA224: PkcsMgfType = PkcsMgfType {
val: CKG_MGF1_SHA224,
};
/// MGF1 SHA-256
pub const MGF1_SHA256: PkcsMgfType = PkcsMgfType {
val: CKG_MGF1_SHA256,
};
/// MGF1 SHA-384
pub const MGF1_SHA384: PkcsMgfType = PkcsMgfType {
val: CKG_MGF1_SHA384,
};
/// MGF1 SHA-512
pub const MGF1_SHA512: PkcsMgfType = PkcsMgfType {
val: CKG_MGF1_SHA512,
};
}
impl Deref for PkcsMgfType {
type Target = CK_RSA_PKCS_MGF_TYPE;
fn deref(&self) -> &Self::Target {
&self.val
}
}
impl From for CK_RSA_PKCS_MGF_TYPE {
fn from(mgf_type: PkcsMgfType) -> Self {
*mgf_type
}
}
impl TryFrom for PkcsMgfType {
type Error = Error;
fn try_from(mgf_type: CK_RSA_PKCS_MGF_TYPE) -> Result {
match mgf_type {
CKG_MGF1_SHA1 => Ok(PkcsMgfType::MGF1_SHA1),
CKG_MGF1_SHA224 => Ok(PkcsMgfType::MGF1_SHA224),
CKG_MGF1_SHA256 => Ok(PkcsMgfType::MGF1_SHA256),
CKG_MGF1_SHA384 => Ok(PkcsMgfType::MGF1_SHA384),
CKG_MGF1_SHA512 => Ok(PkcsMgfType::MGF1_SHA512),
other => {
error!(
"Mask Generation Function type {} is not one of the valid values.",
other
);
Err(Error::InvalidValue)
}
}
}
}
#[derive(Debug, Clone, Copy)]
/// Source of the encoding parameter when formatting a message block for the PKCS #1 OAEP
/// encryption scheme
pub struct PkcsOaepSource<'a>(Option<&'a [u8]>);
impl<'a> PkcsOaepSource<'a> {
/// Construct an empty encoding parameter.
///
/// This is equivalent to `data_specified(&[])`.
pub fn empty() -> Self {
Self(None)
}
/// Construct an encoding parameter from an array of bytes.
pub fn data_specified(source_data: &'a [u8]) -> Self {
Self(Some(source_data))
}
pub(crate) fn source_ptr(&self) -> *const c_void {
if let Some(source_data) = self.0 {
source_data.as_ptr() as _
} else {
std::ptr::null()
}
}
pub(crate) fn source_len(&self) -> Ulong {
self.0
.unwrap_or_default()
.len()
.try_into()
.expect("usize can not fit in CK_ULONG")
}
pub(crate) fn source_type(&self) -> CK_RSA_PKCS_OAEP_SOURCE_TYPE {
CKZ_DATA_SPECIFIED
}
}
/// Parameters of the RsaPkcsPss mechanism
#[derive(Copy, Debug, Clone)]
#[repr(C)]
pub struct PkcsPssParams {
/// hash algorithm used in the PSS encoding; if the signature mechanism does not include
/// message hashing, then this value must be the mechanism used by the application to generate
/// the message hash; if the signature mechanism includes hashing, then this value must match
/// the hash algorithm indicated by the signature mechanism
pub hash_alg: MechanismType,
/// mask generation function to use on the encoded block
pub mgf: PkcsMgfType,
/// length, in bytes, of the salt value used in the PSS encoding; typical values are the length
/// of the message hash and zero
pub s_len: Ulong,
}
/// Parameters of the RsaPkcsOaep mechanism
#[derive(Copy, Debug, Clone)]
#[repr(C)]
pub struct PkcsOaepParams<'a> {
/// mechanism ID of the message digest algorithm used to calculate the digest of the encoding
/// parameter
hash_alg: MechanismType,
/// mask generation function to use on the encoded block
mgf: PkcsMgfType,
/// source of the encoding parameter
source: CK_RSA_PKCS_OAEP_SOURCE_TYPE,
/// data used as the input for the encoding parameter source
source_data: *const c_void,
/// length of the encoding parameter source input
source_data_len: Ulong,
/// marker type to ensure we don't outlive the source_data
_marker: PhantomData<&'a [u8]>,
}
impl<'a> PkcsOaepParams<'a> {
/// Construct a new `PkcsOaepParams`.
///
/// # Arguments
///
/// * `hash_alg` - The message digest algorithm used to calculate
/// a digest of the encoding parameter.
/// * `mgf` - The mask generation function to use on the encoded block.
/// * `encoding_parameter` - The encoding parameter, also known as the label.
pub fn new(
hash_alg: MechanismType,
mgf: PkcsMgfType,
encoding_parameter: PkcsOaepSource<'a>,
) -> Self {
PkcsOaepParams {
hash_alg,
mgf,
source: encoding_parameter.source_type(),
source_data: encoding_parameter.source_ptr(),
source_data_len: encoding_parameter.source_len(),
_marker: PhantomData,
}
}
}
impl<'a> From> for Mechanism<'a> {
fn from(pkcs_oaep_params: PkcsOaepParams<'a>) -> Self {
Mechanism::RsaPkcsOaep(pkcs_oaep_params)
}
}
#[cfg(feature = "psa-crypto-conversions")]
#[allow(deprecated)]
impl PkcsMgfType {
/// Convert a PSA Crypto Hash algorithm to a MGF type
pub fn from_psa_crypto_hash(alg: psa_crypto::types::algorithm::Hash) -> Result {
use psa_crypto::types::algorithm::Hash;
match alg {
Hash::Sha1 => Ok(PkcsMgfType::MGF1_SHA1),
Hash::Sha224 => Ok(PkcsMgfType::MGF1_SHA224),
Hash::Sha256 => Ok(PkcsMgfType::MGF1_SHA256),
Hash::Sha384 => Ok(PkcsMgfType::MGF1_SHA384),
Hash::Sha512 => Ok(PkcsMgfType::MGF1_SHA512),
alg => {
error!("{:?} is not a supported MGF1 algorithm", alg);
Err(Error::NotSupported)
}
}
}
}
cryptoki-0.6.1/src/object.rs 0000644 0000000 0000000 00000170145 10461020230 0014107 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Object types (including Attributes)
use crate::error::{Error, Result};
use crate::mechanism::MechanismType;
use crate::types::{Date, Ulong};
use cryptoki_sys::*;
use log::error;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::ffi::c_void;
use std::fmt::Formatter;
use std::ops::Deref;
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[non_exhaustive]
/// Type of an attribute
pub enum AttributeType {
/// DER-encoding of the attribute certificate's issuer
AcIssuer,
/// List of mechanisms allowed to be used with the key
AllowedMechanisms,
/// Indicates that the user has to supply the PIN for each use with the key
AlwaysAuthenticate,
/// Indicates if the key has always had the Sensitive attribute set to true
AlwaysSensitive,
/// Description of the application that manages the object
Application,
/// BER-encoding of a sequence of object identifier values
AttrTypes,
/// Base number value of a key
Base,
/// Type of certificate
CertificateType,
/// Checksum
CheckValue,
/// Type of an object
Class,
/// The CRT coefficient `iqmp` of an RSA private key
Coefficient,
/// Determines if an object can be copied
Copyable,
/// Determines if a key supports decryption
Decrypt,
/// Determines if it is possible to derive other keys from the key
Derive,
/// Determines if it is possible to destroy an object
Destroyable,
/// Parameters defining an elliptic curve
EcParams,
/// DER-encoded Elliptic Curve point
EcPoint,
/// Determines if a key supports encryption
Encrypt,
/// The end date for the object
EndDate,
/// The private exponent `dmp1` of an RSA private key
Exponent1,
/// The private exponent `dmq1` of an RSA private key
Exponent2,
/// Determines if a key is extractable and can be wrapped
Extractable,
/// Hash of issuer public key
HashOfIssuerPublicKey,
/// Hash of subject public key
HashOfSubjectPublicKey,
/// Key identifier for key
Id,
/// DER-encoding of the certificate issuer name
Issuer,
/// Identifier of the mechanism used to generate the key material
KeyGenMechanism,
/// Type of a key
KeyType,
/// Description of the object
Label,
/// Indicates if the key was generated locally or copied from a locally created object
Local,
/// Determines if the object can be modified
Modifiable,
/// Modulus value of a key
Modulus,
/// Length in bits of the modulus of a key
ModulusBits,
/// Indicates if the key has never had the Extractable attribute set to true
NeverExtractable,
/// Object ID
ObjectId,
/// DER encoding of the attribute certificate's subject field
Owner,
/// Prime number value of a key
Prime,
/// The prime `p` of an RSA private key
Prime1,
/// The prime `q` of an RSA private key
Prime2,
/// Determines if the object is private
Private,
/// Private exponent `d`
PrivateExponent,
/// Public exponent value of a key
PublicExponent,
/// DER-encoding of the SubjectPublicKeyInfo
PublicKeyInfo,
/// Determines if the key is sensitive
Sensitive,
/// DER encoding of the certificate serial number
SerialNumber,
/// Determines if a key supports signing
Sign,
/// Determines if a key supports signing where the data can be recovered from the signature
SignRecover,
/// The start date of the object
StartDate,
/// DER-encoding of certificate subject name
Subject,
/// Determines if the object is a token object
Token,
/// Determines if the object is trusted
Trusted,
/// Determines if a key supports unwrapping
Unwrap,
/// Gives the URL where the complete certificate can be obtained
Url,
/// Value of the object
Value,
/// Length in bytes of the value
ValueLen,
/// Determines if a key supports verifying
Verify,
/// Determines if a key supports verifying where the data can be recovered from the signature
VerifyRecover,
/// Determines if a key supports wrapping
Wrap,
/// Indicates that the key can only be wrapped with a wrapping key that has the Trusted attribute
WrapWithTrusted,
}
impl AttributeType {
pub(crate) fn stringify(val: CK_ATTRIBUTE_TYPE) -> String {
match val {
CKA_CLASS => String::from(stringify!(CKA_CLASS)),
CKA_TOKEN => String::from(stringify!(CKA_TOKEN)),
CKA_PRIVATE => String::from(stringify!(CKA_PRIVATE)),
CKA_LABEL => String::from(stringify!(CKA_LABEL)),
CKA_APPLICATION => String::from(stringify!(CKA_APPLICATION)),
CKA_VALUE => String::from(stringify!(CKA_VALUE)),
CKA_OBJECT_ID => String::from(stringify!(CKA_OBJECT_ID)),
CKA_CERTIFICATE_TYPE => String::from(stringify!(CKA_CERTIFICATE_TYPE)),
CKA_ISSUER => String::from(stringify!(CKA_ISSUER)),
CKA_SERIAL_NUMBER => String::from(stringify!(CKA_SERIAL_NUMBER)),
CKA_AC_ISSUER => String::from(stringify!(CKA_AC_ISSUER)),
CKA_OWNER => String::from(stringify!(CKA_OWNER)),
CKA_ATTR_TYPES => String::from(stringify!(CKA_ATTR_TYPES)),
CKA_TRUSTED => String::from(stringify!(CKA_TRUSTED)),
CKA_CERTIFICATE_CATEGORY => String::from(stringify!(CKA_CERTIFICATE_CATEGORY)),
CKA_JAVA_MIDP_SECURITY_DOMAIN => {
String::from(stringify!(CKA_JAVA_MIDP_SECURITY_DOMAIN))
}
CKA_URL => String::from(stringify!(CKA_URL)),
CKA_HASH_OF_SUBJECT_PUBLIC_KEY => {
String::from(stringify!(CKA_HASH_OF_SUBJECT_PUBLIC_KEY))
}
CKA_HASH_OF_ISSUER_PUBLIC_KEY => {
String::from(stringify!(CKA_HASH_OF_ISSUER_PUBLIC_KEY))
}
CKA_NAME_HASH_ALGORITHM => String::from(stringify!(CKA_NAME_HASH_ALGORITHM)),
CKA_CHECK_VALUE => String::from(stringify!(CKA_CHECK_VALUE)),
CKA_KEY_TYPE => String::from(stringify!(CKA_KEY_TYPE)),
CKA_SUBJECT => String::from(stringify!(CKA_SUBJECT)),
CKA_ID => String::from(stringify!(CKA_ID)),
CKA_SENSITIVE => String::from(stringify!(CKA_SENSITIVE)),
CKA_ENCRYPT => String::from(stringify!(CKA_ENCRYPT)),
CKA_DECRYPT => String::from(stringify!(CKA_DECRYPT)),
CKA_WRAP => String::from(stringify!(CKA_WRAP)),
CKA_UNWRAP => String::from(stringify!(CKA_UNWRAP)),
CKA_SIGN => String::from(stringify!(CKA_SIGN)),
CKA_SIGN_RECOVER => String::from(stringify!(CKA_SIGN_RECOVER)),
CKA_VERIFY => String::from(stringify!(CKA_VERIFY)),
CKA_VERIFY_RECOVER => String::from(stringify!(CKA_VERIFY_RECOVER)),
CKA_DERIVE => String::from(stringify!(CKA_DERIVE)),
CKA_START_DATE => String::from(stringify!(CKA_START_DATE)),
CKA_END_DATE => String::from(stringify!(CKA_END_DATE)),
CKA_MODULUS => String::from(stringify!(CKA_MODULUS)),
CKA_MODULUS_BITS => String::from(stringify!(CKA_MODULUS_BITS)),
CKA_PUBLIC_EXPONENT => String::from(stringify!(CKA_PUBLIC_EXPONENT)),
CKA_PRIVATE_EXPONENT => String::from(stringify!(CKA_PRIVATE_EXPONENT)),
CKA_PRIME_1 => String::from(stringify!(CKA_PRIME_1)),
CKA_PRIME_2 => String::from(stringify!(CKA_PRIME_2)),
CKA_EXPONENT_1 => String::from(stringify!(CKA_EXPONENT_1)),
CKA_EXPONENT_2 => String::from(stringify!(CKA_EXPONENT_2)),
CKA_COEFFICIENT => String::from(stringify!(CKA_COEFFICIENT)),
CKA_PUBLIC_KEY_INFO => String::from(stringify!(CKA_PUBLIC_KEY_INFO)),
CKA_PRIME => String::from(stringify!(CKA_PRIME)),
CKA_SUBPRIME => String::from(stringify!(CKA_SUBPRIME)),
CKA_BASE => String::from(stringify!(CKA_BASE)),
CKA_PRIME_BITS => String::from(stringify!(CKA_PRIME_BITS)),
CKA_SUB_PRIME_BITS => String::from(stringify!(CKA_SUB_PRIME_BITS)),
CKA_VALUE_BITS => String::from(stringify!(CKA_VALUE_BITS)),
CKA_VALUE_LEN => String::from(stringify!(CKA_VALUE_LEN)),
CKA_EXTRACTABLE => String::from(stringify!(CKA_EXTRACTABLE)),
CKA_LOCAL => String::from(stringify!(CKA_LOCAL)),
CKA_NEVER_EXTRACTABLE => String::from(stringify!(CKA_NEVER_EXTRACTABLE)),
CKA_ALWAYS_SENSITIVE => String::from(stringify!(CKA_ALWAYS_SENSITIVE)),
CKA_KEY_GEN_MECHANISM => String::from(stringify!(CKA_KEY_GEN_MECHANISM)),
CKA_MODIFIABLE => String::from(stringify!(CKA_MODIFIABLE)),
CKA_COPYABLE => String::from(stringify!(CKA_COPYABLE)),
CKA_DESTROYABLE => String::from(stringify!(CKA_DESTROYABLE)),
CKA_EC_PARAMS => String::from(stringify!(CKA_EC_PARAMS)),
CKA_EC_POINT => String::from(stringify!(CKA_EC_POINT)),
CKA_SECONDARY_AUTH => String::from(stringify!(CKA_SECONDARY_AUTH)),
CKA_AUTH_PIN_FLAGS => String::from(stringify!(CKA_AUTH_PIN_FLAGS)),
CKA_ALWAYS_AUTHENTICATE => String::from(stringify!(CKA_ALWAYS_AUTHENTICATE)),
CKA_WRAP_WITH_TRUSTED => String::from(stringify!(CKA_WRAP_WITH_TRUSTED)),
CKA_OTP_FORMAT => String::from(stringify!(CKA_OTP_FORMAT)),
CKA_OTP_LENGTH => String::from(stringify!(CKA_OTP_LENGTH)),
CKA_OTP_TIME_INTERVAL => String::from(stringify!(CKA_OTP_TIME_INTERVAL)),
CKA_OTP_USER_FRIENDLY_MODE => String::from(stringify!(CKA_OTP_USER_FRIENDLY_MODE)),
CKA_OTP_CHALLENGE_REQUIREMENT => {
String::from(stringify!(CKA_OTP_CHALLENGE_REQUIREMENT))
}
CKA_OTP_TIME_REQUIREMENT => String::from(stringify!(CKA_OTP_TIME_REQUIREMENT)),
CKA_OTP_COUNTER_REQUIREMENT => String::from(stringify!(CKA_OTP_COUNTER_REQUIREMENT)),
CKA_OTP_PIN_REQUIREMENT => String::from(stringify!(CKA_OTP_PIN_REQUIREMENT)),
CKA_OTP_USER_IDENTIFIER => String::from(stringify!(CKA_OTP_USER_IDENTIFIER)),
CKA_OTP_SERVICE_IDENTIFIER => String::from(stringify!(CKA_OTP_SERVICE_IDENTIFIER)),
CKA_OTP_SERVICE_LOGO => String::from(stringify!(CKA_OTP_SERVICE_LOGO)),
CKA_OTP_SERVICE_LOGO_TYPE => String::from(stringify!(CKA_OTP_SERVICE_LOGO_TYPE)),
CKA_OTP_COUNTER => String::from(stringify!(CKA_OTP_COUNTER)),
CKA_OTP_TIME => String::from(stringify!(CKA_OTP_TIME)),
CKA_GOSTR3410_PARAMS => String::from(stringify!(CKA_GOSTR3410_PARAMS)),
CKA_GOSTR3411_PARAMS => String::from(stringify!(CKA_GOSTR3411_PARAMS)),
CKA_GOST28147_PARAMS => String::from(stringify!(CKA_GOST28147_PARAMS)),
CKA_HW_FEATURE_TYPE => String::from(stringify!(CKA_HW_FEATURE_TYPE)),
CKA_RESET_ON_INIT => String::from(stringify!(CKA_RESET_ON_INIT)),
CKA_HAS_RESET => String::from(stringify!(CKA_HAS_RESET)),
CKA_PIXEL_X => String::from(stringify!(CKA_PIXEL_X)),
CKA_PIXEL_Y => String::from(stringify!(CKA_PIXEL_Y)),
CKA_RESOLUTION => String::from(stringify!(CKA_RESOLUTION)),
CKA_CHAR_ROWS => String::from(stringify!(CKA_CHAR_ROWS)),
CKA_CHAR_COLUMNS => String::from(stringify!(CKA_CHAR_COLUMNS)),
CKA_COLOR => String::from(stringify!(CKA_COLOR)),
CKA_BITS_PER_PIXEL => String::from(stringify!(CKA_BITS_PER_PIXEL)),
CKA_CHAR_SETS => String::from(stringify!(CKA_CHAR_SETS)),
CKA_ENCODING_METHODS => String::from(stringify!(CKA_ENCODING_METHODS)),
CKA_MIME_TYPES => String::from(stringify!(CKA_MIME_TYPES)),
CKA_MECHANISM_TYPE => String::from(stringify!(CKA_MECHANISM_TYPE)),
CKA_REQUIRED_CMS_ATTRIBUTES => String::from(stringify!(CKA_REQUIRED_CMS_ATTRIBUTES)),
CKA_DEFAULT_CMS_ATTRIBUTES => String::from(stringify!(CKA_DEFAULT_CMS_ATTRIBUTES)),
CKA_SUPPORTED_CMS_ATTRIBUTES => String::from(stringify!(CKA_SUPPORTED_CMS_ATTRIBUTES)),
CKA_WRAP_TEMPLATE => String::from(stringify!(CKA_WRAP_TEMPLATE)),
CKA_UNWRAP_TEMPLATE => String::from(stringify!(CKA_UNWRAP_TEMPLATE)),
CKA_DERIVE_TEMPLATE => String::from(stringify!(CKA_DERIVE_TEMPLATE)),
CKA_ALLOWED_MECHANISMS => String::from(stringify!(CKA_ALLOWED_MECHANISMS)),
_ => format!("unknown ({val:08x})"),
}
}
}
impl std::fmt::Display for AttributeType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let attrib: CK_ATTRIBUTE_TYPE = (*self).into();
write!(f, "{}", AttributeType::stringify(attrib))
}
}
impl From for CK_ATTRIBUTE_TYPE {
fn from(attribute_type: AttributeType) -> Self {
match attribute_type {
AttributeType::AcIssuer => CKA_AC_ISSUER,
AttributeType::AllowedMechanisms => CKA_ALLOWED_MECHANISMS,
AttributeType::AlwaysAuthenticate => CKA_ALWAYS_AUTHENTICATE,
AttributeType::AlwaysSensitive => CKA_ALWAYS_SENSITIVE,
AttributeType::Application => CKA_APPLICATION,
AttributeType::AttrTypes => CKA_ATTR_TYPES,
AttributeType::Base => CKA_BASE,
AttributeType::CertificateType => CKA_CERTIFICATE_TYPE,
AttributeType::CheckValue => CKA_CHECK_VALUE,
AttributeType::Class => CKA_CLASS,
AttributeType::Coefficient => CKA_COEFFICIENT,
AttributeType::Copyable => CKA_COPYABLE,
AttributeType::Decrypt => CKA_DECRYPT,
AttributeType::Derive => CKA_DERIVE,
AttributeType::Destroyable => CKA_DESTROYABLE,
AttributeType::EcParams => CKA_EC_PARAMS,
AttributeType::EcPoint => CKA_EC_POINT,
AttributeType::Encrypt => CKA_ENCRYPT,
AttributeType::EndDate => CKA_END_DATE,
AttributeType::Exponent1 => CKA_EXPONENT_1,
AttributeType::Exponent2 => CKA_EXPONENT_2,
AttributeType::Extractable => CKA_EXTRACTABLE,
AttributeType::HashOfIssuerPublicKey => CKA_HASH_OF_ISSUER_PUBLIC_KEY,
AttributeType::HashOfSubjectPublicKey => CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
AttributeType::Id => CKA_ID,
AttributeType::Issuer => CKA_ISSUER,
AttributeType::KeyGenMechanism => CKA_KEY_GEN_MECHANISM,
AttributeType::KeyType => CKA_KEY_TYPE,
AttributeType::Label => CKA_LABEL,
AttributeType::Local => CKA_LOCAL,
AttributeType::Modifiable => CKA_MODIFIABLE,
AttributeType::Modulus => CKA_MODULUS,
AttributeType::ModulusBits => CKA_MODULUS_BITS,
AttributeType::NeverExtractable => CKA_NEVER_EXTRACTABLE,
AttributeType::ObjectId => CKA_OBJECT_ID,
AttributeType::Owner => CKA_OWNER,
AttributeType::Prime => CKA_PRIME,
AttributeType::Prime1 => CKA_PRIME_1,
AttributeType::Prime2 => CKA_PRIME_2,
AttributeType::Private => CKA_PRIVATE,
AttributeType::PrivateExponent => CKA_PRIVATE_EXPONENT,
AttributeType::PublicExponent => CKA_PUBLIC_EXPONENT,
AttributeType::PublicKeyInfo => CKA_PUBLIC_KEY_INFO,
AttributeType::Sensitive => CKA_SENSITIVE,
AttributeType::SerialNumber => CKA_SERIAL_NUMBER,
AttributeType::Sign => CKA_SIGN,
AttributeType::SignRecover => CKA_SIGN_RECOVER,
AttributeType::StartDate => CKA_START_DATE,
AttributeType::Subject => CKA_SUBJECT,
AttributeType::Token => CKA_TOKEN,
AttributeType::Trusted => CKA_TRUSTED,
AttributeType::Unwrap => CKA_UNWRAP,
AttributeType::Url => CKA_URL,
AttributeType::Value => CKA_VALUE,
AttributeType::ValueLen => CKA_VALUE_LEN,
AttributeType::Verify => CKA_VERIFY,
AttributeType::VerifyRecover => CKA_VERIFY_RECOVER,
AttributeType::Wrap => CKA_WRAP,
AttributeType::WrapWithTrusted => CKA_WRAP_WITH_TRUSTED,
}
}
}
impl TryFrom for AttributeType {
type Error = Error;
fn try_from(attribute_type: CK_ATTRIBUTE_TYPE) -> Result {
match attribute_type {
CKA_AC_ISSUER => Ok(AttributeType::AcIssuer),
CKA_ALLOWED_MECHANISMS => Ok(AttributeType::AllowedMechanisms),
CKA_ALWAYS_AUTHENTICATE => Ok(AttributeType::AlwaysAuthenticate),
CKA_ALWAYS_SENSITIVE => Ok(AttributeType::AlwaysSensitive),
CKA_APPLICATION => Ok(AttributeType::Application),
CKA_ATTR_TYPES => Ok(AttributeType::AttrTypes),
CKA_BASE => Ok(AttributeType::Base),
CKA_CERTIFICATE_TYPE => Ok(AttributeType::CertificateType),
CKA_CHECK_VALUE => Ok(AttributeType::CheckValue),
CKA_CLASS => Ok(AttributeType::Class),
CKA_COEFFICIENT => Ok(AttributeType::Coefficient),
CKA_COPYABLE => Ok(AttributeType::Copyable),
CKA_DECRYPT => Ok(AttributeType::Decrypt),
CKA_DERIVE => Ok(AttributeType::Derive),
CKA_DESTROYABLE => Ok(AttributeType::Destroyable),
CKA_EC_PARAMS => Ok(AttributeType::EcParams),
CKA_EC_POINT => Ok(AttributeType::EcPoint),
CKA_ENCRYPT => Ok(AttributeType::Encrypt),
CKA_END_DATE => Ok(AttributeType::EndDate),
CKA_EXPONENT_1 => Ok(AttributeType::Exponent1),
CKA_EXPONENT_2 => Ok(AttributeType::Exponent2),
CKA_EXTRACTABLE => Ok(AttributeType::Extractable),
CKA_HASH_OF_ISSUER_PUBLIC_KEY => Ok(AttributeType::HashOfIssuerPublicKey),
CKA_HASH_OF_SUBJECT_PUBLIC_KEY => Ok(AttributeType::HashOfSubjectPublicKey),
CKA_ID => Ok(AttributeType::Id),
CKA_ISSUER => Ok(AttributeType::Issuer),
CKA_KEY_GEN_MECHANISM => Ok(AttributeType::KeyGenMechanism),
CKA_KEY_TYPE => Ok(AttributeType::KeyType),
CKA_LABEL => Ok(AttributeType::Label),
CKA_LOCAL => Ok(AttributeType::Local),
CKA_MODIFIABLE => Ok(AttributeType::Modifiable),
CKA_MODULUS => Ok(AttributeType::Modulus),
CKA_MODULUS_BITS => Ok(AttributeType::ModulusBits),
CKA_NEVER_EXTRACTABLE => Ok(AttributeType::NeverExtractable),
CKA_OBJECT_ID => Ok(AttributeType::ObjectId),
CKA_OWNER => Ok(AttributeType::Owner),
CKA_PRIME => Ok(AttributeType::Prime),
CKA_PRIME_1 => Ok(AttributeType::Prime1),
CKA_PRIME_2 => Ok(AttributeType::Prime2),
CKA_PRIVATE => Ok(AttributeType::Private),
CKA_PRIVATE_EXPONENT => Ok(AttributeType::PrivateExponent),
CKA_PUBLIC_EXPONENT => Ok(AttributeType::PublicExponent),
CKA_PUBLIC_KEY_INFO => Ok(AttributeType::PublicKeyInfo),
CKA_SENSITIVE => Ok(AttributeType::Sensitive),
CKA_SERIAL_NUMBER => Ok(AttributeType::SerialNumber),
CKA_SIGN => Ok(AttributeType::Sign),
CKA_SIGN_RECOVER => Ok(AttributeType::SignRecover),
CKA_START_DATE => Ok(AttributeType::StartDate),
CKA_SUBJECT => Ok(AttributeType::Subject),
CKA_TOKEN => Ok(AttributeType::Token),
CKA_TRUSTED => Ok(AttributeType::Trusted),
CKA_UNWRAP => Ok(AttributeType::Unwrap),
CKA_URL => Ok(AttributeType::Url),
CKA_VALUE => Ok(AttributeType::Value),
CKA_VALUE_LEN => Ok(AttributeType::ValueLen),
CKA_VERIFY => Ok(AttributeType::Verify),
CKA_VERIFY_RECOVER => Ok(AttributeType::VerifyRecover),
CKA_WRAP => Ok(AttributeType::Wrap),
CKA_WRAP_WITH_TRUSTED => Ok(AttributeType::WrapWithTrusted),
attr_type => {
error!("Attribute type {} not supported.", attr_type);
Err(Error::NotSupported)
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
/// Attribute value
pub enum Attribute {
/// DER-encoding of the attribute certificate's issuer
AcIssuer(Vec),
/// List of mechanisms allowed to be used with the key
AllowedMechanisms(Vec),
/// Indicates that the user has to supply the PIN for each use with the key
AlwaysAuthenticate(bool),
/// Indicates if the key has always had the Sensitive attribute set to true
AlwaysSensitive(bool),
/// Description of the application that manages the object
Application(Vec),
/// BER-encoding of a sequence of object identifier values
AttrTypes(Vec),
/// Base number value of a key
Base(Vec),
/// Type of certificate
CertificateType(CertificateType),
/// Checksum
CheckValue(Vec),
/// Type of an object
Class(ObjectClass),
/// The CRT coefficient `iqmp` of an RSA private key
Coefficient(Vec),
/// Determines if an object can be copied
Copyable(bool),
/// Determines if a key supports decryption
Decrypt(bool),
/// Determines if it is possible to derive other keys from the key
Derive(bool),
/// Determines if it is possible to destroy an object
Destroyable(bool),
/// Parameters describing an elliptic curve
EcParams(Vec),
/// Elliptic Curve point
EcPoint(Vec),
/// Determines if a key supports encryption
Encrypt(bool),
/// The end date of the object
EndDate(Date),
/// The private exponent `dmp1` of an RSA private key
Exponent1(Vec),
/// The private exponent `dmq1` of an RSA private key
Exponent2(Vec),
/// Determines if a key is extractable and can be wrapped
Extractable(bool),
/// Hash of issuer public key
HashOfIssuerPublicKey(Vec),
/// Hash of subject public key
HashOfSubjectPublicKey(Vec),
/// Key identifier for key
Id(Vec),
/// DER-encoding of the certificate issuer name
Issuer(Vec),
/// Identifier of the mechanism used to generate the key material
KeyGenMechanism(MechanismType),
/// Type of a key
KeyType(KeyType),
/// Description of the object
Label(Vec),
/// Indicates if the key was generated locally or copied from a locally created object
Local(bool),
/// Determines if the object can be modified
Modifiable(bool),
/// Modulus value of a key
Modulus(Vec),
/// Length in bits of the modulus of a key
ModulusBits(Ulong),
/// Indicates if the key has never had the Extractable attribute set to true
NeverExtractable(bool),
/// Object ID
ObjectId(Vec),
/// DER encoding of the attribute certificate's subject field
Owner(Vec),
/// Prime number value of a key
Prime(Vec),
/// The prime `p` of an RSA private key
Prime1(Vec),
/// The prime `q` of an RSA private key
Prime2(Vec),
/// Determines if the object is private
Private(bool),
/// The private exponent `d`
PrivateExponent(Vec),
/// Public exponent value of a key
PublicExponent(Vec),
/// DER-encoding of the SubjectPublicKeyInfo
PublicKeyInfo(Vec),
/// Determines if the key is sensitive
Sensitive(bool),
/// DER encoding of the certificate serial number
SerialNumber(Vec),
/// Determines if a key supports signing
Sign(bool),
/// Determines if a key supports signing where the data can be recovered from the signature
SignRecover(bool),
/// The start date of the object
StartDate(Date),
/// DER-encoding of certificate subject name
Subject(Vec),
/// Determines if the object is a token object
Token(bool),
/// Determines if an object is trusted
Trusted(bool),
/// Determines if a key supports unwrapping
Unwrap(bool),
/// Gives the URL where the complete certificate can ber obtained
Url(Vec),
/// Value of the object
Value(Vec),
/// Length in bytes of the value
ValueLen(Ulong),
/// Determines if a key supports verifying
Verify(bool),
/// Determines if a key supports verifying where the data can be recovered from the signature
VerifyRecover(bool),
/// Determines if a key supports wrapping
Wrap(bool),
/// Indicates that the key can only be wrapped with a wrapping key that has the Trusted attribute
WrapWithTrusted(bool),
}
impl Attribute {
/// Get the type of an attribute
pub fn attribute_type(&self) -> AttributeType {
match self {
Attribute::AcIssuer(_) => AttributeType::AcIssuer,
Attribute::AllowedMechanisms(_) => AttributeType::AllowedMechanisms,
Attribute::AlwaysAuthenticate(_) => AttributeType::AlwaysAuthenticate,
Attribute::AlwaysSensitive(_) => AttributeType::AlwaysSensitive,
Attribute::Application(_) => AttributeType::Application,
Attribute::AttrTypes(_) => AttributeType::AttrTypes,
Attribute::Base(_) => AttributeType::Base,
Attribute::CertificateType(_) => AttributeType::CertificateType,
Attribute::CheckValue(_) => AttributeType::CheckValue,
Attribute::Class(_) => AttributeType::Class,
Attribute::Coefficient(_) => AttributeType::Coefficient,
Attribute::Copyable(_) => AttributeType::Copyable,
Attribute::Decrypt(_) => AttributeType::Decrypt,
Attribute::Derive(_) => AttributeType::Derive,
Attribute::Destroyable(_) => AttributeType::Destroyable,
Attribute::EcParams(_) => AttributeType::EcParams,
Attribute::EcPoint(_) => AttributeType::EcPoint,
Attribute::Encrypt(_) => AttributeType::Encrypt,
Attribute::EndDate(_) => AttributeType::EndDate,
Attribute::Exponent1(_) => AttributeType::Exponent1,
Attribute::Exponent2(_) => AttributeType::Exponent2,
Attribute::Extractable(_) => AttributeType::Extractable,
Attribute::HashOfIssuerPublicKey(_) => AttributeType::HashOfIssuerPublicKey,
Attribute::HashOfSubjectPublicKey(_) => AttributeType::HashOfSubjectPublicKey,
Attribute::Id(_) => AttributeType::Id,
Attribute::Issuer(_) => AttributeType::Issuer,
Attribute::KeyGenMechanism(_) => AttributeType::KeyGenMechanism,
Attribute::KeyType(_) => AttributeType::KeyType,
Attribute::Label(_) => AttributeType::Label,
Attribute::Local(_) => AttributeType::Local,
Attribute::Modifiable(_) => AttributeType::Modifiable,
Attribute::Modulus(_) => AttributeType::Modulus,
Attribute::ModulusBits(_) => AttributeType::ModulusBits,
Attribute::NeverExtractable(_) => AttributeType::NeverExtractable,
Attribute::ObjectId(_) => AttributeType::ObjectId,
Attribute::Owner(_) => AttributeType::Owner,
Attribute::Prime(_) => AttributeType::Prime,
Attribute::Prime1(_) => AttributeType::Prime1,
Attribute::Prime2(_) => AttributeType::Prime2,
Attribute::Private(_) => AttributeType::Private,
Attribute::PrivateExponent(_) => AttributeType::PrivateExponent,
Attribute::PublicExponent(_) => AttributeType::PublicExponent,
Attribute::PublicKeyInfo(_) => AttributeType::PublicKeyInfo,
Attribute::Sensitive(_) => AttributeType::Sensitive,
Attribute::SerialNumber(_) => AttributeType::SerialNumber,
Attribute::Sign(_) => AttributeType::Sign,
Attribute::SignRecover(_) => AttributeType::SignRecover,
Attribute::StartDate(_) => AttributeType::StartDate,
Attribute::Subject(_) => AttributeType::Subject,
Attribute::Token(_) => AttributeType::Token,
Attribute::Trusted(_) => AttributeType::Trusted,
Attribute::Unwrap(_) => AttributeType::Unwrap,
Attribute::Url(_) => AttributeType::Url,
Attribute::Value(_) => AttributeType::Value,
Attribute::ValueLen(_) => AttributeType::ValueLen,
Attribute::Verify(_) => AttributeType::Verify,
Attribute::VerifyRecover(_) => AttributeType::VerifyRecover,
Attribute::Wrap(_) => AttributeType::Wrap,
Attribute::WrapWithTrusted(_) => AttributeType::WrapWithTrusted,
}
}
/// Returns the length in bytes of the objects contained by this CkAttribute.
fn len(&self) -> usize {
match self {
Attribute::AlwaysAuthenticate(_)
| Attribute::AlwaysSensitive(_)
| Attribute::Copyable(_)
| Attribute::Decrypt(_)
| Attribute::Derive(_)
| Attribute::Destroyable(_)
| Attribute::Encrypt(_)
| Attribute::Extractable(_)
| Attribute::Local(_)
| Attribute::Modifiable(_)
| Attribute::NeverExtractable(_)
| Attribute::Private(_)
| Attribute::Sensitive(_)
| Attribute::Sign(_)
| Attribute::SignRecover(_)
| Attribute::Token(_)
| Attribute::Trusted(_)
| Attribute::Unwrap(_)
| Attribute::Verify(_)
| Attribute::VerifyRecover(_)
| Attribute::Wrap(_)
| Attribute::WrapWithTrusted(_) => std::mem::size_of::(),
Attribute::Base(_) => 1,
Attribute::Application(bytes) | Attribute::Label(bytes) | Attribute::Url(bytes) => {
std::mem::size_of::() * bytes.len()
}
Attribute::AcIssuer(bytes) => bytes.len(),
Attribute::AttrTypes(bytes) => bytes.len(),
Attribute::CertificateType(_) => std::mem::size_of::(),
Attribute::CheckValue(bytes) => bytes.len(),
Attribute::Class(_) => std::mem::size_of::(),
Attribute::Coefficient(bytes) => bytes.len(),
Attribute::EcParams(bytes) => bytes.len(),
Attribute::EcPoint(bytes) => bytes.len(),
Attribute::Exponent1(bytes) => bytes.len(),
Attribute::Exponent2(bytes) => bytes.len(),
Attribute::HashOfIssuerPublicKey(bytes) => bytes.len(),
Attribute::HashOfSubjectPublicKey(bytes) => bytes.len(),
Attribute::Id(bytes) => bytes.len(),
Attribute::Issuer(bytes) => bytes.len(),
Attribute::KeyGenMechanism(_) => std::mem::size_of::(),
Attribute::KeyType(_) => std::mem::size_of::(),
Attribute::Modulus(bytes) => bytes.len(),
Attribute::ModulusBits(_) => std::mem::size_of::(),
Attribute::ObjectId(bytes) => bytes.len(),
Attribute::Owner(bytes) => bytes.len(),
Attribute::Prime(bytes) => bytes.len(),
Attribute::Prime1(bytes) => bytes.len(),
Attribute::Prime2(bytes) => bytes.len(),
Attribute::PrivateExponent(bytes) => bytes.len(),
Attribute::PublicExponent(bytes) => bytes.len(),
Attribute::PublicKeyInfo(bytes) => bytes.len(),
Attribute::SerialNumber(bytes) => bytes.len(),
Attribute::Subject(bytes) => bytes.len(),
Attribute::Value(bytes) => bytes.len(),
Attribute::ValueLen(_) => std::mem::size_of::(),
Attribute::EndDate(_) | Attribute::StartDate(_) => std::mem::size_of::(),
Attribute::AllowedMechanisms(mechanisms) => {
std::mem::size_of::() * mechanisms.len()
}
}
}
/// Returns a CK_VOID_PTR pointing to the object contained by this CkAttribute.
///
/// Casting from an immutable reference to a mutable pointer is kind of unsafe but the
/// Attribute structure will only be used with PKCS11 functions that do not modify the template
/// given.
/// The C_GetAttributeValue function, which is the only one that modifies the template given,
/// will not use Attribute parameters but return them
/// directly to the caller.
fn ptr(&self) -> *mut c_void {
// Note: bools in Rust are guaranteed to occupy a byte, so
// &mut bool as a raw pointer will provide the same space
// needed for CK_BBOOL types. See also:
// https://doc.rust-lang.org/reference/type-layout.html#primitive-data-layout
match self {
// CK_BBOOL
Attribute::AlwaysAuthenticate(b)
| Attribute::AlwaysSensitive(b)
| Attribute::Copyable(b)
| Attribute::Decrypt(b)
| Attribute::Derive(b)
| Attribute::Destroyable(b)
| Attribute::Encrypt(b)
| Attribute::Extractable(b)
| Attribute::Local(b)
| Attribute::Modifiable(b)
| Attribute::NeverExtractable(b)
| Attribute::Private(b)
| Attribute::Sensitive(b)
| Attribute::Sign(b)
| Attribute::SignRecover(b)
| Attribute::Token(b)
| Attribute::Trusted(b)
| Attribute::Unwrap(b)
| Attribute::Verify(b)
| Attribute::VerifyRecover(b)
| Attribute::Wrap(b)
| Attribute::WrapWithTrusted(b) => b as *const _ as *mut c_void,
// CK_ULONG
Attribute::ModulusBits(val) | Attribute::ValueLen(val) => {
val as *const _ as *mut c_void
}
// Vec
Attribute::AcIssuer(bytes)
| Attribute::Application(bytes)
| Attribute::AttrTypes(bytes)
| Attribute::Base(bytes)
| Attribute::CheckValue(bytes)
| Attribute::Coefficient(bytes)
| Attribute::EcParams(bytes)
| Attribute::EcPoint(bytes)
| Attribute::Exponent1(bytes)
| Attribute::Exponent2(bytes)
| Attribute::HashOfIssuerPublicKey(bytes)
| Attribute::HashOfSubjectPublicKey(bytes)
| Attribute::Issuer(bytes)
| Attribute::Label(bytes)
| Attribute::ObjectId(bytes)
| Attribute::Prime(bytes)
| Attribute::Prime1(bytes)
| Attribute::Prime2(bytes)
| Attribute::PrivateExponent(bytes)
| Attribute::PublicExponent(bytes)
| Attribute::PublicKeyInfo(bytes)
| Attribute::Modulus(bytes)
| Attribute::Owner(bytes)
| Attribute::SerialNumber(bytes)
| Attribute::Subject(bytes)
| Attribute::Url(bytes)
| Attribute::Value(bytes)
| Attribute::Id(bytes) => bytes.as_ptr() as *mut c_void,
// Unique types
Attribute::CertificateType(certificate_type) => {
certificate_type as *const _ as *mut c_void
}
Attribute::Class(object_class) => object_class as *const _ as *mut c_void,
Attribute::KeyGenMechanism(mech) => mech as *const _ as *mut c_void,
Attribute::KeyType(key_type) => key_type as *const _ as *mut c_void,
Attribute::AllowedMechanisms(mechanisms) => mechanisms.as_ptr() as *mut c_void,
Attribute::EndDate(date) | Attribute::StartDate(date) => {
date as *const _ as *mut c_void
}
}
}
}
impl From<&Attribute> for CK_ATTRIBUTE {
fn from(attribute: &Attribute) -> Self {
Self {
type_: attribute.attribute_type().into(),
pValue: attribute.ptr(),
// The panic should only happen if there is a bug.
ulValueLen: attribute
.len()
.try_into()
.expect("Can not convert the attribute length value (usize) to a CK_ULONG."),
}
}
}
/// Private function standing in for `TryInto` for `&[u8]`
/// which can't be implemented through the actual trait because
/// it and both types are external to this crate.
/// NB from the specification: "In Cryptoki, the CK_BBOOL data type
/// is a Boolean type that can be true or false. A zero value means
/// false, and a nonzero value means true." so there is no invalid
/// byte value.
fn try_u8_into_bool(slice: &[u8]) -> Result {
let as_array: [u8; std::mem::size_of::()] = slice.try_into()?;
let as_byte = CK_BBOOL::from_ne_bytes(as_array);
Ok(!matches!(as_byte, 0u8))
}
impl TryFrom for Attribute {
type Error = Error;
fn try_from(attribute: CK_ATTRIBUTE) -> Result {
let attr_type = AttributeType::try_from(attribute.type_)?;
// Cast from c_void to u8
let val = unsafe {
std::slice::from_raw_parts(
attribute.pValue as *const u8,
attribute.ulValueLen.try_into()?,
)
};
match attr_type {
// CK_BBOOL
AttributeType::AlwaysAuthenticate => {
Ok(Attribute::AlwaysAuthenticate(try_u8_into_bool(val)?))
}
AttributeType::AlwaysSensitive => {
Ok(Attribute::AlwaysSensitive(try_u8_into_bool(val)?))
}
AttributeType::Copyable => Ok(Attribute::Copyable(try_u8_into_bool(val)?)),
AttributeType::Decrypt => Ok(Attribute::Decrypt(try_u8_into_bool(val)?)),
AttributeType::Derive => Ok(Attribute::Derive(try_u8_into_bool(val)?)),
AttributeType::Destroyable => Ok(Attribute::Destroyable(try_u8_into_bool(val)?)),
AttributeType::Encrypt => Ok(Attribute::Encrypt(try_u8_into_bool(val)?)),
AttributeType::Extractable => Ok(Attribute::Extractable(try_u8_into_bool(val)?)),
AttributeType::Local => Ok(Attribute::Local(try_u8_into_bool(val)?)),
AttributeType::Modifiable => Ok(Attribute::Modifiable(try_u8_into_bool(val)?)),
AttributeType::NeverExtractable => {
Ok(Attribute::NeverExtractable(try_u8_into_bool(val)?))
}
AttributeType::Private => Ok(Attribute::Private(try_u8_into_bool(val)?)),
AttributeType::Sensitive => Ok(Attribute::Sensitive(try_u8_into_bool(val)?)),
AttributeType::Sign => Ok(Attribute::Sign(try_u8_into_bool(val)?)),
AttributeType::SignRecover => Ok(Attribute::SignRecover(try_u8_into_bool(val)?)),
AttributeType::Token => Ok(Attribute::Token(try_u8_into_bool(val)?)),
AttributeType::Trusted => Ok(Attribute::Trusted(try_u8_into_bool(val)?)),
AttributeType::Unwrap => Ok(Attribute::Unwrap(try_u8_into_bool(val)?)),
AttributeType::Verify => Ok(Attribute::Verify(try_u8_into_bool(val)?)),
AttributeType::VerifyRecover => Ok(Attribute::VerifyRecover(try_u8_into_bool(val)?)),
AttributeType::Wrap => Ok(Attribute::Wrap(try_u8_into_bool(val)?)),
AttributeType::WrapWithTrusted => {
Ok(Attribute::WrapWithTrusted(try_u8_into_bool(val)?))
}
// CK_ULONG
AttributeType::ModulusBits => Ok(Attribute::ModulusBits(
CK_ULONG::from_ne_bytes(val.try_into()?).try_into()?,
)),
AttributeType::ValueLen => Ok(Attribute::ValueLen(
CK_ULONG::from_ne_bytes(val.try_into()?).try_into()?,
)),
// Vec
AttributeType::AcIssuer => Ok(Attribute::AcIssuer(val.to_vec())),
AttributeType::Application => Ok(Attribute::Application(val.to_vec())),
AttributeType::AttrTypes => Ok(Attribute::AttrTypes(val.to_vec())),
AttributeType::Base => Ok(Attribute::Base(val.to_vec())),
AttributeType::CheckValue => Ok(Attribute::CheckValue(val.to_vec())),
AttributeType::Coefficient => Ok(Attribute::Coefficient(val.to_vec())),
AttributeType::EcParams => Ok(Attribute::EcParams(val.to_vec())),
AttributeType::EcPoint => Ok(Attribute::EcPoint(val.to_vec())),
AttributeType::Exponent1 => Ok(Attribute::Exponent1(val.to_vec())),
AttributeType::Exponent2 => Ok(Attribute::Exponent2(val.to_vec())),
AttributeType::HashOfIssuerPublicKey => {
Ok(Attribute::HashOfIssuerPublicKey(val.to_vec()))
}
AttributeType::HashOfSubjectPublicKey => {
Ok(Attribute::HashOfSubjectPublicKey(val.to_vec()))
}
AttributeType::Issuer => Ok(Attribute::Issuer(val.to_vec())),
AttributeType::Label => Ok(Attribute::Label(val.to_vec())),
AttributeType::Prime => Ok(Attribute::Prime(val.to_vec())),
AttributeType::Prime1 => Ok(Attribute::Prime1(val.to_vec())),
AttributeType::Prime2 => Ok(Attribute::Prime2(val.to_vec())),
AttributeType::PrivateExponent => Ok(Attribute::PrivateExponent(val.to_vec())),
AttributeType::PublicExponent => Ok(Attribute::PublicExponent(val.to_vec())),
AttributeType::PublicKeyInfo => Ok(Attribute::PublicKeyInfo(val.to_vec())),
AttributeType::Modulus => Ok(Attribute::Modulus(val.to_vec())),
AttributeType::ObjectId => Ok(Attribute::ObjectId(val.to_vec())),
AttributeType::Owner => Ok(Attribute::Owner(val.to_vec())),
AttributeType::SerialNumber => Ok(Attribute::SerialNumber(val.to_vec())),
AttributeType::Subject => Ok(Attribute::Subject(val.to_vec())),
AttributeType::Url => Ok(Attribute::Url(val.to_vec())),
AttributeType::Value => Ok(Attribute::Value(val.to_vec())),
AttributeType::Id => Ok(Attribute::Id(val.to_vec())),
// Unique types
AttributeType::CertificateType => Ok(Attribute::CertificateType(
CK_CERTIFICATE_TYPE::from_ne_bytes(val.try_into()?).try_into()?,
)),
AttributeType::Class => Ok(Attribute::Class(
CK_OBJECT_CLASS::from_ne_bytes(val.try_into()?).try_into()?,
)),
AttributeType::KeyGenMechanism => Ok(Attribute::KeyGenMechanism(
CK_MECHANISM_TYPE::from_ne_bytes(val.try_into()?).try_into()?,
)),
AttributeType::KeyType => Ok(Attribute::KeyType(
CK_KEY_TYPE::from_ne_bytes(val.try_into()?).try_into()?,
)),
AttributeType::AllowedMechanisms => {
let val = unsafe {
std::slice::from_raw_parts(
attribute.pValue as *const CK_MECHANISM_TYPE,
attribute.ulValueLen.try_into()?,
)
};
let types: Vec = val
.iter()
.copied()
.map(|t| t.try_into())
.collect::>>()?;
Ok(Attribute::AllowedMechanisms(types))
}
AttributeType::EndDate => {
if val.is_empty() {
Ok(Attribute::EndDate(Date::new_empty()))
} else {
let date = val.as_ptr() as *const CK_DATE;
unsafe {
let year = String::from_utf8_lossy(Vec::from((*date).year).as_slice())
.trim_end()
.to_string();
let month = String::from_utf8_lossy(Vec::from((*date).month).as_slice())
.trim_end()
.to_string();
let day = String::from_utf8_lossy(Vec::from((*date).day).as_slice())
.trim_end()
.to_string();
Ok(Attribute::EndDate(Date::new_from_str_slice(
year.as_str(),
month.as_str(),
day.as_str(),
)?))
}
}
}
AttributeType::StartDate => {
if val.is_empty() {
Ok(Attribute::StartDate(Date::new_empty()))
} else {
let date = val.as_ptr() as *const CK_DATE;
unsafe {
let year = String::from_utf8_lossy(Vec::from((*date).year).as_slice())
.trim_end()
.to_string();
let month = String::from_utf8_lossy(Vec::from((*date).month).as_slice())
.trim_end()
.to_string();
let day = String::from_utf8_lossy(Vec::from((*date).day).as_slice())
.trim_end()
.to_string();
Ok(Attribute::StartDate(Date::new_from_str_slice(
year.as_str(),
month.as_str(),
day.as_str(),
)?))
}
}
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Token specific identifier for an object
pub struct ObjectHandle {
handle: CK_OBJECT_HANDLE,
}
impl ObjectHandle {
pub(crate) fn new(handle: CK_OBJECT_HANDLE) -> Self {
ObjectHandle { handle }
}
pub(crate) fn handle(&self) -> CK_OBJECT_HANDLE {
self.handle
}
}
impl std::fmt::Display for ObjectHandle {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.handle)
}
}
impl std::fmt::LowerHex for ObjectHandle {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:08x}", self.handle)
}
}
impl std::fmt::UpperHex for ObjectHandle {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:08X}", self.handle)
}
}
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
#[repr(transparent)]
/// Identifier of the class of an object
pub struct ObjectClass {
val: CK_OBJECT_CLASS,
}
impl ObjectClass {
/// Data objects
pub const DATA: ObjectClass = ObjectClass { val: CKO_DATA };
/// Certificate objects
pub const CERTIFICATE: ObjectClass = ObjectClass {
val: CKO_CERTIFICATE,
};
/// Public key object
pub const PUBLIC_KEY: ObjectClass = ObjectClass {
val: CKO_PUBLIC_KEY,
};
/// Private key object
pub const PRIVATE_KEY: ObjectClass = ObjectClass {
val: CKO_PRIVATE_KEY,
};
/// Secret key object
pub const SECRET_KEY: ObjectClass = ObjectClass {
val: CKO_SECRET_KEY,
};
/// A hardware feature object
pub const HARDWARE_FEATURE: ObjectClass = ObjectClass {
val: CKO_HW_FEATURE,
};
/// A domain parameters object
pub const DOMAIN_PARAMETERS: ObjectClass = ObjectClass {
val: CKO_DOMAIN_PARAMETERS,
};
/// A mechanism object
pub const MECHANISM: ObjectClass = ObjectClass { val: CKO_MECHANISM };
/// An OTP key object
pub const OTP_KEY: ObjectClass = ObjectClass { val: CKO_OTP_KEY };
pub(crate) fn stringify(class: CK_OBJECT_CLASS) -> String {
match class {
CKO_DATA => String::from(stringify!(CKO_DATA)),
CKO_CERTIFICATE => String::from(stringify!(CKO_CERTIFICATE)),
CKO_PUBLIC_KEY => String::from(stringify!(CKO_PUBLIC_KEY)),
CKO_PRIVATE_KEY => String::from(stringify!(CKO_PRIVATE_KEY)),
CKO_SECRET_KEY => String::from(stringify!(CKO_SECRET_KEY)),
CKO_HW_FEATURE => String::from(stringify!(CKO_HW_FEATURE)),
CKO_DOMAIN_PARAMETERS => String::from(stringify!(CKO_DOMAIN_PARAMETERS)),
CKO_MECHANISM => String::from(stringify!(CKO_MECHANISM)),
CKO_OTP_KEY => String::from(stringify!(CKO_OTP_KEY)),
_ => format!("unknown ({class:08x})"),
}
}
}
impl std::fmt::Display for ObjectClass {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", ObjectClass::stringify(self.val))
}
}
impl Deref for ObjectClass {
type Target = CK_OBJECT_CLASS;
fn deref(&self) -> &Self::Target {
&self.val
}
}
impl From for CK_OBJECT_CLASS {
fn from(object_class: ObjectClass) -> Self {
*object_class
}
}
impl TryFrom for ObjectClass {
type Error = Error;
fn try_from(object_class: CK_OBJECT_CLASS) -> Result {
match object_class {
CKO_DATA => Ok(ObjectClass::DATA),
CKO_CERTIFICATE => Ok(ObjectClass::CERTIFICATE),
CKO_PUBLIC_KEY => Ok(ObjectClass::PUBLIC_KEY),
CKO_PRIVATE_KEY => Ok(ObjectClass::PRIVATE_KEY),
CKO_SECRET_KEY => Ok(ObjectClass::SECRET_KEY),
CKO_HW_FEATURE => Ok(ObjectClass::HARDWARE_FEATURE),
CKO_DOMAIN_PARAMETERS => Ok(ObjectClass::DOMAIN_PARAMETERS),
CKO_MECHANISM => Ok(ObjectClass::MECHANISM),
CKO_OTP_KEY => Ok(ObjectClass::OTP_KEY),
_ => {
error!("Object class {} is not supported.", object_class);
Err(Error::NotSupported)
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
/// Key type
pub struct KeyType {
val: CK_KEY_TYPE,
}
impl KeyType {
/// RSA key
pub const RSA: KeyType = KeyType { val: CKK_RSA };
/// DSA key
pub const DSA: KeyType = KeyType { val: CKK_DSA };
/// DH key
pub const DH: KeyType = KeyType { val: CKK_DH };
/// EC key
pub const EC: KeyType = KeyType { val: CKK_EC };
/// X9_42_DH key
pub const X9_42_DH: KeyType = KeyType { val: CKK_X9_42_DH };
/// KEA key
pub const KEA: KeyType = KeyType { val: CKK_KEA };
/// Generic Secret (hmac) key
pub const GENERIC_SECRET: KeyType = KeyType {
val: CKK_GENERIC_SECRET,
};
/// RC2 key
pub const RC2: KeyType = KeyType { val: CKK_RC2 };
/// RC4 key
pub const RC4: KeyType = KeyType { val: CKK_RC4 };
/// DES key
pub const DES: KeyType = KeyType { val: CKK_DES };
/// DES2 key
pub const DES2: KeyType = KeyType { val: CKK_DES2 };
/// DES3 secret
/// Note that DES3 is deprecated. See section 2, p. 6.
pub const DES3: KeyType = KeyType { val: CKK_DES3 };
/// CAST key
pub const CAST: KeyType = KeyType { val: CKK_CAST };
/// CAST3 key
pub const CAST3: KeyType = KeyType { val: CKK_CAST3 };
/// CAST128 key
pub const CAST128: KeyType = KeyType { val: CKK_CAST128 };
/// RC5 key
pub const RC5: KeyType = KeyType { val: CKK_RC5 };
/// IDEA key
pub const IDEA: KeyType = KeyType { val: CKK_IDEA };
/// SKIPJACK key
pub const SKIPJACK: KeyType = KeyType { val: CKK_SKIPJACK };
/// BATON key
pub const BATON: KeyType = KeyType { val: CKK_BATON };
/// JUNIPER key
pub const JUNIPER: KeyType = KeyType { val: CKK_JUNIPER };
/// CDMF key
pub const CDMF: KeyType = KeyType { val: CKK_CDMF };
/// AES key
pub const AES: KeyType = KeyType { val: CKK_AES };
/// BLOWFISH key
pub const BLOWFISH: KeyType = KeyType { val: CKK_BLOWFISH };
/// TWOFISH key
pub const TWOFISH: KeyType = KeyType { val: CKK_TWOFISH };
/// SECURID key
pub const SECURID: KeyType = KeyType { val: CKK_SECURID };
/// HOTP key
pub const HOTP: KeyType = KeyType { val: CKK_HOTP };
/// ACTI key
pub const ACTI: KeyType = KeyType { val: CKK_ACTI };
/// CAMELLIA key
pub const CAMELLIA: KeyType = KeyType { val: CKK_CAMELLIA };
/// ARIA key
pub const ARIA: KeyType = KeyType { val: CKK_ARIA };
/// MD5 HMAC key
pub const MD5_HMAC: KeyType = KeyType { val: CKK_MD5_HMAC };
/// SHA1 HMAC key
pub const SHA_1_HMAC: KeyType = KeyType {
val: CKK_SHA_1_HMAC,
};
/// RIPEMD128 HMAC key
pub const RIPEMD128_HMAC: KeyType = KeyType {
val: CKK_RIPEMD128_HMAC,
};
/// RIPEMD160 HMAC key
pub const RIPEMD160_HMAC: KeyType = KeyType {
val: CKK_RIPEMD160_HMAC,
};
/// SHA256 HMAC key
pub const SHA256_HMAC: KeyType = KeyType {
val: CKK_SHA256_HMAC,
};
/// SHA384 HMAC key
pub const SHA384_HMAC: KeyType = KeyType {
val: CKK_SHA256_HMAC,
};
/// SHA512 HMAC key
pub const SHA512_HMAC: KeyType = KeyType {
val: CKK_SHA256_HMAC,
};
/// SHA224 HMAC key
pub const SHA224_HMAC: KeyType = KeyType {
val: CKK_SHA256_HMAC,
};
/// SEED key
pub const SEED: KeyType = KeyType { val: CKK_SEED };
/// GOSTR3410 key
pub const GOSTR3410: KeyType = KeyType { val: CKK_GOSTR3410 };
/// GOSTR3411 key
pub const GOSTR3411: KeyType = KeyType { val: CKK_GOSTR3411 };
/// GOST28147 key
pub const GOST28147: KeyType = KeyType { val: CKK_GOST28147 };
/// EC edwards key
pub const EC_EDWARDS: KeyType = KeyType {
val: CKK_EC_EDWARDS,
};
/// EC montgomery key
pub const EC_MONTGOMERY: KeyType = KeyType {
val: CKK_EC_MONTGOMERY,
};
fn stringify(key_type: CK_KEY_TYPE) -> String {
match key_type {
CKK_RSA => String::from(stringify!(CKK_RSA)),
CKK_DSA => String::from(stringify!(CKK_DSA)),
CKK_DH => String::from(stringify!(CKK_DH)),
CKK_EC => String::from(stringify!(CKK_EC)),
CKK_X9_42_DH => String::from(stringify!(CKK_X9_42_DH)),
CKK_KEA => String::from(stringify!(CKK_KEA)),
CKK_GENERIC_SECRET => String::from(stringify!(CKK_GENERIC_SECRET)),
CKK_RC2 => String::from(stringify!(CKK_RC2)),
CKK_RC4 => String::from(stringify!(CKK_RC4)),
CKK_DES => String::from(stringify!(CKK_DES)),
CKK_DES2 => String::from(stringify!(CKK_DES2)),
CKK_DES3 => String::from(stringify!(CKK_DES3)),
CKK_CAST => String::from(stringify!(CKK_CAST)),
CKK_CAST3 => String::from(stringify!(CKK_CAST3)),
CKK_CAST128 => String::from(stringify!(CKK_CAST128)),
CKK_RC5 => String::from(stringify!(CKK_RC5)),
CKK_IDEA => String::from(stringify!(CKK_IDEA)),
CKK_SKIPJACK => String::from(stringify!(CKK_SKIPJACK)),
CKK_BATON => String::from(stringify!(CKK_BATON)),
CKK_JUNIPER => String::from(stringify!(CKK_JUNIPER)),
CKK_CDMF => String::from(stringify!(CKK_CDMF)),
CKK_AES => String::from(stringify!(CKK_AES)),
CKK_BLOWFISH => String::from(stringify!(CKK_BLOWFISH)),
CKK_TWOFISH => String::from(stringify!(CKK_TWOFISH)),
CKK_SECURID => String::from(stringify!(CKK_SECURID)),
CKK_HOTP => String::from(stringify!(CKK_HOTP)),
CKK_ACTI => String::from(stringify!(CKK_ACTI)),
CKK_CAMELLIA => String::from(stringify!(CKK_CAMELLIA)),
CKK_ARIA => String::from(stringify!(CKK_ARIA)),
CKK_MD5_HMAC => String::from(stringify!(CKK_MD5_HMAC)),
CKK_SHA_1_HMAC => String::from(stringify!(CKK_SHA_1_HMAC)),
CKK_RIPEMD128_HMAC => String::from(stringify!(CKK_RIPEMD128_HMAC)),
CKK_RIPEMD160_HMAC => String::from(stringify!(CKK_RIPEMD160_HMAC)),
CKK_SHA256_HMAC => String::from(stringify!(CKK_SHA256_HMAC)),
CKK_SHA384_HMAC => String::from(stringify!(CKK_SHA384_HMAC)),
CKK_SHA512_HMAC => String::from(stringify!(CKK_SHA512_HMAC)),
CKK_SHA224_HMAC => String::from(stringify!(CKK_SHA224_HMAC)),
CKK_SEED => String::from(stringify!(CKK_SEED)),
CKK_GOSTR3410 => String::from(stringify!(CKK_GOSTR3410)),
CKK_GOSTR3411 => String::from(stringify!(CKK_GOSTR3411)),
CKK_GOST28147 => String::from(stringify!(CKK_GOST28147)),
CKK_EC_EDWARDS => String::from(stringify!(CKK_EC_EDWARDS)),
_ => format!("unknown ({key_type:08x})"),
}
}
}
impl std::fmt::Display for KeyType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", KeyType::stringify(self.val))
}
}
impl Deref for KeyType {
type Target = CK_KEY_TYPE;
fn deref(&self) -> &Self::Target {
&self.val
}
}
impl From for CK_KEY_TYPE {
fn from(key_type: KeyType) -> Self {
*key_type
}
}
impl TryFrom for KeyType {
type Error = Error;
fn try_from(key_type: CK_KEY_TYPE) -> Result {
match key_type {
CKK_RSA => Ok(KeyType::RSA),
CKK_DSA => Ok(KeyType::DSA),
CKK_DH => Ok(KeyType::DH),
CKK_EC => Ok(KeyType::EC),
CKK_X9_42_DH => Ok(KeyType::X9_42_DH),
CKK_KEA => Ok(KeyType::KEA),
CKK_GENERIC_SECRET => Ok(KeyType::GENERIC_SECRET),
CKK_RC2 => Ok(KeyType::RC2),
CKK_RC4 => Ok(KeyType::RC4),
CKK_DES => Ok(KeyType::DES),
CKK_DES2 => Ok(KeyType::DES2),
CKK_DES3 => Ok(KeyType::DES3),
CKK_CAST => Ok(KeyType::CAST),
CKK_CAST3 => Ok(KeyType::CAST3),
CKK_CAST128 => Ok(KeyType::CAST128),
CKK_RC5 => Ok(KeyType::RC5),
CKK_IDEA => Ok(KeyType::IDEA),
CKK_SKIPJACK => Ok(KeyType::SKIPJACK),
CKK_BATON => Ok(KeyType::BATON),
CKK_JUNIPER => Ok(KeyType::JUNIPER),
CKK_CDMF => Ok(KeyType::CDMF),
CKK_AES => Ok(KeyType::AES),
CKK_BLOWFISH => Ok(KeyType::BLOWFISH),
CKK_TWOFISH => Ok(KeyType::TWOFISH),
CKK_SECURID => Ok(KeyType::SECURID),
CKK_HOTP => Ok(KeyType::HOTP),
CKK_ACTI => Ok(KeyType::ACTI),
CKK_CAMELLIA => Ok(KeyType::CAMELLIA),
CKK_ARIA => Ok(KeyType::ARIA),
CKK_MD5_HMAC => Ok(KeyType::MD5_HMAC),
CKK_SHA_1_HMAC => Ok(KeyType::SHA_1_HMAC),
CKK_RIPEMD128_HMAC => Ok(KeyType::RIPEMD128_HMAC),
CKK_RIPEMD160_HMAC => Ok(KeyType::RIPEMD160_HMAC),
CKK_SHA256_HMAC => Ok(KeyType::SHA256_HMAC),
CKK_SHA384_HMAC => Ok(KeyType::SHA384_HMAC),
CKK_SHA512_HMAC => Ok(KeyType::SHA512_HMAC),
CKK_SHA224_HMAC => Ok(KeyType::SHA224_HMAC),
CKK_SEED => Ok(KeyType::SEED),
CKK_GOSTR3410 => Ok(KeyType::GOSTR3410),
CKK_GOSTR3411 => Ok(KeyType::GOSTR3411),
CKK_GOST28147 => Ok(KeyType::GOST28147),
CKK_EC_EDWARDS => Ok(KeyType::EC_EDWARDS),
CKK_EC_MONTGOMERY => Ok(KeyType::EC_MONTGOMERY),
_ => {
error!("Key type {} is not supported.", key_type);
Err(Error::NotSupported)
}
}
}
}
#[derive(Debug, Copy, Clone)]
/// Information about the attribute of an object
pub enum AttributeInfo {
/// The requested attribute is not a valid attribute for the object
TypeInvalid,
/// The value of the attribute is sensitive and will not be returned
Sensitive,
/// The attribute is available to get from the object and has the specified size in bytes.
Available(usize),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
/// The certificate type
pub struct CertificateType {
val: CK_CERTIFICATE_TYPE,
}
impl CertificateType {
/// An X.509 certificate
pub const X_509: CertificateType = CertificateType { val: CKC_X_509 };
/// An X.509 attribute certificate
pub const X_509_ATTR: CertificateType = CertificateType {
val: CKC_X_509_ATTR_CERT,
};
/// A WTLS certificate
pub const WTLS: CertificateType = CertificateType { val: CKC_WTLS };
pub(crate) fn stringify(cert_type: CK_CERTIFICATE_TYPE) -> String {
match cert_type {
CKC_X_509 => String::from(stringify!(CKC_X_509)),
CKC_X_509_ATTR_CERT => String::from(stringify!(CKC_X_509_ATTR_CERT)),
CKC_WTLS => String::from(stringify!(CKC_WTLS)),
_ => format!("unknown ({cert_type:08x})"),
}
}
}
impl std::fmt::Display for CertificateType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", CertificateType::stringify(self.val))
}
}
impl Deref for CertificateType {
type Target = CK_CERTIFICATE_TYPE;
fn deref(&self) -> &Self::Target {
&self.val
}
}
impl From for CK_CERTIFICATE_TYPE {
fn from(certificate_type: CertificateType) -> Self {
*certificate_type
}
}
impl TryFrom for CertificateType {
type Error = Error;
fn try_from(certificate_type: CK_CERTIFICATE_TYPE) -> Result {
match certificate_type {
CKC_X_509 => Ok(CertificateType::X_509),
CKC_X_509_ATTR_CERT => Ok(CertificateType::X_509_ATTR),
CKC_WTLS => Ok(CertificateType::WTLS),
_ => {
error!("Certificate type {} is not supported.", certificate_type);
Err(Error::NotSupported)
}
}
}
}
cryptoki-0.6.1/src/session/decryption.rs 0000644 0000000 0000000 00000003300 10461020230 0016470 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Decrypting data
use crate::error::{Result, Rv};
use crate::mechanism::Mechanism;
use crate::object::ObjectHandle;
use crate::session::Session;
use cryptoki_sys::*;
use std::convert::TryInto;
impl Session {
/// Single-part decryption operation
pub fn decrypt(
&self,
mechanism: &Mechanism,
key: ObjectHandle,
encrypted_data: &[u8],
) -> Result> {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut data_len = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_DecryptInit)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
key.handle(),
))
.into_result()?;
}
// Get the output buffer length
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Decrypt)(
self.handle(),
// C_Decrypt should not modify this buffer
encrypted_data.as_ptr() as *mut u8,
encrypted_data.len().try_into()?,
std::ptr::null_mut(),
&mut data_len,
))
.into_result()?;
}
let mut data = vec![0; data_len.try_into()?];
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Decrypt)(
self.handle(),
encrypted_data.as_ptr() as *mut u8,
encrypted_data.len().try_into()?,
data.as_mut_ptr(),
&mut data_len,
))
.into_result()?;
}
data.resize(data_len.try_into()?, 0);
Ok(data)
}
}
cryptoki-0.6.1/src/session/digesting.rs 0000644 0000000 0000000 00000002733 10461020230 0016276 0 ustar 0000000 0000000 // Copyright 2023 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Digesting functions
use crate::error::{Result, Rv};
use crate::mechanism::Mechanism;
use crate::session::Session;
use cryptoki_sys::*;
use std::convert::TryInto;
impl Session {
/// Single-part digesting operation
pub fn digest(&self, m: &Mechanism, data: &[u8]) -> Result> {
let mut mechanism: CK_MECHANISM = m.into();
let mut digest_len = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_DigestInit)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
))
.into_result()?;
}
// Get the output buffer length
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Digest)(
self.handle(),
data.as_ptr() as *mut u8,
data.len().try_into()?,
std::ptr::null_mut(),
&mut digest_len,
))
.into_result()?;
}
let mut digest = vec![0; digest_len.try_into()?];
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Digest)(
self.handle(),
data.as_ptr() as *mut u8,
data.len().try_into()?,
digest.as_mut_ptr(),
&mut digest_len,
))
.into_result()?;
}
digest.resize(digest_len.try_into()?, 0);
Ok(digest)
}
}
cryptoki-0.6.1/src/session/encryption.rs 0000644 0000000 0000000 00000003255 10461020230 0016513 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Encrypting data
use crate::error::{Result, Rv};
use crate::mechanism::Mechanism;
use crate::object::ObjectHandle;
use crate::session::Session;
use cryptoki_sys::*;
use std::convert::TryInto;
impl Session {
/// Single-part encryption operation
pub fn encrypt(
&self,
mechanism: &Mechanism,
key: ObjectHandle,
data: &[u8],
) -> Result> {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut encrypted_data_len = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_EncryptInit)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
key.handle(),
))
.into_result()?;
}
// Get the output buffer length
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Encrypt)(
self.handle(),
data.as_ptr() as *mut u8,
data.len().try_into()?,
std::ptr::null_mut(),
&mut encrypted_data_len,
))
.into_result()?;
}
let mut encrypted_data = vec![0; encrypted_data_len.try_into()?];
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Encrypt)(
self.handle(),
data.as_ptr() as *mut u8,
data.len().try_into()?,
encrypted_data.as_mut_ptr(),
&mut encrypted_data_len,
))
.into_result()?;
}
encrypted_data.resize(encrypted_data_len.try_into()?, 0);
Ok(encrypted_data)
}
}
cryptoki-0.6.1/src/session/key_management.rs 0000644 0000000 0000000 00000012027 10461020230 0017302 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Key management functions
use crate::error::{Result, Rv};
use crate::mechanism::Mechanism;
use crate::object::{Attribute, ObjectHandle};
use crate::session::Session;
use cryptoki_sys::{CK_ATTRIBUTE, CK_MECHANISM, CK_MECHANISM_PTR};
use std::convert::TryInto;
impl Session {
/// Generate a secret key
pub fn generate_key(
&self,
mechanism: &Mechanism,
template: &[Attribute],
) -> Result {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut template: Vec = template.iter().map(|attr| attr.into()).collect();
let mut handle = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_GenerateKey)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
template.as_mut_ptr(),
template.len().try_into()?,
&mut handle,
))
.into_result()?;
}
Ok(ObjectHandle::new(handle))
}
/// Generate a public/private key pair
pub fn generate_key_pair(
&self,
mechanism: &Mechanism,
pub_key_template: &[Attribute],
priv_key_template: &[Attribute],
) -> Result<(ObjectHandle, ObjectHandle)> {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut pub_key_template: Vec =
pub_key_template.iter().map(|attr| attr.into()).collect();
let mut priv_key_template: Vec =
priv_key_template.iter().map(|attr| attr.into()).collect();
let mut pub_handle = 0;
let mut priv_handle = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_GenerateKeyPair)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
pub_key_template.as_mut_ptr(),
pub_key_template.len().try_into()?,
priv_key_template.as_mut_ptr(),
priv_key_template.len().try_into()?,
&mut pub_handle,
&mut priv_handle,
))
.into_result()?;
}
Ok((
ObjectHandle::new(pub_handle),
ObjectHandle::new(priv_handle),
))
}
/// Derives a key from a base key
pub fn derive_key(
&self,
mechanism: &Mechanism,
base_key: ObjectHandle,
template: &[Attribute],
) -> Result {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut template: Vec = template.iter().map(|attr| attr.into()).collect();
let mut handle = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_DeriveKey)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
base_key.handle(),
template.as_mut_ptr(),
template.len().try_into()?,
&mut handle,
))
.into_result()?;
}
Ok(ObjectHandle::new(handle))
}
/// Wrap key
pub fn wrap_key(
&self,
mechanism: &Mechanism,
wrapping_key: ObjectHandle,
key: ObjectHandle,
) -> Result> {
let mut mechanism: CK_MECHANISM = mechanism.into();
unsafe {
let mut wrapped_key_len = 0;
Rv::from(get_pkcs11!(self.client(), C_WrapKey)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
wrapping_key.handle(),
key.handle(),
std::ptr::null_mut(),
&mut wrapped_key_len,
))
.into_result()?;
let mut wrapped_key = vec![0; wrapped_key_len.try_into()?];
Rv::from(get_pkcs11!(self.client(), C_WrapKey)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
wrapping_key.handle(),
key.handle(),
wrapped_key.as_mut_ptr(),
&mut wrapped_key_len,
))
.into_result()?;
Ok(wrapped_key)
}
}
/// Unwrap previously wrapped key
pub fn unwrap_key(
&self,
mechanism: &Mechanism,
unwrapping_key: ObjectHandle,
wrapped_key: &[u8],
template: &[Attribute],
) -> Result {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut template: Vec = template.iter().map(|attr| attr.into()).collect();
let mut handle = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_UnwrapKey)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
unwrapping_key.handle(),
wrapped_key.as_ptr() as *mut u8,
wrapped_key.len().try_into()?,
template.as_mut_ptr(),
template.len().try_into()?,
&mut handle,
))
.into_result()?;
}
Ok(ObjectHandle::new(handle))
}
}
cryptoki-0.6.1/src/session/mod.rs 0000644 0000000 0000000 00000004702 10461020230 0015076 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Session types
use crate::context::Pkcs11;
use cryptoki_sys::*;
use std::fmt::Formatter;
use std::marker::PhantomData;
mod decryption;
mod digesting;
mod encryption;
mod key_management;
mod object_management;
mod random;
mod session_info;
mod session_management;
mod signing_macing;
mod slot_token_management;
pub use session_info::{SessionInfo, SessionState};
/// Type that identifies a session
///
/// It will automatically get closed (and logout) on drop.
/// Session does not implement Sync to prevent the same Session instance to be used from multiple
/// threads. A Session needs to be created in its own thread or to be passed by ownership to
/// another thread.
#[derive(Debug)]
pub struct Session {
handle: CK_SESSION_HANDLE,
client: Pkcs11,
// This is not used but to prevent Session to automatically implement Send and Sync
_guard: PhantomData<*mut u32>,
}
impl std::fmt::Display for Session {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.handle)
}
}
impl std::fmt::LowerHex for Session {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:08x}", self.handle)
}
}
impl std::fmt::UpperHex for Session {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:08X}", self.handle)
}
}
// Session does not implement Sync to prevent the same Session instance to be used from multiple
// threads.
unsafe impl Send for Session {}
impl Session {
pub(crate) fn new(handle: CK_SESSION_HANDLE, client: Pkcs11) -> Self {
Session {
handle,
client,
_guard: PhantomData,
}
}
}
impl Session {
/// Close a session
/// This will be called on drop as well.
pub fn close(self) {}
pub(crate) fn handle(&self) -> CK_SESSION_HANDLE {
self.handle
}
pub(crate) fn client(&self) -> &Pkcs11 {
&self.client
}
}
/// Types of PKCS11 users
#[derive(Copy, Clone, Debug)]
pub enum UserType {
/// Security Officer
So,
/// User
User,
/// Context Specific
ContextSpecific,
}
impl From for CK_USER_TYPE {
fn from(user_type: UserType) -> CK_USER_TYPE {
match user_type {
UserType::So => CKU_SO,
UserType::User => CKU_USER,
UserType::ContextSpecific => CKU_CONTEXT_SPECIFIC,
}
}
}
cryptoki-0.6.1/src/session/object_management.rs 0000644 0000000 0000000 00000023534 10461020230 0017765 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Object management functions
use crate::error::{Result, Rv, RvError};
use crate::object::{Attribute, AttributeInfo, AttributeType, ObjectHandle};
use crate::session::Session;
use cryptoki_sys::*;
use std::collections::HashMap;
use std::convert::TryInto;
// Search 10 elements at a time
const MAX_OBJECT_COUNT: usize = 10;
impl Session {
/// Search for session objects matching a template
pub fn find_objects(&self, template: &[Attribute]) -> Result> {
let mut template: Vec = template.iter().map(|attr| attr.into()).collect();
unsafe {
Rv::from(get_pkcs11!(self.client(), C_FindObjectsInit)(
self.handle(),
template.as_mut_ptr(),
template.len().try_into()?,
))
.into_result()?;
}
let mut object_handles = [0; MAX_OBJECT_COUNT];
let mut object_count = 0;
let mut objects = Vec::new();
unsafe {
Rv::from(get_pkcs11!(self.client(), C_FindObjects)(
self.handle(),
object_handles.as_mut_ptr() as CK_OBJECT_HANDLE_PTR,
MAX_OBJECT_COUNT.try_into()?,
&mut object_count,
))
.into_result()?;
}
while object_count > 0 {
objects.extend_from_slice(&object_handles[..object_count.try_into()?]);
unsafe {
Rv::from(get_pkcs11!(self.client(), C_FindObjects)(
self.handle(),
object_handles.as_mut_ptr() as CK_OBJECT_HANDLE_PTR,
MAX_OBJECT_COUNT.try_into()?,
&mut object_count,
))
.into_result()?;
}
}
unsafe {
Rv::from(get_pkcs11!(self.client(), C_FindObjectsFinal)(
self.handle(),
))
.into_result()?;
}
let objects = objects.into_iter().map(ObjectHandle::new).collect();
Ok(objects)
}
/// Create a new object
pub fn create_object(&self, template: &[Attribute]) -> Result {
let mut template: Vec = template.iter().map(|attr| attr.into()).collect();
let mut object_handle = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_CreateObject)(
self.handle(),
template.as_mut_ptr(),
template.len().try_into()?,
&mut object_handle as CK_OBJECT_HANDLE_PTR,
))
.into_result()?;
}
Ok(ObjectHandle::new(object_handle))
}
/// Destroy an object
pub fn destroy_object(&self, object: ObjectHandle) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_DestroyObject)(
self.handle(),
object.handle(),
))
.into_result()
}
}
/// Get the attribute info of an object: if the attribute is present and its size.
///
/// # Arguments
///
/// * `object` - The [ObjectHandle] used to reference the object
/// * `attributes` - The list of attributes to get the information of
///
/// # Returns
///
/// This function will return a Vector of [AttributeInfo] enums that will either contain
/// the size of the requested attribute, [AttributeInfo::TypeInvalid] if the attribute is not a
/// valid type for the object, or [AttributeInfo::Sensitive] if the requested attribute is
/// sensitive and will not be returned to the user.
///
/// The list of returned attributes is 1-to-1 matched with the provided vector of attribute
/// types. If you wish, you may create a hash table simply by:
///
/// ```no_run
/// use cryptoki::context::Pkcs11;
/// use cryptoki::context::CInitializeArgs;
/// use cryptoki::object::AttributeType;
/// use cryptoki::session::UserType;
/// use cryptoki::types::AuthPin;
/// use std::collections::HashMap;
/// use std::env;
///
/// let mut pkcs11 = Pkcs11::new(
/// env::var("PKCS11_SOFTHSM2_MODULE")
/// .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()),
/// )
/// .unwrap();
///
/// pkcs11.initialize(CInitializeArgs::OsThreads).unwrap();
/// let slot = pkcs11.get_slots_with_token().unwrap().remove(0);
///
/// let session = pkcs11.open_ro_session(slot).unwrap();
/// session.login(UserType::User, Some(&AuthPin::new("fedcba".into())));
///
/// let empty_attrib= vec![];
/// if let Some(object) = session.find_objects(&empty_attrib).unwrap().get(0) {
/// let attribute_types = vec![
/// AttributeType::Token,
/// AttributeType::Private,
/// AttributeType::Modulus,
/// AttributeType::KeyType,
/// AttributeType::Verify,];
///
/// let attribute_info = session.get_attribute_info(*object, &attribute_types).unwrap();
///
/// let hash = attribute_types
/// .iter()
/// .zip(attribute_info.iter())
/// .collect::>();
/// }
/// ```
///
/// Alternatively, you can call [Session::get_attribute_info_map], found below.
pub fn get_attribute_info(
&self,
object: ObjectHandle,
attributes: &[AttributeType],
) -> Result> {
let mut results = Vec::new();
for attrib in attributes.iter() {
let mut template: Vec = vec![CK_ATTRIBUTE {
type_: (*attrib).into(),
pValue: std::ptr::null_mut(),
ulValueLen: 0,
}];
match unsafe {
Rv::from(get_pkcs11!(self.client(), C_GetAttributeValue)(
self.handle(),
object.handle(),
template.as_mut_ptr(),
template.len().try_into()?,
))
} {
Rv::Ok => {
results.push(AttributeInfo::Available(template[0].ulValueLen.try_into()?))
}
Rv::Error(RvError::AttributeSensitive) => results.push(AttributeInfo::Sensitive),
Rv::Error(RvError::AttributeTypeInvalid) => {
results.push(AttributeInfo::TypeInvalid)
}
rv => rv.into_result()?,
}
}
Ok(results)
}
/// Get the attribute info of an object: if the attribute is present and its size.
///
/// # Arguments
///
/// * `object` - The [ObjectHandle] used to reference the object
/// * `attributes` - The list of attributes to get the information of
///
/// # Returns
///
/// This function will return a HashMap of [AttributeType] and [AttributeInfo] enums that will
/// either contain the size of the requested attribute, [AttributeInfo::TypeInvalid] if the
/// attribute is not a valid type for the object, or [AttributeInfo::Sensitive] if the requested
/// attribute is sensitive and will not be returned to the user.
pub fn get_attribute_info_map(
&self,
object: ObjectHandle,
attributes: Vec,
) -> Result> {
let attrib_info = self.get_attribute_info(object, attributes.as_slice())?;
Ok(attributes
.iter()
.cloned()
.zip(attrib_info.iter().cloned())
.collect::>())
}
/// Get the attributes values of an object.
/// Ignore the unavailable one. One has to call the get_attribute_info method to check which
/// ones are unavailable.
pub fn get_attributes(
&self,
object: ObjectHandle,
attributes: &[AttributeType],
) -> Result> {
let attrs_info = self.get_attribute_info(object, attributes)?;
// Allocating a chunk of memory where to put the attributes value.
let attrs_memory: Vec<(AttributeType, Vec)> = attrs_info
.iter()
.zip(attributes.iter())
.filter_map(|(attr_info, attr_type)| {
if let AttributeInfo::Available(size) = attr_info {
Some((*attr_type, vec![0; *size]))
} else {
None
}
})
.collect();
let mut template: Vec = attrs_memory
.iter()
.map(|(attr_type, memory)| {
Ok(CK_ATTRIBUTE {
type_: (*attr_type).into(),
pValue: memory.as_ptr() as *mut std::ffi::c_void,
ulValueLen: memory.len().try_into()?,
})
})
.collect::>>()?;
// This should only return OK as all attributes asked should be
// available. Concurrency problem?
unsafe {
Rv::from(get_pkcs11!(self.client(), C_GetAttributeValue)(
self.handle(),
object.handle(),
template.as_mut_ptr(),
template.len().try_into()?,
))
.into_result()?;
}
// Convert from CK_ATTRIBUTE to Attribute
template.into_iter().map(|attr| attr.try_into()).collect()
}
/// Sets the attributes of an object
pub fn update_attributes(&self, object: ObjectHandle, template: &[Attribute]) -> Result<()> {
let mut template: Vec = template.iter().map(|attr| attr.into()).collect();
unsafe {
Rv::from(get_pkcs11!(self.client(), C_SetAttributeValue)(
self.handle(),
object.handle(),
template.as_mut_ptr(),
template.len().try_into()?,
))
.into_result()?;
}
Ok(())
}
}
cryptoki-0.6.1/src/session/random.rs 0000644 0000000 0000000 00000003377 10461020230 0015606 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Functions used to generate random numbers
use crate::error::{Result, Rv};
use crate::session::Session;
use std::convert::TryInto;
impl Session {
/// Generates a random number and sticks it in a slice
///
/// # Arguments
///
/// * `random_slice` - The slice to stick the random data into. The length of the slice represents
/// the number of bytes to obtain from the RBG
pub fn generate_random_slice(&self, random_data: &mut [u8]) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_GenerateRandom)(
self.handle(),
random_data.as_ptr() as *mut u8,
random_data.len().try_into()?,
))
.into_result()?;
}
Ok(())
}
/// Generates random data and returns it as a `Vec`. The length of the returned Vector will
/// be the amount of random requested, which is `random_len`.
pub fn generate_random_vec(&self, random_len: u32) -> Result> {
let mut result: Vec = vec![0; random_len as usize];
unsafe {
Rv::from(get_pkcs11!(self.client(), C_GenerateRandom)(
self.handle(),
result.as_mut_ptr(),
random_len.try_into()?,
))
.into_result()?;
}
Ok(result)
}
/// Seeds the RNG
pub fn seed_random(&self, seed: &[u8]) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_SeedRandom)(
self.handle(),
seed.as_ptr() as *mut u8,
seed.len().try_into()?,
))
.into_result()?;
}
Ok(())
}
}
cryptoki-0.6.1/src/session/session_info.rs 0000644 0000000 0000000 00000007752 10461020230 0017025 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Session info
use crate::error::{Error, Result};
use crate::slot::Slot;
use bitflags::bitflags;
use cryptoki_sys::*;
use std::convert::{TryFrom, TryInto};
use std::fmt::Debug;
bitflags! {
/// Collection of flags defined for [`CK_SESSION_INFO`]
struct SessionInfoFlags: CK_FLAGS {
const RW_SESSION = CKF_RW_SESSION;
const SERIAL_SESSION = CKF_SERIAL_SESSION;
}
}
/// Provides information about a session
#[derive(Copy, Clone, Debug)]
pub struct SessionInfo {
slot_id: Slot,
state: SessionState,
flags: SessionInfoFlags,
device_error: u64,
}
impl SessionInfo {
/// ID of the slot that interfaces the token
pub fn slot_id(&self) -> Slot {
self.slot_id
}
/// The state of the session
pub fn session_state(&self) -> SessionState {
self.state
}
/// True if the session has R/W access to token objects, and false if access
/// is read-only
pub fn read_write(&self) -> bool {
self.flags.contains(SessionInfoFlags::RW_SESSION)
}
/// An error code defined by the cryptographic device (used for errors not
/// covered by PKCS#11)
pub fn device_error(&self) -> u64 {
self.device_error
}
}
#[doc(hidden)]
impl TryFrom for SessionInfo {
type Error = Error;
fn try_from(val: CK_SESSION_INFO) -> Result {
#[allow(clippy::useless_conversion)]
let device_error = val.ulDeviceError.into();
Ok(Self {
slot_id: Slot::new(val.slotID),
state: val.state.try_into()?,
flags: SessionInfoFlags::from_bits_truncate(val.flags),
device_error,
})
}
}
/// The current state of the session which describes access to token and session
/// objects based on user type and login status
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SessionState {
/// The session has read-only access to public token objects and R/W access
/// to to public session objects
RoPublic,
/// A normal user has been authenticated to the token.
/// The session has read-only access to all public and private token objects
/// The session has R/W access to all public and private session objects
RoUser,
/// The session has read/write access to all public objects
RwPublic,
/// A normal user has been authenticated to the token.
/// The session has read/write access to all objects
RwUser,
/// A security officer (SO) user has been authenticated to the token.
/// The session has R/W access only to public token objects. The SO
/// can set the normal user's PIN.
RwSecurityOfficer,
}
#[doc(hidden)]
impl TryFrom for SessionState {
type Error = Error;
fn try_from(value: CK_STATE) -> Result {
match value {
CKS_RO_PUBLIC_SESSION => Ok(Self::RoPublic),
CKS_RO_USER_FUNCTIONS => Ok(Self::RoUser),
CKS_RW_PUBLIC_SESSION => Ok(Self::RwPublic),
CKS_RW_USER_FUNCTIONS => Ok(Self::RwUser),
CKS_RW_SO_FUNCTIONS => Ok(Self::RwSecurityOfficer),
_ => Err(Error::InvalidValue),
}
}
}
#[cfg(test)]
mod test {
use super::{SessionInfo, SessionInfoFlags, SessionState};
use crate::slot::Slot;
#[test]
fn debug_flags_all() {
let expected = "RW_SESSION | SERIAL_SESSION";
let all = SessionInfoFlags::all();
let observed = format!("{all:#?}");
assert_eq!(observed, expected);
}
#[test]
fn debug_info() {
let info = SessionInfo {
slot_id: Slot::new(100),
state: SessionState::RoPublic,
flags: SessionInfoFlags::empty(),
device_error: 0,
};
let expected = r#"SessionInfo {
slot_id: Slot {
slot_id: 100,
},
state: RoPublic,
flags: (empty),
device_error: 0,
}"#;
let observed = format!("{info:#?}");
assert_eq!(observed, expected);
}
}
cryptoki-0.6.1/src/session/session_management.rs 0000644 0000000 0000000 00000006575 10461020230 0020210 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Session management functions
use crate::error::{Result, Rv};
use crate::session::{Session, SessionInfo, UserType};
use crate::types::{AuthPin, RawAuthPin};
#[cfg(doc)]
use cryptoki_sys::CKF_PROTECTED_AUTHENTICATION_PATH;
use cryptoki_sys::CK_SESSION_INFO;
use log::error;
use secrecy::ExposeSecret;
use std::convert::{TryFrom, TryInto};
impl Drop for Session {
fn drop(&mut self) {
#[inline(always)]
fn close(session: &Session) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(session.client(), C_CloseSession)(
session.handle(),
))
.into_result()
}
}
if let Err(e) = close(self) {
error!("Failed to close session: {}", e);
}
}
}
impl Session {
/// Log a session in.
///
/// # Arguments
///
/// * `user_type` - The type of user to log in as
/// * `pin` - The PIN to use, or `None` if you wish to use the protected authentication path
///
/// _NOTE: By passing `None` into `login`, you must ensure that the
/// [CKF_PROTECTED_AUTHENTICATION_PATH] flag is set in the `TokenFlags`._
pub fn login(&self, user_type: UserType, pin: Option<&AuthPin>) -> Result<()> {
let (pin, pin_len) = match pin {
Some(pin) => (
pin.expose_secret().as_ptr() as *mut u8,
pin.expose_secret().len(),
),
None => (std::ptr::null_mut(), 0),
};
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Login)(
self.handle(),
user_type.into(),
pin,
pin_len.try_into()?,
))
.into_result()
}
}
/// Logs a session in using a slice of raw bytes as a PIN. Some dongle drivers allow
/// non UTF-8 characters in the PIN and as a result, we aren't guaranteed that we can
/// pass in a UTF-8 string to login. Therefore, it's useful to be able to pass in raw bytes
/// rather than convert a UTF-8 string to bytes.
///
/// # Arguments
///
/// * `user_type` - The type of user to log in as
/// * `pin` - The PIN to use
///
/// _NOTE: By passing `None` into `login`, you must ensure that the
/// [CKF_PROTECTED_AUTHENTICATION_PATH] flag is set in the `TokenFlags`._
pub fn login_with_raw(&self, user_type: UserType, pin: &RawAuthPin) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Login)(
self.handle(),
user_type.into(),
pin.expose_secret().as_ptr() as *mut u8,
pin.expose_secret().len().try_into()?,
))
.into_result()
}
}
/// Log a session out
pub fn logout(&self) -> Result<()> {
unsafe { Rv::from(get_pkcs11!(self.client(), C_Logout)(self.handle())).into_result() }
}
/// Returns the information about a session
pub fn get_session_info(&self) -> Result {
let mut session_info = CK_SESSION_INFO::default();
unsafe {
Rv::from(get_pkcs11!(self.client(), C_GetSessionInfo)(
self.handle(),
&mut session_info,
))
.into_result()?;
SessionInfo::try_from(session_info)
}
}
}
cryptoki-0.6.1/src/session/signing_macing.rs 0000644 0000000 0000000 00000004752 10461020230 0017300 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Signing and authentication functions
use crate::error::{Result, Rv};
use crate::mechanism::Mechanism;
use crate::object::ObjectHandle;
use crate::session::Session;
use cryptoki_sys::*;
use std::convert::TryInto;
impl Session {
/// Sign data in single-part
pub fn sign(&self, mechanism: &Mechanism, key: ObjectHandle, data: &[u8]) -> Result> {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut signature_len = 0;
unsafe {
Rv::from(get_pkcs11!(self.client(), C_SignInit)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
key.handle(),
))
.into_result()?;
}
// Get the output buffer length
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Sign)(
self.handle(),
data.as_ptr() as *mut u8,
data.len().try_into()?,
std::ptr::null_mut(),
&mut signature_len,
))
.into_result()?;
}
let mut signature = vec![0; signature_len.try_into()?];
//TODO: we should add a new error instead of those unwrap!
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Sign)(
self.handle(),
data.as_ptr() as *mut u8,
data.len().try_into()?,
signature.as_mut_ptr(),
&mut signature_len,
))
.into_result()?;
}
signature.resize(signature_len.try_into()?, 0);
Ok(signature)
}
/// Verify data in single-part
pub fn verify(
&self,
mechanism: &Mechanism,
key: ObjectHandle,
data: &[u8],
signature: &[u8],
) -> Result<()> {
let mut mechanism: CK_MECHANISM = mechanism.into();
unsafe {
Rv::from(get_pkcs11!(self.client(), C_VerifyInit)(
self.handle(),
&mut mechanism as CK_MECHANISM_PTR,
key.handle(),
))
.into_result()?;
}
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Verify)(
self.handle(),
data.as_ptr() as *mut u8,
data.len().try_into()?,
signature.as_ptr() as *mut u8,
signature.len().try_into()?,
))
.into_result()
}
}
}
cryptoki-0.6.1/src/session/slot_token_management.rs 0000644 0000000 0000000 00000002406 10461020230 0020673 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Slot and token management functions
use crate::error::{Result, Rv};
use crate::session::Session;
use crate::types::AuthPin;
use secrecy::ExposeSecret;
use std::convert::TryInto;
impl Session {
/// Initialize the normal user's pin for a token
pub fn init_pin(&self, pin: &AuthPin) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_InitPIN)(
self.handle(),
pin.expose_secret().as_ptr() as *mut u8,
pin.expose_secret().len().try_into()?,
))
.into_result()
}
}
/// Changes the PIN of either the currently logged in user or of the `CKU_USER` if no user is
/// logged in.
pub fn set_pin(&self, old_pin: &AuthPin, new_pin: &AuthPin) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_SetPIN)(
self.handle(),
old_pin.expose_secret().as_ptr() as *mut u8,
old_pin.expose_secret().len().try_into()?,
new_pin.expose_secret().as_ptr() as *mut u8,
new_pin.expose_secret().len().try_into()?,
))
.into_result()
}
}
}
cryptoki-0.6.1/src/slot/mod.rs 0000644 0000000 0000000 00000003451 10461020230 0014374 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
// Depending on the target, CK_SLOT_ID is not u64
#![allow(clippy::useless_conversion)]
//! Slot and token types
mod slot_info;
mod token_info;
pub use slot_info::SlotInfo;
pub use token_info::{Limit, TokenInfo};
use crate::error::{Error, Result};
use cryptoki_sys::CK_SLOT_ID;
use std::convert::{TryFrom, TryInto};
use std::fmt::Formatter;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
/// Type identifying a slot
pub struct Slot {
slot_id: CK_SLOT_ID,
}
impl std::fmt::LowerHex for Slot {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let val = self.slot_id;
std::fmt::LowerHex::fmt(&val, f)
}
}
impl std::fmt::UpperHex for Slot {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let val = self.slot_id;
std::fmt::UpperHex::fmt(&val, f)
}
}
impl Slot {
pub(crate) fn new(slot_id: CK_SLOT_ID) -> Slot {
Slot { slot_id }
}
/// Underlying ID used for a slot
pub fn id(&self) -> u64 {
self.slot_id.into()
}
}
impl TryFrom for Slot {
type Error = Error;
fn try_from(slot_id: u64) -> Result {
Ok(Self {
slot_id: slot_id.try_into()?,
})
}
}
impl TryFrom for Slot {
type Error = Error;
fn try_from(slot_id: u32) -> Result {
Ok(Self {
slot_id: slot_id.try_into()?,
})
}
}
impl From for usize {
fn from(slot: Slot) -> Self {
slot.slot_id as usize
}
}
impl From for CK_SLOT_ID {
fn from(slot: Slot) -> Self {
slot.slot_id
}
}
impl std::fmt::Display for Slot {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.slot_id)
}
}
cryptoki-0.6.1/src/slot/slot_info.rs 0000644 0000000 0000000 00000007617 10461020230 0015621 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! PKCS11 Slot info and associated flags
use crate::{string_from_blank_padded, types::Version};
use bitflags::bitflags;
use cryptoki_sys::*;
use std::fmt::Debug;
bitflags! {
/// Collection of flags defined for [`CK_SLOT_INFO`]
struct SlotInfoFlags: CK_FLAGS {
const TOKEN_PRESENT=CKF_TOKEN_PRESENT;
const REMOVABLE_DEVICE=CKF_REMOVABLE_DEVICE;
const HW_SLOT = CKF_HW_SLOT;
}
}
/// Information about a slot
#[derive(Debug, Clone)]
pub struct SlotInfo {
slot_description: String,
manufacturer_id: String,
flags: SlotInfoFlags,
hardware_version: Version,
firmware_version: Version,
}
impl SlotInfo {
/// String description of the slot
///
/// **[Conformance](crate#conformance-notes):**
/// This string is maximally 64 bytes (*not* chars) as UTF-8
pub fn slot_description(&self) -> &str {
&self.slot_description
}
/// ID of the slot manufacturer
///
/// **[Conformance](crate#conformance-notes):**
/// This string is maximally 32 bytes (*not* chars) as UTF-8
pub fn manufacturer_id(&self) -> &str {
&self.manufacturer_id
}
/// True if a token is in the slot (e.g., a device is in the reader).
///
/// **[Conformance](crate#conformance-notes):**
/// If this slot does not represent a removable device, a token is *always*
/// considered to be present. That is, `slot.removable_device() == false`
/// implies `slot.token_present() == true`.
pub fn token_present(&self) -> bool {
self.flags.contains(SlotInfoFlags::TOKEN_PRESENT)
}
/// True if the reader supports removable devices.
///
/// **[Conformance](crate#conformance-notes):**
/// For a given slot, this flag *never* changes
pub fn removable_device(&self) -> bool {
self.flags.contains(SlotInfoFlags::REMOVABLE_DEVICE)
}
/// True if the slot is a hardware slot, as opposed to a software slot
/// implementing a "soft token"
pub fn hardware_slot(&self) -> bool {
self.flags.contains(SlotInfoFlags::HW_SLOT)
}
/// Version number of the slot's hardware
pub fn hardware_version(&self) -> Version {
self.hardware_version
}
/// Version number of the slot's firmware
pub fn firmware_version(&self) -> Version {
self.firmware_version
}
}
#[doc(hidden)]
impl From for SlotInfo {
fn from(val: CK_SLOT_INFO) -> Self {
Self {
slot_description: string_from_blank_padded(&val.slotDescription),
manufacturer_id: string_from_blank_padded(&val.manufacturerID),
flags: SlotInfoFlags::from_bits_truncate(val.flags),
hardware_version: val.hardwareVersion.into(),
firmware_version: val.firmwareVersion.into(),
}
}
}
#[cfg(test)]
mod test {
use super::{SlotInfo, SlotInfoFlags};
use crate::types::Version;
#[test]
fn debug_flags_all() {
let expected = "TOKEN_PRESENT | REMOVABLE_DEVICE | HW_SLOT";
let all = SlotInfoFlags::all();
let observed = format!("{all:#?}");
assert_eq!(observed, expected);
}
#[test]
fn debug_info() {
let info = SlotInfo {
slot_description: String::from("Slot Description"),
manufacturer_id: String::from("Manufacturer ID"),
flags: SlotInfoFlags::empty(),
hardware_version: Version::new(0, 255),
firmware_version: Version::new(255, 0),
};
let expected = r#"SlotInfo {
slot_description: "Slot Description",
manufacturer_id: "Manufacturer ID",
flags: (empty),
hardware_version: Version {
major: 0,
minor: 255,
},
firmware_version: Version {
major: 255,
minor: 0,
},
}"#;
let observed = format!("{info:#?}");
assert_eq!(observed, expected);
}
}
cryptoki-0.6.1/src/slot/token_info.rs 0000644 0000000 0000000 00000050304 10461020230 0015747 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! PKCS11 Token info and associated flags
use crate::error::{Error, Result};
use crate::string_from_blank_padded;
use crate::types::convert_utc_time;
use crate::types::{UtcTime, Version};
use bitflags::bitflags;
use cryptoki_sys::*;
use std::convert::TryFrom;
use std::fmt::Debug;
bitflags! {
/// Collection of flags defined for [`CK_TOKEN_INFO`]
struct TokenInfoFlags: CK_FLAGS {
const RNG = CKF_RNG;
const WRITE_PROTECTED = CKF_WRITE_PROTECTED;
const LOGIN_REQUIRED = CKF_LOGIN_REQUIRED;
const USER_PIN_INITIALIZED = CKF_USER_PIN_INITIALIZED;
const RESTORE_KEY_NOT_NEEDED = CKF_RESTORE_KEY_NOT_NEEDED;
const CLOCK_ON_TOKEN = CKF_CLOCK_ON_TOKEN;
const PROTECTED_AUTHENTICATION_PATH = CKF_PROTECTED_AUTHENTICATION_PATH;
const DUAL_CRYPTO_OPERATIONS = CKF_DUAL_CRYPTO_OPERATIONS;
const TOKEN_INITIALIZED = CKF_TOKEN_INITIALIZED;
const SECONDARY_AUTHENTICATION = CKF_SECONDARY_AUTHENTICATION;
const USER_PIN_COUNT_LOW = CKF_USER_PIN_COUNT_LOW;
const USER_PIN_FINAL_TRY = CKF_USER_PIN_FINAL_TRY;
const USER_PIN_LOCKED = CKF_USER_PIN_LOCKED;
const USER_PIN_TO_BE_CHANGED = CKF_USER_PIN_TO_BE_CHANGED;
const SO_PIN_COUNT_LOW = CKF_SO_PIN_COUNT_LOW;
const SO_PIN_FINAL_TRY = CKF_SO_PIN_FINAL_TRY;
const SO_PIN_LOCKED = CKF_SO_PIN_LOCKED;
const SO_PIN_TO_BE_CHANGED = CKF_SO_PIN_TO_BE_CHANGED;
const ERROR_STATE = CKF_ERROR_STATE;
}
}
#[derive(Debug, Clone, Copy)]
/// A limiting value for the token that may or may not take an explicit value
pub enum Limit {
/// There is an explicit value for this limit
Max(u64),
/// The token does not provide information about this limit
Unavailable,
/// The limit is "effectively infinite" and may be treated as such
Infinite,
}
/// Information about a token
#[derive(Debug, Clone)]
pub struct TokenInfo {
// The following four strings are limited in size based on
// the orignating struct definition. Sizes are in *bytes*
// but UTF-8 data may represent fewer characters.
// Original buffers were space (0x20) padded.
label: String, // len <= 32 bytes
manufacturer_id: String, // len <= 32 bytes
model: String, // len <= 16 bytes
serial_number: String, // len <= 16 bytes
flags: TokenInfoFlags,
max_session_count: Limit,
session_count: Option,
max_rw_session_count: Limit,
rw_session_count: Option,
max_pin_len: usize,
min_pin_len: usize,
total_public_memory: Option,
free_public_memory: Option,
total_private_memory: Option,
free_private_memory: Option,
hardware_version: Version,
firmware_version: Version,
utc_time: Option,
}
trait MaybeUnavailable: Sized {
fn maybe_unavailable(value: CK_ULONG) -> Option;
}
impl MaybeUnavailable for usize {
fn maybe_unavailable(value: CK_ULONG) -> Option {
if value == CK_UNAVAILABLE_INFORMATION {
None
} else {
Some(value as usize)
}
}
}
impl MaybeUnavailable for u64 {
fn maybe_unavailable(value: CK_ULONG) -> Option {
if value == CK_UNAVAILABLE_INFORMATION {
None
} else {
// Must have cast for when ulong is 32 bits
Some(value.into())
}
}
}
/// Flattens both `Infinite` and `Unavailable` to `None`,
impl From for Option {
fn from(limit: Limit) -> Self {
match limit {
Limit::Unavailable | Limit::Infinite => None,
Limit::Max(n) => Some(n),
}
}
}
fn maybe_unlimited(value: CK_ULONG) -> Limit {
match value {
CK_UNAVAILABLE_INFORMATION => Limit::Unavailable,
CK_EFFECTIVELY_INFINITE => Limit::Infinite,
// Must have cast for when ulong is 32 bits
_ => Limit::Max(value.into()),
}
}
impl TokenInfo {
/// An application-defined label, assigned during token initialization
///
/// **[Conformance](crate#conformance-notes):**
/// This string is maximally 32 bytes (*not* chars) as UTF-8
pub fn label(&self) -> &str {
&self.label
}
/// The ID of the device manufacturer
///
/// **[Conformance](crate#conformance-notes):**
/// This string is maximally 32 bytes (*not* chars) as UTF-8
pub fn manufacturer_id(&self) -> &str {
&self.manufacturer_id
}
/// The model of the device
///
/// **[Conformance](crate#conformance-notes):**
/// This string is maximally 16 bytes (*not* chars) as UTF-8
pub fn model(&self) -> &str {
&self.model
}
/// The character-string serial number of the device
///
/// **[Conformance](crate#conformance-notes):**
/// This string is maximally 16 bytes (*not* chars) as UTF-8
pub fn serial_number(&self) -> &str {
&self.serial_number
}
/// True if the token has its own random number generator
pub fn rng(&self) -> bool {
self.flags.contains(TokenInfoFlags::RNG)
}
/// True if the token is write-protected
///
/// **[Conformance](crate#conformance-notes):**
/// Exactly what this value means is determined by the application. An
/// application may be unable to perform certain actions on a write-
/// protected token. These actions can include any of the following (non-
/// exhaustive):
/// * Creating/modifying/deleting any object on the token
/// * Creating/modifying/deleting a token object on the token
/// * Changing the Security Officer's PIN
/// * Changing the normal user's PIN
///
/// The token may change its write-protected status depending on the
/// session state to implement its object management policy. For instance,
/// the token may report write-protection unless the session state is R/W
/// SO or R/W User to implement a policy that does not allow any objects,
/// public or private, to be created, modified, or deleted unless the user
/// has successfully called [`Session::login`](crate::session::Session::login).
pub fn write_protected(&self) -> bool {
self.flags.contains(TokenInfoFlags::WRITE_PROTECTED)
}
/// True if there are some cryptographic functions that a user *must* be
/// logged in to perform
pub fn login_required(&self) -> bool {
self.flags.contains(TokenInfoFlags::LOGIN_REQUIRED)
}
/// True of the normal user's PIN has been initialized
pub fn user_pin_initialized(&self) -> bool {
self.flags.contains(TokenInfoFlags::USER_PIN_INITIALIZED)
}
/// True if a successful save of a session's cryptographic operations state
/// *always* contains all keys needed to restore the state of the session.
pub fn restore_key_not_needed(&self) -> bool {
self.flags.contains(TokenInfoFlags::RESTORE_KEY_NOT_NEEDED)
}
/// True if the token has its own hardware clock
pub fn clock_on_token(&self) -> bool {
self.flags.contains(TokenInfoFlags::CLOCK_ON_TOKEN)
}
/// True if the token has a "protected authentication path" whereby a user
/// can log into the token without passing a PIN
pub fn protected_authentication_path(&self) -> bool {
self.flags
.contains(TokenInfoFlags::PROTECTED_AUTHENTICATION_PATH)
}
/// True if a single session with the token can perform dual cryptographic
/// operations
// TODO: Requires Session callbacks to access
// * digest_encrypt_update
// * decrypt_digest_update
// * sign_encrypt_update
// * decrypt_verify_update
pub fn dual_crypto_operations(&self) -> bool {
self.flags.contains(TokenInfoFlags::DUAL_CRYPTO_OPERATIONS)
}
/// True if the token has been initialized with
/// [`Pkcs11::init_token](crate::context::Pkcs11::init_token) or an
/// equivalent mechanism outside the scope of the PKCS#11 standard
///
/// **[Conformance](crate#conformance-notes):**
/// Calling [`Pkcs11::init_token`](crate::context::Pkcs11::init_token) when
/// this flag is set will cause the token to be reinitialized.
pub fn token_initialized(&self) -> bool {
self.flags.contains(TokenInfoFlags::TOKEN_INITIALIZED)
}
/// True if the token supports secondary authentication for private key
/// objects
/// **[Conformance](crate#conformance-notes):**
/// This field is deprecated and new providers *must not* set it. I.e., this function must always return `false`.
pub fn secondary_authentication(&self) -> bool {
self.flags
.contains(TokenInfoFlags::SECONDARY_AUTHENTICATION)
}
/// True if an incorrect user login PIN has been entered at least once
/// since the last successful authentication
///
/// **[Conformance](crate#conformance-notes):**
/// This value may be set to always be false if the token either does not
/// support the functionality or will not reveal the information because of
/// its security policy.
pub fn user_pin_count_low(&self) -> bool {
self.flags.contains(TokenInfoFlags::USER_PIN_COUNT_LOW)
}
/// True if supplying an incorrect user PIN will cause it to become locked
///
/// **[Conformance](crate#conformance-notes):**
/// This value may be set to always be false if the token either does not
/// support the functionality or will not reveal the information because of
/// its security policy.
pub fn user_pin_final_try(&self) -> bool {
self.flags.contains(TokenInfoFlags::USER_PIN_FINAL_TRY)
}
/// True if the user PIN has been locked; user login to the token is not
/// possible
pub fn user_pin_locked(&self) -> bool {
self.flags.contains(TokenInfoFlags::USER_PIN_LOCKED)
}
/// True if the user PIN value is the default value set by the token
/// initialization or manufacturing, or the PIN has been expired by the
/// card
///
/// **[Conformance](crate#conformance-notes):**
/// This may be always false if the token either does not support the
/// functionality or will not reveal the information because of its
/// security policy.
///
/// If a PIN is set to the default value or has expired, this function
/// returns `true`. When true, logging in with a PIN will succeed, but only
/// the [`Session::set_pin`][crate::session::Session::set_pin] function can
/// be called. Calling any other function that required the user to be
/// logged in will cause [`PinExpired`][crate::error::RvError::PinExpired]
/// to be returned until
/// [`Session::set_pin`][crate::session::Session::set_pin] is called
/// successfully.
pub fn user_pin_to_be_changed(&self) -> bool {
self.flags.contains(TokenInfoFlags::USER_PIN_TO_BE_CHANGED)
}
/// True if an incorrect Security Officer login PIN has been entered at least once since
/// the last successful authentication
///
/// **[Conformance](crate#conformance-notes):**
/// This value may be set to always be false if the token either does not
/// support the functionality or will not reveal the information because of
/// its security policy.
pub fn so_pin_count_low(&self) -> bool {
self.flags.contains(TokenInfoFlags::SO_PIN_COUNT_LOW)
}
/// True if supplying an incorrect Security Officer PIN will cause it to become locked
///
/// **[Conformance](crate#conformance-notes):**
/// This value may be set to always be false if the token either does not
/// support the functionality or will not reveal the information because of
/// its security policy.
pub fn so_pin_final_try(&self) -> bool {
self.flags.contains(TokenInfoFlags::SO_PIN_FINAL_TRY)
}
/// True if the Security Officer PIN has been locked; Security Officer login to the token is not
/// possible
pub fn so_pin_locked(&self) -> bool {
self.flags.contains(TokenInfoFlags::SO_PIN_LOCKED)
}
/// True if the Security Officer PIN value is the default value set by the token
/// initialization or manufacturing, or the PIN has been expired by the card
///
/// **[Conformance](crate#conformance-notes):**
/// This may be always false if the token either does not support the
/// functionality or will not reveal the information because of its security
/// policy.
///
/// If a PIN is set to the default value or has expired, this function
/// returns `true`. When true, logging in with a PIN will succeed, but only
/// the [`Session::set_pin`][crate::session::Session::set_pin] function can
/// be called. Calling any other function that required the user to be
/// logged in will cause [`PinExpired`][crate::error::RvError::PinExpired]
/// to be returned until
/// [`Session::set_pin`][crate::session::Session::set_pin] is called
/// successfully.
pub fn so_pin_to_be_changed(&self) -> bool {
self.flags.contains(TokenInfoFlags::SO_PIN_TO_BE_CHANGED)
}
/// True if the token failed a FIPS 140-2 self-test and entered an error state
pub fn error_state(&self) -> bool {
self.flags.contains(TokenInfoFlags::ERROR_STATE)
}
/// The maximum number of sessions that can be opened with the token at one
/// time by a single application.
pub fn max_session_count(&self) -> Limit {
self.max_session_count
}
/// The number of sessions this application currently has open with the
/// token
pub fn session_count(&self) -> Option {
self.session_count
}
/// The maximum number of read/write sessions that can be opened with the
/// token at one time by a single application.
pub fn max_rw_session_count(&self) -> Limit {
self.max_rw_session_count
}
/// The number of read/write sessions this application currently has open
/// with the token
pub fn rw_session_count(&self) -> Option {
self.rw_session_count
}
/// The maximum length in bytes of the PIN
pub fn max_pin_length(&self) -> usize {
self.max_pin_len
}
/// The minimum length in bytes of the PIN
pub fn min_pin_length(&self) -> usize {
self.min_pin_len
}
/// The total amount of memory on the token (in bytes) in which public
/// objects may be stored
/// Returns `None` if this information is unavailable
pub fn total_public_memory(&self) -> Option {
self.total_public_memory
}
/// The amount of free (unused) emmeory on the token (in bytes) for public
/// objects
/// Returns `None` if this information is unavailable
pub fn free_public_memory(&self) -> Option {
self.free_public_memory
}
/// The total amount of memory on the token (in bytes) in which private
/// objects may be stored
/// Returns `None` if this information is unavailable
pub fn total_private_memory(&self) -> Option {
self.total_private_memory
}
/// The amount of free (unused) emmeory on the token (in bytes) for private
/// objects
/// Returns `None` if this information is unavailable
pub fn free_private_memory(&self) -> Option {
self.free_private_memory
}
/// The version number of the hardware
pub fn hardware_version(&self) -> Version {
self.hardware_version
}
/// The version number of the firmware
pub fn firmware_version(&self) -> Version {
self.firmware_version
}
/// The current UTC datetime reported by the token
///
/// Returns `None` if the token is not equipped with a clock (i.e.,
/// `self.clock_on_token() == false`)
///
/// **[Conformance](crate#conformance-notes):**
/// The string representation of the datetime from the token is only
/// required to be parsable as a string of ASCII digits. No additional
/// structure (e.g., months numbered from 0 or from 1) is defined.
pub fn utc_time(&self) -> Option {
self.utc_time
}
}
#[doc(hidden)]
impl TryFrom for TokenInfo {
type Error = Error;
fn try_from(val: CK_TOKEN_INFO) -> Result {
let flags = TokenInfoFlags::from_bits_truncate(val.flags);
let utc_time = if flags.contains(TokenInfoFlags::CLOCK_ON_TOKEN) {
Some(convert_utc_time(val.utcTime)?)
} else {
None
};
Ok(Self {
label: string_from_blank_padded(&val.label),
manufacturer_id: string_from_blank_padded(&val.manufacturerID),
model: string_from_blank_padded(&val.model),
serial_number: string_from_blank_padded(&val.serialNumber),
flags,
max_session_count: maybe_unlimited(val.ulMaxSessionCount),
session_count: u64::maybe_unavailable(val.ulSessionCount),
max_rw_session_count: maybe_unlimited(val.ulMaxRwSessionCount),
rw_session_count: u64::maybe_unavailable(val.ulRwSessionCount),
max_pin_len: val.ulMaxPinLen as usize,
min_pin_len: val.ulMinPinLen as usize,
total_public_memory: usize::maybe_unavailable(val.ulTotalPublicMemory),
free_public_memory: usize::maybe_unavailable(val.ulFreePublicMemory),
total_private_memory: usize::maybe_unavailable(val.ulTotalPrivateMemory),
free_private_memory: usize::maybe_unavailable(val.ulFreePrivateMemory),
hardware_version: val.hardwareVersion.into(),
firmware_version: val.firmwareVersion.into(),
utc_time,
})
}
}
#[cfg(test)]
mod test {
use super::{Limit, TokenInfo, TokenInfoFlags};
use crate::types::{UtcTime, Version};
#[test]
fn debug_flags_all() {
let expected = "\
RNG | WRITE_PROTECTED | LOGIN_REQUIRED | USER_PIN_INITIALIZED | \
RESTORE_KEY_NOT_NEEDED | CLOCK_ON_TOKEN | PROTECTED_AUTHENTICATION_PATH | \
DUAL_CRYPTO_OPERATIONS | TOKEN_INITIALIZED | SECONDARY_AUTHENTICATION | \
USER_PIN_COUNT_LOW | USER_PIN_FINAL_TRY | USER_PIN_LOCKED | \
USER_PIN_TO_BE_CHANGED | SO_PIN_COUNT_LOW | SO_PIN_FINAL_TRY | SO_PIN_LOCKED | \
SO_PIN_TO_BE_CHANGED | ERROR_STATE";
let all = TokenInfoFlags::all();
let observed = format!("{all:#?}");
assert_eq!(observed, expected);
}
#[test]
fn debug_info() {
let info = TokenInfo {
label: String::from("Token Label"),
manufacturer_id: String::from("Manufacturer ID"),
model: String::from("Token Model"),
serial_number: String::from("Serial Number"),
flags: TokenInfoFlags::empty(),
max_session_count: Limit::Max(100), // max == 100
session_count: None, // unavailable
max_rw_session_count: Limit::Infinite, // max == infinite
rw_session_count: Some(1),
max_pin_len: 16,
min_pin_len: 4,
total_public_memory: Some(32 << 30), // 32GiB
free_public_memory: Some(1234567890),
total_private_memory: None, // unavailable
free_private_memory: None, // unavailable
hardware_version: Version::new(0, 255),
firmware_version: Version::new(255, 0),
utc_time: Some(UtcTime {
year: 1970,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
}),
};
let expected = r#"TokenInfo {
label: "Token Label",
manufacturer_id: "Manufacturer ID",
model: "Token Model",
serial_number: "Serial Number",
flags: (empty),
max_session_count: Max(
100,
),
session_count: None,
max_rw_session_count: Infinite,
rw_session_count: Some(
1,
),
max_pin_len: 16,
min_pin_len: 4,
total_public_memory: Some(
34359738368,
),
free_public_memory: Some(
1234567890,
),
total_private_memory: None,
free_private_memory: None,
hardware_version: Version {
major: 0,
minor: 255,
},
firmware_version: Version {
major: 255,
minor: 0,
},
utc_time: Some(
UtcTime {
year: 1970,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
},
),
}"#;
let observed = format!("{info:#?}");
assert_eq!(observed, expected);
}
}
cryptoki-0.6.1/src/types.rs 0000644 0000000 0000000 00000022327 10461020230 0014003 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! PKCS11 General Data Types
use crate::error::{Error, Result};
use cryptoki_sys::*;
use secrecy::SecretString;
use secrecy::SecretVec;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::fmt::Formatter;
use std::ops::Deref;
#[derive(Debug, Copy, Clone, Default)]
#[repr(transparent)]
/// Value that represents a date
pub struct Date {
date: CK_DATE,
}
impl Date {
/// Creates a new `Date` structure
///
/// # Arguments
///
/// * `year` - A 4 character length year, e.g. "2021"
/// * `month` - A 2 character length mont, e.g. "02"
/// * `day` - A 2 character length day, e.g. "15"
///
/// # Errors
///
/// If the lengths are invalid a `Error::InvalidValue` will be returned
pub fn new_from_str_slice(year: &str, month: &str, day: &str) -> Result {
if year.len() != 4 || month.len() != 2 || day.len() != 2 {
Err(Error::InvalidValue)
} else {
let mut year_slice: [u8; 4] = Default::default();
let mut month_slice: [u8; 2] = Default::default();
let mut day_slice: [u8; 2] = Default::default();
year_slice.copy_from_slice(year.as_bytes());
month_slice.copy_from_slice(month.as_bytes());
day_slice.copy_from_slice(day.as_bytes());
Ok(Date::new(year_slice, month_slice, day_slice))
}
}
/// Creates a new `Date` structure from byte slices
///
/// # Arguments
///
/// * `year` - A 4 character length year, e.g. "2021"
/// * `month` - A 2 character length mont, e.g. "02"
/// * `day` - A 2 character length day, e.g. "15"
pub fn new(year: [u8; 4], month: [u8; 2], day: [u8; 2]) -> Self {
let date = CK_DATE { year, month, day };
Self { date }
}
/// Creates a new, empty `Date` structure
///
/// This represents the default value of the attribute (on
/// newer implementations of `Cryptoki`).
pub fn new_empty() -> Self {
Self::default()
}
/// Check if `Date` is empty
///
/// *NOTE*: This function is only representative of newer implementations
/// of `Cryptoki`, for which dates are represented as empty object attributes.
pub fn is_empty(&self) -> bool {
self.date.year == <[u8; 4]>::default()
&& self.date.month == <[u8; 2]>::default()
&& self.date.day == <[u8; 2]>::default()
}
}
impl Deref for Date {
type Target = CK_DATE;
fn deref(&self) -> &Self::Target {
&self.date
}
}
impl From for CK_DATE {
fn from(date: Date) -> Self {
*date
}
}
impl From for Date {
fn from(date: CK_DATE) -> Self {
Self { date }
}
}
impl std::fmt::Display for Date {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let year = String::from_utf8_lossy(Vec::from(self.year).as_slice())
.trim_end()
.to_string();
let month = String::from_utf8_lossy(Vec::from(self.month).as_slice())
.trim_end()
.to_string();
let day = String::from_utf8_lossy(Vec::from(self.day).as_slice())
.trim_end()
.to_string();
write!(f, "Month: {month}\nDay: {day}\nYear: {year}")
}
}
impl PartialEq for Date {
fn eq(&self, other: &Self) -> bool {
self.date.year == other.date.year
&& self.date.month == other.date.month
&& self.date.day == other.date.day
}
}
impl Eq for Date {}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
/// Unsigned value, at least 32 bits long
pub struct Ulong {
val: CK_ULONG,
}
impl Deref for Ulong {
type Target = CK_ULONG;
fn deref(&self) -> &Self::Target {
&self.val
}
}
impl From for CK_ULONG {
fn from(ulong: Ulong) -> Self {
*ulong
}
}
impl From for Ulong {
fn from(ulong: CK_ULONG) -> Self {
Ulong { val: ulong }
}
}
impl TryFrom for Ulong {
type Error = Error;
fn try_from(ulong: usize) -> Result {
Ok(Ulong {
val: ulong.try_into()?,
})
}
}
impl From for usize {
fn from(ulong: Ulong) -> Self {
ulong.val as usize
}
}
impl std::fmt::Display for Ulong {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.val)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// Represents a version
pub struct Version {
major: CK_BYTE,
minor: CK_BYTE,
}
impl std::fmt::Display for Version {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}", self.major, self.minor)
}
}
impl Version {
/// Construct a new version
#[cfg(test)]
pub(crate) fn new(major: u8, minor: u8) -> Self {
Self { major, minor }
}
/// Returns the major version
pub fn major(&self) -> CK_BYTE {
self.major
}
/// Returns the minor version
pub fn minor(&self) -> CK_BYTE {
self.minor
}
}
impl From for CK_VERSION {
fn from(version: Version) -> Self {
CK_VERSION {
major: version.major,
minor: version.minor,
}
}
}
impl From for Version {
fn from(version: CK_VERSION) -> Self {
Version {
major: version.major,
minor: version.minor,
}
}
}
/// A UTC datetime returned by a token's clock if present.
#[derive(Copy, Clone, Debug)]
pub struct UtcTime {
/// **[Conformance](crate#conformance-notes):**
/// Guaranteed to be in range 0..=9999
pub year: u16,
/// **[Conformance](crate#conformance-notes):**
/// Guaranteed to be in range 0..=99
pub month: u8,
/// **[Conformance](crate#conformance-notes):**
/// Guaranteed to be in range 0..=99
pub day: u8,
/// **[Conformance](crate#conformance-notes):**
/// Guaranteed to be in range 0..=99
pub hour: u8,
/// **[Conformance](crate#conformance-notes):**
/// Guaranteed to be in range 0..=99
pub minute: u8,
/// **[Conformance](crate#conformance-notes):**
/// Guaranteed to be in range 0..=99
pub second: u8,
}
impl UtcTime {
/// Stringify the structure in ISO 8601 format.
///
/// PKCS#11 and ISO are unrelated standards, and this function is provided
/// only for convenience. ISO format is more widely recognized and parsable
/// by various date/time utilities, while PKCS#11's internal representation
/// of this type is is not used elsewhere.
/// Other than formatting, this crate does not guarantee or enforce any part
/// of the ISO standard.
pub fn as_iso8601_string(&self) -> String {
format!(
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
self.year, self.month, self.day, self.hour, self.minute, self.second
)
}
}
// UTC time has the format YYYYMMDDhhmmss00 as ASCII digits
pub(crate) fn convert_utc_time(orig: [u8; 16]) -> Result {
// Note: No validaiton of these values beyond being ASCII digits
// because PKCS#11 doesn't impose any such restrictions.
Ok(UtcTime {
year: std::str::from_utf8(&orig[0..4])?.parse()?,
month: std::str::from_utf8(&orig[4..6])?.parse()?,
day: std::str::from_utf8(&orig[6..8])?.parse()?,
hour: std::str::from_utf8(&orig[8..10])?.parse()?,
minute: std::str::from_utf8(&orig[10..12])?.parse()?,
second: std::str::from_utf8(&orig[12..14])?.parse()?,
})
}
/// Secret wrapper for a Pin
///
/// Enable the `serde` feature to add support for Deserialize
pub type AuthPin = SecretString;
/// Secret wrapper for a raw non UTF-8 Pin
///
/// Enable the `serde` feature to add support for Deserialize
pub type RawAuthPin = SecretVec;
#[cfg(test)]
mod test {
use super::*;
const UTC_TIME: UtcTime = UtcTime {
year: 1970,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
};
#[test]
fn utc_time_convert_good() {
let valid: [u8; 16] = [
0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30,
];
let valid = convert_utc_time(valid).unwrap();
assert_eq!(valid.year, UTC_TIME.year);
assert_eq!(valid.month, UTC_TIME.month);
assert_eq!(valid.day, UTC_TIME.day);
assert_eq!(valid.hour, UTC_TIME.hour);
assert_eq!(valid.minute, UTC_TIME.minute);
assert_eq!(valid.second, UTC_TIME.second);
}
#[test]
fn utc_time_convert_bad() {
// Year starts with a non-numeric value ('A')
let invalid: [u8; 16] = [
0x41, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30,
];
let invalid = convert_utc_time(invalid);
assert!(invalid.is_err());
}
#[test]
fn utc_time_debug_fmt() {
let expected = r#"UtcTime {
year: 1970,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
}"#;
let observed = format!("{UTC_TIME:#?}");
assert_eq!(observed, expected);
}
#[test]
fn utc_time_display_fmt() {
let iso_format = UTC_TIME.as_iso8601_string();
assert_eq!(&iso_format, "1970-01-01T00:00:00Z");
}
}
cryptoki-0.6.1/tests/basic.rs 0000644 0000000 0000000 00000101504 10461020230 0014266 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
mod common;
use crate::common::{get_pkcs11, SO_PIN, USER_PIN};
use common::init_pins;
use cryptoki::error::{Error, RvError};
use cryptoki::mechanism::aead::GcmParams;
use cryptoki::mechanism::rsa::{PkcsMgfType, PkcsOaepParams, PkcsOaepSource};
use cryptoki::mechanism::{Mechanism, MechanismType};
use cryptoki::object::{Attribute, AttributeInfo, AttributeType, KeyType, ObjectClass};
use cryptoki::session::{SessionState, UserType};
use cryptoki::types::AuthPin;
use serial_test::serial;
use std::collections::HashMap;
use std::thread;
use testresult::TestResult;
#[test]
#[serial]
fn sign_verify() -> TestResult {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot)?;
// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// get mechanism
let mechanism = Mechanism::RsaPkcsKeyPairGen;
let public_exponent: Vec = vec![0x01, 0x00, 0x01];
let modulus_bits = 1024;
// pub key template
let pub_key_template = vec![
Attribute::Token(true),
Attribute::Private(false),
Attribute::PublicExponent(public_exponent),
Attribute::ModulusBits(modulus_bits.into()),
];
// priv key template
let priv_key_template = vec![Attribute::Token(true)];
// generate a key pair
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
// data to sign
let data = [0xFF, 0x55, 0xDD];
// sign something with it
let signature = session.sign(&Mechanism::RsaPkcs, private, &data)?;
// verify the signature
session.verify(&Mechanism::RsaPkcs, public, &data, &signature)?;
// delete keys
session.destroy_object(public)?;
session.destroy_object(private)?;
Ok(())
}
#[test]
#[serial]
fn sign_verify_ed25519() -> TestResult {
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let mechanism = Mechanism::EccEdwardsKeyPairGen;
let pub_key_template = vec![
Attribute::Token(true),
Attribute::Private(false),
Attribute::Verify(true),
// Ed25519 OID
// See: https://github.com/opendnssec/SoftHSMv2/blob/ac70dc398b236e4522101930e790008936489e2d/src/lib/test/SignVerifyTests.cpp#L173
Attribute::EcParams(vec![
0x13, 0x0c, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x35, 0x35, 0x31, 0x39,
]),
];
let priv_key_template = vec![Attribute::Token(true)];
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
let data = [0xFF, 0x55, 0xDD];
let signature = session.sign(&Mechanism::Eddsa, private, &data)?;
session.verify(&Mechanism::Eddsa, public, &data, &signature)?;
session.destroy_object(public)?;
session.destroy_object(private)?;
Ok(())
}
#[test]
#[serial]
fn encrypt_decrypt() -> TestResult {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot)?;
// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// get mechanism
let mechanism = Mechanism::RsaPkcsKeyPairGen;
let public_exponent: Vec = vec![0x01, 0x00, 0x01];
let modulus_bits = 1024;
// pub key template
let pub_key_template = vec![
Attribute::Token(true),
Attribute::Private(false),
Attribute::PublicExponent(public_exponent),
Attribute::ModulusBits(modulus_bits.into()),
Attribute::Encrypt(true),
];
// priv key template
let priv_key_template = vec![Attribute::Token(true), Attribute::Decrypt(true)];
// generate a key pair
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
// data to encrypt
let data = vec![0xFF, 0x55, 0xDD];
// encrypt something with it
let encrypted_data = session.encrypt(&Mechanism::RsaPkcs, public, &data)?;
// decrypt
let decrypted_data = session.decrypt(&Mechanism::RsaPkcs, private, &encrypted_data)?;
// The decrypted buffer is bigger than the original one.
assert_eq!(data, decrypted_data);
// delete keys
session.destroy_object(public)?;
session.destroy_object(private)?;
Ok(())
}
#[test]
#[serial]
fn derive_key() -> TestResult {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot)?;
// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// get mechanism
let mechanism = Mechanism::EccKeyPairGen;
let secp256r1_oid: Vec = vec![0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
// pub key template
let pub_key_template = vec![
Attribute::Token(true),
Attribute::Private(false),
Attribute::Derive(true),
Attribute::KeyType(KeyType::EC),
Attribute::Verify(true),
Attribute::EcParams(secp256r1_oid),
];
// priv key template
let priv_key_template = vec![
Attribute::Token(true),
Attribute::Private(true),
Attribute::Sensitive(true),
Attribute::Extractable(false),
Attribute::Derive(true),
Attribute::Sign(true),
];
// generate a key pair
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
let ec_point_attribute = session
.get_attributes(public, &[AttributeType::EcPoint])?
.remove(0);
let ec_point = if let Attribute::EcPoint(point) = ec_point_attribute {
point
} else {
panic!("Expected EC point attribute.");
};
use cryptoki::mechanism::elliptic_curve::*;
let params = Ecdh1DeriveParams::new(EcKdf::null(), &ec_point);
let shared_secret = session.derive_key(
&Mechanism::Ecdh1Derive(params),
private,
&[
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::KeyType(KeyType::GENERIC_SECRET),
Attribute::Sensitive(false),
Attribute::Extractable(true),
Attribute::Token(false),
],
)?;
let value_attribute = session
.get_attributes(shared_secret, &[AttributeType::Value])?
.remove(0);
let value = if let Attribute::Value(value) = value_attribute {
value
} else {
panic!("Expected value attribute.");
};
assert_eq!(value.len(), 32);
// delete keys
session.destroy_object(public)?;
session.destroy_object(private)?;
Ok(())
}
#[test]
#[serial]
fn import_export() -> TestResult {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot)?;
// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let public_exponent: Vec = vec![0x01, 0x00, 0x01];
let modulus = vec![0xFF; 1024];
let template = vec![
Attribute::Token(true),
Attribute::Private(false),
Attribute::PublicExponent(public_exponent),
Attribute::Modulus(modulus.clone()),
Attribute::Class(ObjectClass::PUBLIC_KEY),
Attribute::KeyType(KeyType::RSA),
Attribute::Verify(true),
];
{
// Intentionally forget the object handle to find it later
let _public_key = session.create_object(&template)?;
}
let is_it_the_public_key = session.find_objects(&template)?.remove(0);
let attribute_info = session
.get_attribute_info(is_it_the_public_key, &[AttributeType::Modulus])?
.remove(0);
if let AttributeInfo::Available(size) = attribute_info {
assert_eq!(size, 1024);
} else {
panic!("The Modulus attribute was expected to be present.")
};
let attr = session
.get_attributes(is_it_the_public_key, &[AttributeType::Modulus])?
.remove(0);
if let Attribute::Modulus(modulus_cmp) = attr {
assert_eq!(modulus[..], modulus_cmp[..]);
} else {
panic!("Expected the Modulus attribute.");
}
// delete key
session.destroy_object(is_it_the_public_key)?;
Ok(())
}
#[test]
#[serial]
fn get_token_info() -> TestResult {
let (pkcs11, slot) = init_pins();
let info = pkcs11.get_token_info(slot)?;
assert_eq!("SoftHSM project", info.manufacturer_id());
Ok(())
}
#[test]
#[serial]
fn wrap_and_unwrap_key() {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot).unwrap();
// log in the session
session
.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))
.unwrap();
let key_to_be_wrapped_template = vec![
Attribute::Token(true),
// the key needs to be extractable to be suitable for being wrapped
Attribute::Extractable(true),
Attribute::Encrypt(true),
];
// generate a secret key that will be wrapped
let key_to_be_wrapped = session
.generate_key(&Mechanism::Des3KeyGen, &key_to_be_wrapped_template)
.unwrap();
// Des3Ecb input length must be a multiple of 8
// see: PKCS#11 spec Table 10-10, DES-ECB Key And Data Length Constraints
let encrypted_with_original = session
.encrypt(
&Mechanism::Des3Ecb,
key_to_be_wrapped,
&[1, 2, 3, 4, 5, 6, 7, 8],
)
.unwrap();
// pub key template
let pub_key_template = vec![
Attribute::Token(true),
Attribute::Private(true),
Attribute::PublicExponent(vec![0x01, 0x00, 0x01]),
Attribute::ModulusBits(1024.into()),
// key needs to have "wrap" attribute to wrap other keys
Attribute::Wrap(true),
];
// priv key template
let priv_key_template = vec![Attribute::Token(true)];
let (wrapping_key, unwrapping_key) = session
.generate_key_pair(
&Mechanism::RsaPkcsKeyPairGen,
&pub_key_template,
&priv_key_template,
)
.unwrap();
let wrapped_key = session
.wrap_key(&Mechanism::RsaPkcs, wrapping_key, key_to_be_wrapped)
.unwrap();
assert_eq!(wrapped_key.len(), 128);
let unwrapped_key = session
.unwrap_key(
&Mechanism::RsaPkcs,
unwrapping_key,
&wrapped_key,
&[
Attribute::Token(true),
Attribute::Private(true),
Attribute::Encrypt(true),
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::KeyType(KeyType::DES3),
],
)
.unwrap();
let encrypted_with_unwrapped = session
.encrypt(
&Mechanism::Des3Ecb,
unwrapped_key,
&[1, 2, 3, 4, 5, 6, 7, 8],
)
.unwrap();
assert_eq!(encrypted_with_original, encrypted_with_unwrapped);
}
#[test]
#[serial]
fn login_feast() {
const SESSIONS: usize = 100;
let (pkcs11, slot) = init_pins();
let mut threads = Vec::new();
for _ in 0..SESSIONS {
let pkcs11 = pkcs11.clone();
threads.push(thread::spawn(move || {
let session = pkcs11.open_rw_session(slot).unwrap();
match session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into()))) {
Ok(_) | Err(Error::Pkcs11(RvError::UserAlreadyLoggedIn)) => {}
Err(e) => panic!("Bad error response: {}", e),
}
match session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into()))) {
Ok(_) | Err(Error::Pkcs11(RvError::UserAlreadyLoggedIn)) => {}
Err(e) => panic!("Bad error response: {}", e),
}
match session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into()))) {
Ok(_) | Err(Error::Pkcs11(RvError::UserAlreadyLoggedIn)) => {}
Err(e) => panic!("Bad error response: {}", e),
}
match session.logout() {
Ok(_) | Err(Error::Pkcs11(RvError::UserNotLoggedIn)) => {}
Err(e) => panic!("Bad error response: {}", e),
}
match session.logout() {
Ok(_) | Err(Error::Pkcs11(RvError::UserNotLoggedIn)) => {}
Err(e) => panic!("Bad error response: {}", e),
}
match session.logout() {
Ok(_) | Err(Error::Pkcs11(RvError::UserNotLoggedIn)) => {}
Err(e) => panic!("Bad error response: {}", e),
}
}));
}
for thread in threads {
thread.join().unwrap();
}
}
#[test]
#[serial]
fn get_info_test() -> TestResult {
let (pkcs11, _) = init_pins();
let info = pkcs11.get_library_info()?;
assert_eq!(info.cryptoki_version().major(), 2);
assert_eq!(info.cryptoki_version().minor(), 40);
assert_eq!(info.manufacturer_id(), String::from("SoftHSM"));
Ok(())
}
#[test]
#[serial]
fn get_slot_info_test() -> TestResult {
let (pkcs11, slot) = init_pins();
let slot_info = pkcs11.get_slot_info(slot)?;
assert!(slot_info.token_present());
assert!(!slot_info.hardware_slot());
assert!(!slot_info.removable_device());
assert_eq!(slot_info.manufacturer_id(), String::from("SoftHSM project"));
Ok(())
}
#[test]
#[serial]
fn get_session_info_test() -> TestResult {
let (pkcs11, slot) = init_pins();
{
let session = pkcs11.open_ro_session(slot)?;
let session_info = session.get_session_info()?;
assert!(!session_info.read_write());
assert_eq!(session_info.slot_id(), slot);
assert!(matches!(
session_info.session_state(),
SessionState::RoPublic
));
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let session_info = session.get_session_info()?;
assert!(!session_info.read_write());
assert_eq!(session_info.slot_id(), slot);
assert!(matches!(session_info.session_state(), SessionState::RoUser));
session.logout()?;
if let Err(cryptoki::error::Error::Pkcs11(rv_error)) =
session.login(UserType::So, Some(&AuthPin::new(SO_PIN.into())))
{
assert_eq!(rv_error, RvError::SessionReadOnlyExists)
} else {
panic!("Should error when attempting to log in as CKU_SO on a read-only session");
}
}
let session = pkcs11.open_rw_session(slot)?;
let session_info = session.get_session_info()?;
assert!(session_info.read_write());
assert_eq!(session_info.slot_id(), slot);
assert!(matches!(
session_info.session_state(),
SessionState::RwPublic
));
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let session_info = session.get_session_info()?;
assert!(session_info.read_write());
assert_eq!(session_info.slot_id(), slot);
assert!(matches!(session_info.session_state(), SessionState::RwUser,));
session.logout()?;
session.login(UserType::So, Some(&AuthPin::new(SO_PIN.into())))?;
let session_info = session.get_session_info()?;
assert!(session_info.read_write());
assert_eq!(session_info.slot_id(), slot);
assert!(matches!(
session_info.session_state(),
SessionState::RwSecurityOfficer
));
Ok(())
}
#[test]
#[serial]
fn generate_random_test() -> TestResult {
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_ro_session(slot)?;
let poor_seed: [u8; 32] = [0; 32];
session.seed_random(&poor_seed)?;
let mut random_data: [u8; 32] = [0; 32];
session.generate_random_slice(&mut random_data)?;
// This of course assumes the RBG in the the SoftHSM is not terrible
assert!(!random_data.iter().all(|&x| x == 0));
let random_vec = session.generate_random_vec(32)?;
assert_eq!(random_vec.len(), 32);
assert!(!random_vec.iter().all(|&x| x == 0));
Ok(())
}
#[test]
#[serial]
fn set_pin_test() -> TestResult {
let new_user_pin = "123456";
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_rw_session(slot)?;
let user_pin = AuthPin::new(USER_PIN.into());
let new_user_pin = AuthPin::new(new_user_pin.into());
session.login(UserType::User, Some(&user_pin))?;
session.set_pin(&user_pin, &new_user_pin)?;
session.logout()?;
session.login(UserType::User, Some(&new_user_pin))?;
Ok(())
}
#[test]
#[serial]
fn get_attribute_info_test() -> TestResult {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot)?;
// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// get mechanism
let mechanism = Mechanism::RsaPkcsKeyPairGen;
let public_exponent: Vec = vec![0x01, 0x00, 0x01];
let modulus_bits = 2048;
// pub key template
let pub_key_template = vec![
Attribute::Token(false),
Attribute::Private(false),
Attribute::PublicExponent(public_exponent),
Attribute::ModulusBits(modulus_bits.into()),
];
// priv key template
let priv_key_template = vec![
Attribute::Token(false),
Attribute::Sensitive(true),
Attribute::Extractable(false),
];
// generate a key pair
let (public, private) =
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
let pub_attribs = vec![AttributeType::PublicExponent, AttributeType::Modulus];
let mut priv_attribs = pub_attribs.clone();
priv_attribs.push(AttributeType::PrivateExponent);
let attrib_info = session.get_attribute_info(public, &pub_attribs)?;
let hash = pub_attribs
.iter()
.zip(attrib_info.iter())
.collect::>();
if let AttributeInfo::Available(size) = hash[&AttributeType::Modulus] {
assert_eq!(*size, 2048 / 8);
} else {
panic!("Modulus should not return Unavailable for an RSA public key");
}
match hash[&AttributeType::PublicExponent] {
AttributeInfo::Available(_) => {}
_ => panic!("Public Exponent should not return Unavailable for an RSA public key"),
}
let attrib_info = session.get_attribute_info(private, &priv_attribs)?;
let hash = priv_attribs
.iter()
.zip(attrib_info.iter())
.collect::>();
if let AttributeInfo::Available(size) = hash[&AttributeType::Modulus] {
assert_eq!(*size, 2048 / 8);
} else {
panic!("Modulus should not return Unavailable on an RSA private key");
}
match hash[&AttributeType::PublicExponent] {
AttributeInfo::Available(_) => {}
_ => panic!("PublicExponent should not return Unavailable on an RSA private key"),
}
match hash[&AttributeType::PrivateExponent] {
AttributeInfo::Sensitive => {}
_ => panic!("Private Exponent of RSA private key should be sensitive"),
}
let hash = session.get_attribute_info_map(private, priv_attribs)?;
if let AttributeInfo::Available(size) = hash[&AttributeType::Modulus] {
assert_eq!(size, 2048 / 8);
} else {
panic!("Modulus should not return Unavailable on an RSA private key");
}
match hash[&AttributeType::PublicExponent] {
AttributeInfo::Available(_) => {}
_ => panic!("Public Exponent should not return Unavailable for an RSA private key"),
}
match hash[&AttributeType::PrivateExponent] {
AttributeInfo::Sensitive => {}
_ => panic!("Private Exponent of RSA private key should be sensitive"),
}
Ok(())
}
#[test]
#[serial]
fn is_fn_supported_test() {
use cryptoki::context::Function;
let (pkcs11, _) = init_pins();
assert!(
pkcs11.is_fn_supported(Function::Initialize),
"C_Initialize function reports as not supported"
);
assert!(
pkcs11.is_fn_supported(Function::Sign),
"C_Sign function reports as not supported"
);
assert!(
pkcs11.is_fn_supported(Function::DigestFinal),
"C_DigestFinal function reports as not supported"
);
}
#[test]
#[serial]
fn is_initialized_test() {
use cryptoki::context::CInitializeArgs;
let pkcs11 = get_pkcs11();
assert!(
!pkcs11.is_initialized(),
"Context created with initialized flag on"
);
// initialize the library
pkcs11.initialize(CInitializeArgs::OsThreads).unwrap();
assert!(
pkcs11.is_initialized(),
"Context was not marked as initialized"
);
match pkcs11.initialize(CInitializeArgs::OsThreads) {
Err(Error::AlreadyInitialized) => (),
Err(e) => panic!("Got unexpected error when initializing: {}", e),
Ok(()) => panic!("Initializing twice should not have been allowed"),
}
}
#[test]
#[serial]
#[allow(clippy::redundant_clone)]
fn test_clone_initialize() {
use cryptoki::context::CInitializeArgs;
let pkcs11 = get_pkcs11();
let clone = pkcs11.clone();
assert!(
!pkcs11.is_initialized(),
"Before initialize() it should not be initialized"
);
assert!(
!clone.is_initialized(),
"Before initialize() the clone should not be initialized"
);
pkcs11.initialize(CInitializeArgs::OsThreads).unwrap();
assert!(
pkcs11.is_initialized(),
"After initialize() it should be initialized"
);
assert!(
clone.is_initialized(),
"After initialize() the clone should be initialized"
);
}
#[test]
#[serial]
fn aes_key_attributes_test() -> TestResult {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot)?;
// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// get mechanism
let mechanism = Mechanism::AesKeyGen;
// pub key template
let key_template = vec![
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::Token(true),
Attribute::Sensitive(true),
Attribute::ValueLen(16.into()),
Attribute::KeyType(KeyType::AES),
Attribute::Label(b"testAES".to_vec()),
Attribute::Private(true),
];
// generate a key pair
let key = session.generate_key(&mechanism, &key_template)?;
let mut attributes_result =
session.get_attributes(key, &[AttributeType::EndDate, AttributeType::StartDate])?;
if let Some(Attribute::StartDate(date)) = attributes_result.pop() {
assert!(date.is_empty());
} else {
panic!("Last attribute was not a start date");
}
if let Some(Attribute::EndDate(date)) = attributes_result.pop() {
assert!(date.is_empty());
} else {
panic!("First attribute was not an end date");
}
Ok(())
}
#[test]
#[serial]
fn ro_rw_session_test() -> TestResult {
let public_exponent: Vec = vec![0x01, 0x00, 0x01];
let modulus = vec![0xFF; 1024];
let template = vec![
Attribute::Token(true),
Attribute::Private(false),
Attribute::PublicExponent(public_exponent),
Attribute::Modulus(modulus),
Attribute::Class(ObjectClass::PUBLIC_KEY),
Attribute::KeyType(KeyType::RSA),
Attribute::Verify(true),
];
let (pkcs11, slot) = init_pins();
// Try out Read-Only session
{
// open a session
let ro_session = pkcs11.open_ro_session(slot)?;
// log in the session
ro_session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// generate a key pair
// This should NOT work using the Read-Only session
let e = ro_session.create_object(&template).unwrap_err();
if let Error::Pkcs11(RvError::SessionReadOnly) = e {
// as expected
} else {
panic!("Got wrong error code (expecting SessionReadOnly): {}", e);
}
ro_session.logout()?;
}
// Try out Read/Write session
{
// open a session
let rw_session = pkcs11.open_rw_session(slot)?;
// log in the session
rw_session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// generate a key pair
// This should work using the Read/Write session
let object = rw_session.create_object(&template)?;
// delete keys
rw_session.destroy_object(object)?;
rw_session.logout()?;
}
Ok(())
}
#[test]
#[serial]
fn aes_cbc_encrypt() -> TestResult {
// Encrypt two blocks of zeros with AES-128-CBC, and zero IV
let key = vec![0; 16];
let iv = [0; 16];
let plain = [0; 32];
let expected_cipher = [
0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b, 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b,
0x2e, 0xf7, 0x95, 0xbd, 0x4a, 0x52, 0xe2, 0x9e, 0xd7, 0x13, 0xd3, 0x13, 0xfa, 0x20, 0xe9,
0x8d, 0xbc,
];
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let template = [
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::KeyType(KeyType::AES),
Attribute::Value(key),
Attribute::Encrypt(true),
];
let key_handle = session.create_object(&template)?;
let mechanism = Mechanism::AesCbc(iv);
let cipher = session.encrypt(&mechanism, key_handle, &plain)?;
assert_eq!(expected_cipher[..], cipher[..]);
Ok(())
}
#[test]
#[serial]
fn aes_cbc_pad_encrypt() -> TestResult {
// Encrypt two blocks of zeros with AES-128-CBC and PKCS#7 padding, and zero IV
let key = vec![0; 16];
let iv = [0; 16];
let plain = [0; 32];
let expected_cipher = [
0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b, 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b,
0x2e, 0xf7, 0x95, 0xbd, 0x4a, 0x52, 0xe2, 0x9e, 0xd7, 0x13, 0xd3, 0x13, 0xfa, 0x20, 0xe9,
0x8d, 0xbc, 0x5c, 0x04, 0x76, 0x16, 0x75, 0x6f, 0xdc, 0x1c, 0x32, 0xe0, 0xdf, 0x6e, 0x8c,
0x59, 0xbb, 0x2a,
];
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let template = [
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::KeyType(KeyType::AES),
Attribute::Value(key),
Attribute::Encrypt(true),
];
let key_handle = session.create_object(&template)?;
let mechanism = Mechanism::AesCbcPad(iv);
let cipher = session.encrypt(&mechanism, key_handle, &plain)?;
assert_eq!(expected_cipher[..], cipher[..]);
Ok(())
}
#[test]
#[serial]
fn update_attributes_key() -> TestResult {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot)?;
// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// pub key template
let pub_key_template = vec![
Attribute::Token(true),
Attribute::Private(true),
Attribute::PublicExponent(vec![0x01, 0x00, 0x01]),
Attribute::ModulusBits(1024.into()),
];
// priv key template
let priv_key_template = vec![Attribute::Token(true), Attribute::Extractable(true)];
let (_public_key, private_key) = session.generate_key_pair(
&Mechanism::RsaPkcsKeyPairGen,
&pub_key_template,
&priv_key_template,
)?;
let updated_attributes = vec![Attribute::Extractable(false)];
session.update_attributes(private_key, &updated_attributes)?;
let mut attributes_result =
session.get_attributes(private_key, &[AttributeType::Extractable])?;
if let Some(Attribute::Extractable(ext)) = attributes_result.pop() {
assert!(!ext);
} else {
panic!("Last attribute was not extractable");
}
Ok(())
}
#[test]
#[serial]
fn sha256_digest() -> TestResult {
let (pkcs11, slot) = init_pins();
// open a session
let session = pkcs11.open_rw_session(slot)?;
// log in the session
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
// data to digest
let data = vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
let want = [
0x17, 0x22, 0x6b, 0x1f, 0x68, 0xae, 0xba, 0xcd, 0xef, 0x07, 0x46, 0x45, 0x0f, 0x64, 0x28,
0x74, 0x63, 0x8b, 0x29, 0x57, 0x07, 0xef, 0x73, 0xfb, 0x2c, 0x6b, 0xb7, 0xf8, 0x8e, 0x89,
0x92, 0x9f,
];
let have = session.digest(&Mechanism::Sha256, &data)?;
assert_eq!(want[..], have[..]);
Ok(())
}
#[test]
#[serial]
// Currently empty AAD crashes SoftHSM, see: https://github.com/opendnssec/SoftHSMv2/issues/605
#[ignore]
fn aes_gcm_no_aad() -> TestResult {
// Encrypt two blocks of zeros with AES-128-GCM
let key = vec![0; 16];
let iv = [0; 12];
let aad = [];
let plain = [0; 32];
let expected_cipher_and_tag = [
0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe,
0x78, 0xf7, 0x95, 0xaa, 0xab, 0x49, 0x4b, 0x59, 0x23, 0xf7, 0xfd, 0x89, 0xff, 0x94, 0x8b,
0xc1, 0xe0, 0x40, 0x49, 0x0a, 0xf4, 0x80, 0x56, 0x06, 0xb2, 0xa3, 0xa2, 0xe7, 0x93,
];
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let template = [
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::KeyType(KeyType::AES),
Attribute::Value(key),
Attribute::Encrypt(true),
];
let key_handle = session.create_object(&template)?;
let mechanism = Mechanism::AesGcm(GcmParams::new(&iv, &aad, 96.into()));
let cipher_and_tag = session.encrypt(&mechanism, key_handle, &plain)?;
assert_eq!(expected_cipher_and_tag[..], cipher_and_tag[..]);
Ok(())
}
#[test]
#[serial]
fn aes_gcm_with_aad() -> TestResult {
// Encrypt a block of zeros with AES-128-GCM.
// Use another block of zeros for AAD.
let key = vec![0; 16];
let iv = [0; 12];
let aad = [0; 16];
let plain = [0; 16];
let expected_cipher_and_tag = [
0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe,
0x78, 0xd2, 0x4e, 0x50, 0x3a, 0x1b, 0xb0, 0x37, 0x07, 0x1c, 0x71, 0xb3, 0x5d,
];
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let template = [
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::KeyType(KeyType::AES),
Attribute::Value(key),
Attribute::Encrypt(true),
];
let key_handle = session.create_object(&template)?;
let mechanism = Mechanism::AesGcm(GcmParams::new(&iv, &aad, 96.into()));
let cipher_and_tag = session.encrypt(&mechanism, key_handle, &plain)?;
assert_eq!(expected_cipher_and_tag[..], cipher_and_tag[..]);
Ok(())
}
#[test]
#[serial]
fn rsa_pkcs_oaep_empty() -> TestResult {
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let pub_key_template = [Attribute::ModulusBits(2048.into())];
let (pubkey, privkey) =
session.generate_key_pair(&Mechanism::RsaPkcsKeyPairGen, &pub_key_template, &[])?;
let oaep = PkcsOaepParams::new(
MechanismType::SHA1,
PkcsMgfType::MGF1_SHA1,
PkcsOaepSource::empty(),
);
let encrypt_mechanism: Mechanism = Mechanism::RsaPkcsOaep(oaep);
let encrypted_data = session.encrypt(&encrypt_mechanism, pubkey, b"Hello")?;
let decrypted_data = session.decrypt(&encrypt_mechanism, privkey, &encrypted_data)?;
let decrypted = String::from_utf8(decrypted_data)?;
assert_eq!("Hello", decrypted);
Ok(())
}
#[test]
#[serial]
#[ignore] // it's not clear why the test with data specified fails
fn rsa_pkcs_oaep_with_data() -> TestResult {
let (pkcs11, slot) = init_pins();
let session = pkcs11.open_rw_session(slot)?;
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
let pub_key_template = [Attribute::ModulusBits(2048.into())];
let (pubkey, privkey) =
session.generate_key_pair(&Mechanism::RsaPkcsKeyPairGen, &pub_key_template, &[])?;
let oaep = PkcsOaepParams::new(
MechanismType::SHA1,
PkcsMgfType::MGF1_SHA1,
PkcsOaepSource::data_specified(&[1, 2, 3, 4, 5, 6, 7, 8]),
);
let encrypt_mechanism: Mechanism = Mechanism::RsaPkcsOaep(oaep);
let encrypted_data = session.encrypt(&encrypt_mechanism, pubkey, b"Hello")?;
let decrypted_data = session.decrypt(&encrypt_mechanism, privkey, &encrypted_data)?;
let decrypted = String::from_utf8(decrypted_data)?;
assert_eq!("Hello", decrypted);
Ok(())
}
#[test]
#[serial]
fn get_slot_event() -> TestResult {
// Not implemented in SoftHSMv2
// https://github.com/opendnssec/SoftHSMv2/issues/370
let (pkcs11, _slot) = init_pins();
let event = pkcs11.get_slot_event()?;
assert_eq!(None, event);
Ok(())
}
#[test]
#[serial]
fn wait_for_slot_event() {
// Not implemented in SoftHSMv2
// https://github.com/opendnssec/SoftHSMv2/issues/370
let (pkcs11, _slot) = init_pins();
let res = pkcs11.wait_for_slot_event();
assert!(
matches!(res, Err(Error::Pkcs11(RvError::FunctionNotSupported))),
"res = {:?}",
res
);
}
cryptoki-0.6.1/tests/common.rs 0000644 0000000 0000000 00000002306 10461020230 0014475 0 ustar 0000000 0000000 // Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
use cryptoki::context::{CInitializeArgs, Pkcs11};
use cryptoki::session::UserType;
use cryptoki::slot::Slot;
use cryptoki::types::AuthPin;
use std::env;
// The default user pin
pub static USER_PIN: &str = "fedcba";
// The default SO pin
pub static SO_PIN: &str = "abcdef";
pub fn get_pkcs11() -> Pkcs11 {
Pkcs11::new(
env::var("PKCS11_SOFTHSM2_MODULE")
.unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()),
)
.unwrap()
}
pub fn init_pins() -> (Pkcs11, Slot) {
let pkcs11 = get_pkcs11();
// initialize the library
pkcs11.initialize(CInitializeArgs::OsThreads).unwrap();
// find a slot, get the first one
let slot = pkcs11.get_slots_with_token().unwrap().remove(0);
let so_pin = AuthPin::new(SO_PIN.into());
pkcs11.init_token(slot, &so_pin, "Test Token").unwrap();
{
// open a session
let session = pkcs11.open_rw_session(slot).unwrap();
// log in the session
session.login(UserType::So, Some(&so_pin)).unwrap();
session.init_pin(&AuthPin::new(USER_PIN.into())).unwrap();
}
(pkcs11, slot)
}