Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cryptoki/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ log = "0.4.14"
derivative = "2.2.0"
psa-crypto = { version = "0.9.0", default-features = false, optional = true }
cryptoki-sys = { path = "../cryptoki-sys", version = "0.1.3" }
paste = "1.0.6"

[dev-dependencies]
num-traits = "0.2.14"
Expand Down
165 changes: 164 additions & 1 deletion cryptoki/src/context/general_purpose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
use crate::context::{CInitializeArgs, Info, Pkcs11};
use crate::error::{Result, Rv};
use cryptoki_sys::{CK_C_INITIALIZE_ARGS, CK_INFO};
use paste::paste;
use std::convert::TryFrom;

// See public docs on stub in parent mod.rs
#[inline(always)]
pub(super) fn initialize(ctx: &Pkcs11, init_args: CInitializeArgs) -> Result<()> {
pub(super) fn initialize(ctx: &mut Pkcs11, init_args: CInitializeArgs) -> Result<()> {
// if no args are specified, library expects NULL
let mut init_args = CK_C_INITIALIZE_ARGS::from(init_args);
let init_args_ptr = &mut init_args;
Expand All @@ -18,6 +19,9 @@ pub(super) fn initialize(ctx: &Pkcs11, init_args: CInitializeArgs) -> Result<()>
init_args_ptr as *mut CK_C_INITIALIZE_ARGS as *mut ::std::ffi::c_void,
))
.into_result()
.map(|_| {
ctx.initialized = true;
})
}
}

Expand All @@ -30,3 +34,162 @@ pub(super) fn get_library_info(ctx: &Pkcs11) -> Result<Info> {
Info::try_from(info)
}
}

macro_rules! check_fn {
($pkcs11:expr, $func_name:ident) => {
paste! { $pkcs11
.impl_
.function_list
.[< C_ $func_name >]
.is_some()
}
};
}

#[allow(clippy::enum_variant_names, missing_docs)]
#[derive(Debug, Copy, Clone)]
/// Enumeration of all functions defined by the PKCS11 spec
pub enum Function {
Initialize,
Finalize,
GetInfo,
GetFunctionList,
GetSlotList,
GetSlotInfo,
GetTokenInfo,
GetMechanismList,
GetMechanismInfo,
InitToken,
InitPIN,
SetPIN,
OpenSession,
CloseSession,
CloseAllSessions,
GetSessionInfo,
GetOperationState,
SetOperationState,
Login,
Logout,
CreateObject,
CopyObject,
DestroyObject,
GetObjectSize,
GetAttributeValue,
SetAttributeValue,
FindObjectsInit,
FindObjects,
FindObjectsFinal,
EncryptInit,
Encrypt,
EncryptUpdate,
EncryptFinal,
DecryptInit,
Decrypt,
DecryptUpdate,
DecryptFinal,
DigestInit,
Digest,
DigestUpdate,
DigestKey,
DigestFinal,
SignInit,
Sign,
SignUpdate,
SignFinal,
SignRecoverInit,
SignRecover,
VerifyInit,
Verify,
VerifyUpdate,
VerifyFinal,
VerifyRecoverInit,
VerifyRecover,
DigestEncryptUpdate,
DecryptDigestUpdate,
SignEncryptUpdate,
DecryptVerifyUpdate,
GenerateKey,
GenerateKeyPair,
WrapKey,
UnwrapKey,
DeriveKey,
SeedRandom,
GenerateRandom,
GetFunctionStatus,
CancelFunction,
WaitForSlotEvent,
}

