diff --git a/cryptoki/src/context/mod.rs b/cryptoki/src/context/mod.rs index c6f25e3a..ae2ddb29 100644 --- a/cryptoki/src/context/mod.rs +++ b/cryptoki/src/context/mod.rs @@ -19,15 +19,11 @@ mod locking; mod session_management; mod slot_token_management; -use cryptoki_sys::{CK_FALSE, CK_TRUE}; pub use general_purpose::*; pub use info::*; pub use locking::*; use crate::error::{Error, Result, Rv}; -use crate::mechanism::{MechanismInfo, MechanismType}; -use crate::session::Session; -use crate::slot::{Slot, SlotInfo, TokenInfo}; use derivative::Derivative; use log::error; @@ -126,64 +122,6 @@ impl Pkcs11 { get_library_info(self) } - /// Get all slots available with a token - pub fn get_slots_with_token(&self) -> Result> { - slot_token_management::get_slots(self, CK_TRUE) - } - - /// Get all slots available with a token - pub fn get_slots_with_initialized_token(&self) -> Result> { - slot_token_management::get_slots_with_initialized_token(self) - } - - /// Get all slots - pub fn get_all_slots(&self) -> Result> { - slot_token_management::get_slots(self, CK_FALSE) - } - - /// Initialize a token - /// - /// Currently will use an empty label for all tokens. - pub fn init_token(&self, slot: Slot, pin: &str, label: &str) -> Result<()> { - slot_token_management::init_token(self, slot, pin, label) - } - - /// Returns the slot info - pub fn get_slot_info(&self, slot: Slot) -> Result { - slot_token_management::get_slot_info(self, slot) - } - - /// Returns information about a specific token - pub fn get_token_info(&self, slot: Slot) -> Result { - slot_token_management::get_token_info(self, slot) - } - - /// Get all mechanisms support by a slot - pub fn get_mechanism_list(&self, slot: Slot) -> Result> { - slot_token_management::get_mechanism_list(self, slot) - } - - /// Get detailed information about a mechanism for a slot - pub fn get_mechanism_info(&self, slot: Slot, type_: MechanismType) -> Result { - slot_token_management::get_mechanism_info(self, slot, type_) - } - - /// 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 { - session_management::open_session(self, 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 { - session_management::open_session(self, slot_id, true) - } - /// 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) diff --git a/cryptoki/src/context/session_management.rs b/cryptoki/src/context/session_management.rs index dbe52e16..d3d55bfc 100644 --- a/cryptoki/src/context/session_management.rs +++ b/cryptoki/src/context/session_management.rs @@ -9,27 +9,45 @@ use crate::error::{Result, Rv}; use crate::session::Session; use crate::slot::Slot; use std::convert::TryInto; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn open_session(ctx: &Pkcs11, 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!(ctx, 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()?; +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())) } - Ok(Session::new(session_handle, ctx.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) + } } diff --git a/cryptoki/src/context/slot_token_management.rs b/cryptoki/src/context/slot_token_management.rs index 77df0b50..4647f1ae 100644 --- a/cryptoki/src/context/slot_token_management.rs +++ b/cryptoki/src/context/slot_token_management.rs @@ -7,154 +7,157 @@ use crate::error::{Result, Rv}; use crate::label_from_str; use crate::mechanism::{MechanismInfo, MechanismType}; use crate::slot::{Slot, SlotInfo, TokenInfo}; -use cryptoki_sys::{CK_BBOOL, CK_MECHANISM_INFO, CK_SLOT_INFO, CK_TOKEN_INFO}; +use cryptoki_sys::{CK_BBOOL, CK_FALSE, CK_MECHANISM_INFO, CK_SLOT_INFO, CK_TOKEN_INFO, CK_TRUE}; use std::convert::{TryFrom, TryInto}; use crate::error::RvError::BufferTooSmall; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_slots(ctx: &Pkcs11, with_token: CK_BBOOL) -> Result> { - let mut slot_count = 0; - let rval = unsafe { - get_pkcs11!(ctx, 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]; +impl Pkcs11 { + #[inline(always)] + fn get_slots(&self, with_token: CK_BBOOL) -> Result> { + let mut slot_count = 0; let rval = unsafe { - get_pkcs11!(ctx, C_GetSlotList)(with_token, slots.as_mut_ptr(), &mut slot_count) + get_pkcs11!(self, C_GetSlotList)(with_token, std::ptr::null_mut(), &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; + 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()) } - // 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()) -} - -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_slots_with_initialized_token(ctx: &Pkcs11) -> Result> { - let slots = ctx.get_slots_with_token()?; - - slots - .into_iter() - .filter_map(|slot| match ctx.get_token_info(slot) { - Ok(token_info) => { - if token_info.token_initialized() { - Some(Ok(slot)) - } else { - None - } - } - Err(e) => Some(Err(e)), - }) - .collect() -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn init_token(ctx: &Pkcs11, slot: Slot, pin: &str, label: &str) -> Result<()> { - let label = label_from_str(label); - unsafe { - Rv::from(get_pkcs11!(ctx, C_InitToken)( - slot.try_into()?, - pin.as_ptr() as *mut u8, - pin.len().try_into()?, - label.as_ptr() as *mut u8, - )) - .into_result() + /// Get all slots available with a token + pub fn get_slots_with_token(&self) -> Result> { + self.get_slots(CK_TRUE) } -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_slot_info(ctx: &Pkcs11, slot: Slot) -> Result { - unsafe { - let mut slot_info = CK_SLOT_INFO::default(); - Rv::from(get_pkcs11!(ctx, C_GetSlotInfo)( - slot.try_into()?, - &mut slot_info, - )) - .into_result()?; - Ok(SlotInfo::from(slot_info)) + /// Get all slots + pub fn get_all_slots(&self) -> Result> { + self.get_slots(CK_FALSE) } -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_token_info(ctx: &Pkcs11, slot: Slot) -> Result { - unsafe { - let mut token_info = CK_TOKEN_INFO::default(); - Rv::from(get_pkcs11!(ctx, C_GetTokenInfo)( - slot.try_into()?, - &mut token_info, - )) - .into_result()?; - TokenInfo::try_from(token_info) + /// 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() } -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_mechanism_list(ctx: &Pkcs11, slot: Slot) -> Result> { - let mut mechanism_count = 0; - - unsafe { - Rv::from(get_pkcs11!(ctx, C_GetMechanismList)( - slot.try_into()?, - std::ptr::null_mut(), - &mut mechanism_count, - )) - .into_result()?; + /// Initialize a token + /// + /// Currently will use an empty label for all tokens. + pub fn init_token(&self, slot: Slot, pin: &str, label: &str) -> Result<()> { + let label = label_from_str(label); + unsafe { + Rv::from(get_pkcs11!(self, C_InitToken)( + slot.try_into()?, + pin.as_ptr() as *mut u8, + pin.len().try_into()?, + label.as_ptr() as *mut u8, + )) + .into_result() + } } - let mut mechanisms = vec![0; mechanism_count.try_into()?]; + /// 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)) + } + } - unsafe { - Rv::from(get_pkcs11!(ctx, C_GetMechanismList)( - slot.try_into()?, - mechanisms.as_mut_ptr(), - &mut mechanism_count, - )) - .into_result()?; + /// 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) + } } - // Truncate mechanisms if count decreased. - mechanisms.truncate(mechanism_count.try_into()?); + /// 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()?; + } - Ok(mechanisms - .into_iter() - .filter_map(|type_| type_.try_into().ok()) - .collect()) -} + let mut mechanisms = vec![0; mechanism_count.try_into()?]; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_mechanism_info( - ctx: &Pkcs11, - slot: Slot, - type_: MechanismType, -) -> Result { - unsafe { - let mut mechanism_info = CK_MECHANISM_INFO::default(); - Rv::from(get_pkcs11!(ctx, C_GetMechanismInfo)( - slot.try_into()?, - type_.into(), - &mut mechanism_info, - )) - .into_result()?; - Ok(MechanismInfo::from(mechanism_info)) + 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)) + } } } diff --git a/cryptoki/src/session/decryption.rs b/cryptoki/src/session/decryption.rs index 242a5661..5cd463bb 100644 --- a/cryptoki/src/session/decryption.rs +++ b/cryptoki/src/session/decryption.rs @@ -9,53 +9,54 @@ use crate::session::Session; use cryptoki_sys::*; use std::convert::TryInto; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn decrypt( - session: &Session, - 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!(session.client(), C_DecryptInit)( - session.handle(), - &mut mechanism as CK_MECHANISM_PTR, - key.handle(), - )) - .into_result()?; +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) } - - // Get the output buffer length - unsafe { - Rv::from(get_pkcs11!(session.client(), C_Decrypt)( - session.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!(session.client(), C_Decrypt)( - session.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) } diff --git a/cryptoki/src/session/encryption.rs b/cryptoki/src/session/encryption.rs index 32e89db0..0caa1f3c 100644 --- a/cryptoki/src/session/encryption.rs +++ b/cryptoki/src/session/encryption.rs @@ -9,52 +9,53 @@ use crate::session::Session; use cryptoki_sys::*; use std::convert::TryInto; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub fn encrypt( - session: &Session, - 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!(session.client(), C_EncryptInit)( - session.handle(), - &mut mechanism as CK_MECHANISM_PTR, - key.handle(), - )) - .into_result()?; +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) } - - // Get the output buffer length - unsafe { - Rv::from(get_pkcs11!(session.client(), C_Encrypt)( - session.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!(session.client(), C_Encrypt)( - session.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) } diff --git a/cryptoki/src/session/key_management.rs b/cryptoki/src/session/key_management.rs index 8893fb7b..7755e205 100644 --- a/cryptoki/src/session/key_management.rs +++ b/cryptoki/src/session/key_management.rs @@ -9,154 +9,151 @@ use crate::session::Session; use cryptoki_sys::{CK_ATTRIBUTE, CK_MECHANISM, CK_MECHANISM_PTR}; use std::convert::TryInto; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn generate_key( - session: &Session, - 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!(session.client(), C_GenerateKey)( - session.handle(), - &mut mechanism as CK_MECHANISM_PTR, - template.as_mut_ptr(), - template.len().try_into()?, - &mut handle, - )) - .into_result()?; +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)) } - 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()?; + } -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn generate_key_pair( - session: &Session, - 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!(session.client(), C_GenerateKeyPair)( - session.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, + Ok(( + ObjectHandle::new(pub_handle), + ObjectHandle::new(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()?; + } -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn derive_key( - session: &Session, - 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!(session.client(), C_DeriveKey)( - session.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)) } - 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; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn wrap_key( - session: &Session, - 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()?; - Rv::from(get_pkcs11!(session.client(), C_WrapKey)( - session.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()?]; - 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()?; - Rv::from(get_pkcs11!(session.client(), C_WrapKey)( - session.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) + Ok(wrapped_key) + } } -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn unwrap_key( - session: &Session, - 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!(session.client(), C_UnwrapKey)( - session.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()?; - } + /// 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)) + Ok(ObjectHandle::new(handle)) + } } diff --git a/cryptoki/src/session/mod.rs b/cryptoki/src/session/mod.rs index 245c461e..c9921716 100644 --- a/cryptoki/src/session/mod.rs +++ b/cryptoki/src/session/mod.rs @@ -3,13 +3,8 @@ //! Session types use crate::context::Pkcs11; -use crate::error::Result; -use crate::mechanism::Mechanism; -use crate::object::{Attribute, AttributeInfo, AttributeType, ObjectHandle}; use cryptoki_sys::*; -use log::error; -use std::collections::HashMap; use std::fmt::Formatter; use std::marker::PhantomData; @@ -72,278 +67,10 @@ impl Session { } impl Session { - /// Initialize the normal user's pin for a token - pub fn init_pin(&self, pin: &str) -> Result<()> { - slot_token_management::init_pin(self, pin) - } - - /// 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: &str, new_pin: &str) -> Result<()> { - slot_token_management::set_pin(self, old_pin, new_pin) - } - /// Close a session /// This will be called on drop as well. pub fn close(self) {} - /// 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<&str>) -> Result<()> { - session_management::login(self, user_type, pin) - } - - /// 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: &[u8]) -> Result<()> { - session_management::login_with_raw(self, user_type, pin) - } - - /// Log a session out - pub fn logout(&self) -> Result<()> { - session_management::logout(self) - } - - /// Returns the information about a session - pub fn get_session_info(&self) -> Result { - session_management::get_session_info(self) - } - - /// Search for session objects matching a template - pub fn find_objects(&self, template: &[Attribute]) -> Result> { - object_management::find_objects(self, template) - } - - /// Create a new object - pub fn create_object(&self, template: &[Attribute]) -> Result { - object_management::create_object(self, template) - } - - /// Destroy an object - pub fn destroy_object(&self, object: ObjectHandle) -> Result<()> { - object_management::destroy_object(self, object) - } - - /// 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 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("fedcba")); - /// - /// 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> { - object_management::get_attribute_info(self, object, attributes) - } - - /// 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> { - object_management::get_attribute_info_map(self, object, attributes) - } - - /// 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> { - object_management::get_attributes(self, object, attributes) - } - - /// Single-part encryption operation - pub fn encrypt( - &self, - mechanism: &Mechanism, - key: ObjectHandle, - data: &[u8], - ) -> Result> { - encryption::encrypt(self, mechanism, key, data) - } - - /// Single-part decryption operation - pub fn decrypt( - &self, - mechanism: &Mechanism, - key: ObjectHandle, - encrypted_data: &[u8], - ) -> Result> { - decryption::decrypt(self, mechanism, key, encrypted_data) - } - - /// Sign data in single-part - pub fn sign(&self, mechanism: &Mechanism, key: ObjectHandle, data: &[u8]) -> Result> { - signing_macing::sign(self, mechanism, key, data) - } - - /// Verify data in single-part - pub fn verify( - &self, - mechanism: &Mechanism, - key: ObjectHandle, - data: &[u8], - signature: &[u8], - ) -> Result<()> { - signing_macing::verify(self, mechanism, key, data, signature) - } - - /// Generate a secret key - pub fn generate_key( - &self, - mechanism: &Mechanism, - template: &[Attribute], - ) -> Result { - key_management::generate_key(self, mechanism, template) - } - - /// 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)> { - key_management::generate_key_pair(self, mechanism, pub_key_template, priv_key_template) - } - - /// Derives a key from a base key - pub fn derive_key( - &self, - mechanism: &Mechanism, - base_key: ObjectHandle, - template: &[Attribute], - ) -> Result { - key_management::derive_key(self, mechanism, base_key, template) - } - - /// Wrap key - pub fn wrap_key( - &self, - mechanism: &Mechanism, - wrapping_key: ObjectHandle, - key: ObjectHandle, - ) -> Result> { - key_management::wrap_key(self, mechanism, wrapping_key, key) - } - - /// Unwrap previously wrapped key - pub fn unwrap_key( - &self, - mechanism: &Mechanism, - unwrapping_key: ObjectHandle, - wrapped_key: &[u8], - template: &[Attribute], - ) -> Result { - key_management::unwrap_key(self, mechanism, unwrapping_key, wrapped_key, template) - } - - /// 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<()> { - random::generate_random_slice(self, random_data) - } - - /// 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> { - random::generate_random_vec(self, random_len) - } - - /// Seeds the RNG - pub fn seed_random(&self, seed: &[u8]) -> Result<()> { - random::seed_random(self, seed) - } - pub(crate) fn handle(&self) -> CK_SESSION_HANDLE { self.handle } @@ -353,14 +80,6 @@ impl Session { } } -impl Drop for Session { - fn drop(&mut self) { - if let Err(e) = session_management::close_private(self) { - error!("Failed to close session: {}", e); - } - } -} - /// Types of PKCS11 users #[derive(Copy, Clone, Debug)] pub enum UserType { diff --git a/cryptoki/src/session/object_management.rs b/cryptoki/src/session/object_management.rs index 65f77d72..2b1cc7a2 100644 --- a/cryptoki/src/session/object_management.rs +++ b/cryptoki/src/session/object_management.rs @@ -12,190 +12,257 @@ use std::convert::TryInto; // Search 10 elements at a time const MAX_OBJECT_COUNT: usize = 10; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn find_objects(session: &Session, template: &[Attribute]) -> Result> { - let mut template: Vec = template.iter().map(|attr| attr.into()).collect(); - - unsafe { - Rv::from(get_pkcs11!(session.client(), C_FindObjectsInit)( - session.handle(), - template.as_mut_ptr(), - template.len().try_into()?, - )) - .into_result()?; - } +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(); - let mut object_handles = [0; MAX_OBJECT_COUNT]; - let mut object_count = 0; - let mut objects = Vec::new(); - - unsafe { - Rv::from(get_pkcs11!(session.client(), C_FindObjects)( - session.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_FindObjectsInit)( + self.handle(), + template.as_mut_ptr(), + template.len().try_into()?, + )) + .into_result()?; + } - while object_count > 0 { - objects.extend_from_slice(&object_handles[..object_count.try_into()?]); + let mut object_handles = [0; MAX_OBJECT_COUNT]; + let mut object_count = 0; + let mut objects = Vec::new(); unsafe { - Rv::from(get_pkcs11!(session.client(), C_FindObjects)( - session.handle(), + 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!(session.client(), C_FindObjectsFinal)( - session.handle(), - )) - .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()?; + } + } - let objects = objects.into_iter().map(ObjectHandle::new).collect(); + unsafe { + Rv::from(get_pkcs11!(self.client(), C_FindObjectsFinal)( + self.handle(), + )) + .into_result()?; + } - Ok(objects) -} + let objects = objects.into_iter().map(ObjectHandle::new).collect(); -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn create_object(session: &Session, template: &[Attribute]) -> Result { - let mut template: Vec = template.iter().map(|attr| attr.into()).collect(); - let mut object_handle = 0; - - unsafe { - Rv::from(get_pkcs11!(session.client(), C_CreateObject)( - session.handle(), - template.as_mut_ptr(), - template.len().try_into()?, - &mut object_handle as CK_OBJECT_HANDLE_PTR, - )) - .into_result()?; + Ok(objects) } - Ok(ObjectHandle::new(object_handle)) -} + /// 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; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn destroy_object(session: &Session, object: ObjectHandle) -> Result<()> { - unsafe { - Rv::from(get_pkcs11!(session.client(), C_DestroyObject)( - session.handle(), - object.handle(), - )) - .into_result() + 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)) } -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_attribute_info( - session: &Session, - 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!(session.client(), C_GetAttributeValue)( - session.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(), - 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()?, + .into_result() } } - Ok(results) -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_attribute_info_map( - session: &Session, - object: ObjectHandle, - attributes: Vec, -) -> Result> { - let attrib_info = session.get_attribute_info(object, attributes.as_slice())?; - - Ok(attributes - .iter() - .cloned() - .zip(attrib_info.iter().cloned()) - .collect::>()) -} + /// 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 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("fedcba")); + /// + /// 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(); -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_attributes( - session: &Session, - object: ObjectHandle, - attributes: &[AttributeType], -) -> Result> { - let attrs_info = session.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 + 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()?, } - }) - .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!(session.client(), C_GetAttributeValue)( - session.handle(), - object.handle(), - template.as_mut_ptr(), - template.len().try_into()?, - )) - .into_result()?; + } + Ok(results) } - // Convert from CK_ATTRIBUTE to Attribute - template.into_iter().map(|attr| attr.try_into()).collect() -} + /// 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() + } -impl Session { /// 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(); diff --git a/cryptoki/src/session/random.rs b/cryptoki/src/session/random.rs index f95d3cc1..8093e021 100644 --- a/cryptoki/src/session/random.rs +++ b/cryptoki/src/session/random.rs @@ -6,45 +6,50 @@ use crate::error::{Result, Rv}; use crate::session::Session; use std::convert::TryInto; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn generate_random_slice(session: &Session, random_data: &mut [u8]) -> Result<()> { - unsafe { - Rv::from(get_pkcs11!(session.client(), C_GenerateRandom)( - session.handle(), - random_data.as_ptr() as *mut u8, - random_data.len().try_into()?, - )) - .into_result()?; +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(()) } - Ok(()) -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn generate_random_vec(session: &Session, random_len: u32) -> Result> { - let mut result: Vec = vec![0; random_len as usize]; - unsafe { - Rv::from(get_pkcs11!(session.client(), C_GenerateRandom)( - session.handle(), - result.as_mut_ptr() as *mut u8, - random_len.try_into()?, - )) - .into_result()?; + /// 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() as *mut u8, + random_len.try_into()?, + )) + .into_result()?; + } + Ok(result) } - Ok(result) -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn seed_random(session: &Session, seed: &[u8]) -> Result<()> { - unsafe { - Rv::from(get_pkcs11!(session.client(), C_SeedRandom)( - session.handle(), - seed.as_ptr() as *mut u8, - seed.len().try_into()?, - )) - .into_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(()) } - Ok(()) } diff --git a/cryptoki/src/session/session_management.rs b/cryptoki/src/session/session_management.rs index 6d1873b3..fc539c7d 100644 --- a/cryptoki/src/session/session_management.rs +++ b/cryptoki/src/session/session_management.rs @@ -4,68 +4,96 @@ use crate::error::{Result, Rv}; use crate::session::{Session, SessionInfo, UserType}; + +#[cfg(doc)] +use cryptoki_sys::CKF_PROTECTED_AUTHENTICATION_PATH; use cryptoki_sys::CK_SESSION_INFO; +use log::error; use std::convert::{TryFrom, TryInto}; -// See public docs on close() in parent mod.rs -#[inline(always)] -pub(super) fn close_private(session: &Session) -> Result<()> { - unsafe { - Rv::from(get_pkcs11!(session.client(), C_CloseSession)( - session.handle(), - )) - .into_result() +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); + } } } -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn login(session: &Session, user_type: UserType, pin: Option<&str>) -> Result<()> { - let (pin, pin_len) = match pin { - Some(pin) => (pin.as_ptr() as *mut u8, pin.len()), - None => (std::ptr::null_mut(), 0), - }; - unsafe { - Rv::from(get_pkcs11!(session.client(), C_Login)( - session.handle(), - user_type.into(), - pin, - pin_len.try_into()?, - )) - .into_result() +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<&str>) -> Result<()> { + let (pin, pin_len) = match pin { + Some(pin) => (pin.as_ptr() as *mut u8, pin.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() + } } -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn login_with_raw(session: &Session, user_type: UserType, pin: &[u8]) -> Result<()> { - unsafe { - Rv::from(get_pkcs11!(session.client(), C_Login)( - session.handle(), - user_type.into(), - pin.as_ptr() as *mut u8, - 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: &[u8]) -> Result<()> { + unsafe { + Rv::from(get_pkcs11!(self.client(), C_Login)( + self.handle(), + user_type.into(), + pin.as_ptr() as *mut u8, + pin.len().try_into()?, + )) + .into_result() + } } -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn logout(session: &Session) -> Result<()> { - unsafe { Rv::from(get_pkcs11!(session.client(), C_Logout)(session.handle())).into_result() } -} + /// Log a session out + pub fn logout(&self) -> Result<()> { + unsafe { Rv::from(get_pkcs11!(self.client(), C_Logout)(self.handle())).into_result() } + } -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn get_session_info(session: &Session) -> Result { - let mut session_info = CK_SESSION_INFO::default(); - unsafe { - Rv::from(get_pkcs11!(session.client(), C_GetSessionInfo)( - session.handle(), - &mut session_info, - )) - .into_result()?; - SessionInfo::try_from(session_info) + /// 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) + } } } diff --git a/cryptoki/src/session/signing_macing.rs b/cryptoki/src/session/signing_macing.rs index 34eff3d4..d100c72b 100644 --- a/cryptoki/src/session/signing_macing.rs +++ b/cryptoki/src/session/signing_macing.rs @@ -9,85 +9,80 @@ use crate::session::Session; use cryptoki_sys::*; use std::convert::TryInto; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn sign( - session: &Session, - mechanism: &Mechanism, - key: ObjectHandle, - data: &[u8], -) -> Result> { - let mut mechanism: CK_MECHANISM = mechanism.into(); - let mut signature_len = 0; +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!(session.client(), C_SignInit)( - session.handle(), - &mut mechanism as CK_MECHANISM_PTR, - key.handle(), - )) - .into_result()?; - } + 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!(session.client(), C_Sign)( - session.handle(), - data.as_ptr() as *mut u8, - data.len().try_into()?, - std::ptr::null_mut(), - &mut signature_len, - )) - .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()?]; + 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!(session.client(), C_Sign)( - session.handle(), - data.as_ptr() as *mut u8, - data.len().try_into()?, - signature.as_mut_ptr(), - &mut signature_len, - )) - .into_result()?; - } + //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); + signature.resize(signature_len.try_into()?, 0); - Ok(signature) -} + Ok(signature) + } -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn verify( - session: &Session, - mechanism: &Mechanism, - key: ObjectHandle, - data: &[u8], - signature: &[u8], -) -> Result<()> { - let mut mechanism: CK_MECHANISM = mechanism.into(); + /// 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!(session.client(), C_VerifyInit)( - session.handle(), - &mut mechanism as CK_MECHANISM_PTR, - key.handle(), - )) - .into_result()?; - } + 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!(session.client(), C_Verify)( - session.handle(), - data.as_ptr() as *mut u8, - data.len().try_into()?, - signature.as_ptr() as *mut u8, - signature.len().try_into()?, - )) - .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() + } } } diff --git a/cryptoki/src/session/slot_token_management.rs b/cryptoki/src/session/slot_token_management.rs index c6f92dc7..02bb133c 100644 --- a/cryptoki/src/session/slot_token_management.rs +++ b/cryptoki/src/session/slot_token_management.rs @@ -6,30 +6,31 @@ use crate::error::{Result, Rv}; use crate::session::Session; use std::convert::TryInto; -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn init_pin(session: &Session, pin: &str) -> Result<()> { - unsafe { - Rv::from(get_pkcs11!(session.client(), C_InitPIN)( - session.handle(), - pin.as_ptr() as *mut u8, - pin.len().try_into()?, - )) - .into_result() +impl Session { + /// Initialize the normal user's pin for a token + pub fn init_pin(&self, pin: &str) -> Result<()> { + unsafe { + Rv::from(get_pkcs11!(self.client(), C_InitPIN)( + self.handle(), + pin.as_ptr() as *mut u8, + pin.len().try_into()?, + )) + .into_result() + } } -} -// See public docs on stub in parent mod.rs -#[inline(always)] -pub(super) fn set_pin(session: &Session, old_pin: &str, new_pin: &str) -> Result<()> { - unsafe { - Rv::from(get_pkcs11!(session.client(), C_SetPIN)( - session.handle(), - old_pin.as_ptr() as *mut u8, - old_pin.len().try_into()?, - new_pin.as_ptr() as *mut u8, - new_pin.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: &str, new_pin: &str) -> Result<()> { + unsafe { + Rv::from(get_pkcs11!(self.client(), C_SetPIN)( + self.handle(), + old_pin.as_ptr() as *mut u8, + old_pin.len().try_into()?, + new_pin.as_ptr() as *mut u8, + new_pin.len().try_into()?, + )) + .into_result() + } } }