#[inline(always)]
pub(super) fn is_fn_supported(ctx: &Pkcs11, function: Function) -> bool {
match function {
Function::Initialize => check_fn!(ctx, Initialize),
Function::Finalize => check_fn!(ctx, Finalize),
Function::GetInfo => check_fn!(ctx, GetInfo),
Function::GetFunctionList => check_fn!(ctx, GetFunctionList),
Function::GetSlotList => check_fn!(ctx, GetSlotList),
Function::GetSlotInfo => check_fn!(ctx, GetSlotInfo),
Function::GetTokenInfo => check_fn!(ctx, GetTokenInfo),
Function::GetMechanismList => check_fn!(ctx, GetMechanismList),
Function::GetMechanismInfo => check_fn!(ctx, GetMechanismInfo),
Function::InitToken => check_fn!(ctx, InitToken),
Function::InitPIN => check_fn!(ctx, InitPIN),
Function::SetPIN => check_fn!(ctx, SetPIN),
Function::OpenSession => check_fn!(ctx, OpenSession),
Function::CloseSession => check_fn!(ctx, CloseSession),
Function::CloseAllSessions => check_fn!(ctx, CloseAllSessions),
Function::GetSessionInfo => check_fn!(ctx, GetSessionInfo),
Function::GetOperationState => check_fn!(ctx, GetOperationState),
Function::SetOperationState => check_fn!(ctx, SetOperationState),
Function::Login => check_fn!(ctx, Login),
Function::Logout => check_fn!(ctx, Logout),
Function::CreateObject => check_fn!(ctx, CreateObject),
Function::CopyObject => check_fn!(ctx, CopyObject),
Function::DestroyObject => check_fn!(ctx, DestroyObject),
Function::GetObjectSize => check_fn!(ctx, GetObjectSize),
Function::GetAttributeValue => check_fn!(ctx, GetAttributeValue),
Function::SetAttributeValue => check_fn!(ctx, SetAttributeValue),
Function::FindObjectsInit => check_fn!(ctx, FindObjectsInit),
Function::FindObjects => check_fn!(ctx, FindObjects),
Function::FindObjectsFinal => check_fn!(ctx, FindObjectsFinal),
Function::EncryptInit => check_fn!(ctx, EncryptInit),
Function::Encrypt => check_fn!(ctx, Encrypt),
Function::EncryptUpdate => check_fn!(ctx, EncryptUpdate),
Function::EncryptFinal => check_fn!(ctx, EncryptFinal),
Function::DecryptInit => check_fn!(ctx, DecryptInit),
Function::Decrypt => check_fn!(ctx, Decrypt),
Function::DecryptUpdate => check_fn!(ctx, DecryptUpdate),
Function::DecryptFinal => check_fn!(ctx, DecryptFinal),
Function::DigestInit => check_fn!(ctx, DigestInit),
Function::Digest => check_fn!(ctx, Digest),
Function::DigestUpdate => check_fn!(ctx, DigestUpdate),
Function::DigestKey => check_fn!(ctx, DigestKey),
Function::DigestFinal => check_fn!(ctx, DigestFinal),
Function::SignInit => check_fn!(ctx, SignInit),
Function::Sign => check_fn!(ctx, Sign),
Function::SignUpdate => check_fn!(ctx, SignUpdate),
Function::SignFinal => check_fn!(ctx, SignFinal),
Function::SignRecoverInit => check_fn!(ctx, SignRecoverInit),
Function::SignRecover => check_fn!(ctx, SignRecover),
Function::VerifyInit => check_fn!(ctx, VerifyInit),
Function::Verify => check_fn!(ctx, Verify),
Function::VerifyUpdate => check_fn!(ctx, VerifyUpdate),
Function::VerifyFinal => check_fn!(ctx, VerifyFinal),
Function::VerifyRecoverInit => check_fn!(ctx, VerifyRecoverInit),
Function::VerifyRecover => check_fn!(ctx, VerifyRecover),
Function::DigestEncryptUpdate => check_fn!(ctx, DigestEncryptUpdate),
Function::DecryptDigestUpdate => check_fn!(ctx, DecryptDigestUpdate),
Function::SignEncryptUpdate => check_fn!(ctx, SignEncryptUpdate),
Function::DecryptVerifyUpdate => check_fn!(ctx, DecryptVerifyUpdate),
Function::GenerateKey => check_fn!(ctx, GenerateKey),
Function::GenerateKeyPair => check_fn!(ctx, GenerateKeyPair),
Function::WrapKey => check_fn!(ctx, WrapKey),
Function::UnwrapKey => check_fn!(ctx, UnwrapKey),
Function::DeriveKey => check_fn!(ctx, DeriveKey),
Function::SeedRandom => check_fn!(ctx, SeedRandom),
Function::GenerateRandom => check_fn!(ctx, GenerateRandom),
Function::GetFunctionStatus => check_fn!(ctx, GetFunctionStatus),
Function::CancelFunction => check_fn!(ctx, CancelFunction),
Function::WaitForSlotEvent => check_fn!(ctx, WaitForSlotEvent),
}
}
25 changes: 21 additions & 4 deletions cryptoki/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod session_management;
mod slot_token_management;

use cryptoki_sys::{CK_FALSE, CK_TRUE};
pub use general_purpose::*;
pub use info::*;
pub use locking::*;

Expand Down Expand Up @@ -74,10 +75,11 @@ impl Drop for Pkcs11Impl {
#[derive(Clone, Debug)]
pub struct Pkcs11 {
pub(crate) impl_: Arc<Pkcs11Impl>,
initialized: bool,
}

impl Pkcs11 {
/// Instantiate a new context from the path of a PKCS11 dynamic llibrary implementation.
/// Instantiate a new context from the path of a PKCS11 dynamic library implementation.
pub fn new<P>(filename: P) -> Result<Self>
where
P: AsRef<Path>,
Expand All @@ -96,13 +98,23 @@ impl Pkcs11 {
_pkcs11_lib: pkcs11_lib,
function_list: *list_ptr,
}),
initialized: false,
})
}
}

/// Initialize the PKCS11 library
pub fn initialize(&self, init_args: CInitializeArgs) -> Result<()> {
general_purpose::initialize(self, init_args)
pub fn initialize(&mut self, init_args: CInitializeArgs) -> Result<()> {
if !self.initialized {
initialize(self, init_args)
} else {
Err(Error::AlreadyInitialized)
}
}

/// Check whether the PKCS11 library has been initialized
pub fn is_initialized(&self) -> bool {
self.initialized
}

/// Finalize the PKCS11 library. Indicates that the application no longer needs to use PKCS11.
Expand All @@ -111,7 +123,7 @@ impl Pkcs11 {

/// Returns the information about the library
pub fn get_library_info(&self) -> Result<Info> {
general_purpose::get_library_info(self)
get_library_info(self)
}

/// Get all slots available with a token
Expand Down Expand Up @@ -160,4 +172,9 @@ impl Pkcs11 {
pub fn open_session_no_callback(&self, slot_id: Slot, read_write: bool) -> Result<Session> {
session_management::open_session_no_callback(self, slot_id, read_write)
}

/// 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)
}
}
7 changes: 6 additions & 1 deletion cryptoki/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pub enum Error {

/// The PIN was not set before logging in.
PinNotSet,

/// The PKCS11 library has already been initialized
AlreadyInitialized,
}

impl fmt::Display for Error {
Expand All @@ -62,6 +65,7 @@ impl fmt::Display for Error {
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"),
}
}
}
Expand All @@ -79,7 +83,8 @@ impl std::error::Error for Error {
| Error::NotSupported
| Error::NullFunctionPointer
| Error::PinNotSet
| Error::InvalidValue => None,
| Error::InvalidValue
| Error::AlreadyInitialized => None,
}
}
}
Expand Down
76 changes: 42 additions & 34 deletions cryptoki/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -877,48 +877,56 @@ impl TryFrom<CK_ATTRIBUTE> for Attribute {
)
};
let types: Vec<MechanismType> = val
.to_vec()
.into_iter()
.iter()
.copied()
.map(|t| t.try_into())
.collect::<Result<Vec<MechanismType>>>()?;
Ok(Attribute::AllowedMechanisms(types))
}
AttributeType::EndDate => {
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(),
)?))
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 => {
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(),
)?))
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(),
)?))
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion cryptoki/src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl Session {
/// use std::collections::HashMap;
/// use std::env;
///
/// let pkcs11 = Pkcs11::new(
/// let mut pkcs11 = Pkcs11::new(
/// env::var("PKCS11_SOFTHSM2_MODULE")
/// .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()),
/// )
Expand Down
Loading