-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #56 from vkkoskie/module-tree-hygiene
Module tree hygiene
- Loading branch information
Showing
45 changed files
with
3,102 additions
and
2,773 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright 2021 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
//! PKCS11 flags for use with CInitializeArgs | ||
|
||
use crate::error::{Error, Result}; | ||
use crate::types::Flags; | ||
use cryptoki_sys::*; | ||
use std::convert::TryFrom; | ||
use std::fmt::Formatter; | ||
|
||
#[derive(Debug, Default, Clone, Copy)] | ||
/// Collection of flags defined for [`CK_C_INITIALIZE_ARGS`] | ||
pub struct InitializeFlags { | ||
flags: CK_FLAGS, | ||
} | ||
|
||
impl Flags for InitializeFlags { | ||
type FlagType = CK_FLAGS; | ||
|
||
fn flag_value(&self) -> Self::FlagType { | ||
self.flags | ||
} | ||
|
||
fn flag(&self, flag: Self::FlagType) -> bool { | ||
self.flag_value() & flag == flag | ||
} | ||
|
||
fn set_flag(&mut self, flag: Self::FlagType, b: bool) { | ||
if b { | ||
self.flags |= flag; | ||
} else { | ||
self.flags &= !flag; | ||
} | ||
} | ||
|
||
fn stringify_flag(flag: CK_FLAGS) -> &'static str { | ||
match flag { | ||
CKF_LIBRARY_CANT_CREATE_OS_THREADS => { | ||
std::stringify!(CKF_LIBRARY_CANT_CREATE_OS_THREADS) | ||
} | ||
CKF_OS_LOCKING_OK => std::stringify!(CKF_OS_LOCKING_OK), | ||
_ => "Unknown CK_C_INITIALIZE_ARGS flag", | ||
} | ||
} | ||
} | ||
|
||
impl InitializeFlags { | ||
/// Creates a new instance of `InitializeFlags` with no flags set | ||
pub fn new() -> Self { | ||
InitializeFlags::default() | ||
} | ||
|
||
/// Gets value of [`CKF_LIBRARY_CANT_CREATE_OS_THREADS`] | ||
pub fn library_cant_create_os_threads(&self) -> bool { | ||
self.flag(CKF_LIBRARY_CANT_CREATE_OS_THREADS) | ||
} | ||
|
||
/// Sets value of [`CKF_LIBRARY_CANT_CREATE_OS_THREADS`] | ||
pub fn set_library_cant_create_os_threads(&mut self, b: bool) -> &mut Self { | ||
self.set_flag(CKF_LIBRARY_CANT_CREATE_OS_THREADS, b); | ||
self | ||
} | ||
|
||
/// Gets value of [`CKF_OS_LOCKING_OK`] | ||
pub fn os_locking_ok(&self) -> bool { | ||
self.flag(CKF_OS_LOCKING_OK) | ||
} | ||
|
||
/// Sets value of [`CKF_OS_LOCKING_OK`] | ||
pub fn set_os_locking_ok(&mut self, b: bool) -> &mut Self { | ||
self.set_flag(CKF_OS_LOCKING_OK, b); | ||
self | ||
} | ||
} | ||
|
||
impl std::fmt::Display for InitializeFlags { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
let flags = vec![CKF_LIBRARY_CANT_CREATE_OS_THREADS, CKF_OS_LOCKING_OK]; | ||
self.stringify_fmt(f, flags) | ||
} | ||
} | ||
|
||
impl From<InitializeFlags> for CK_FLAGS { | ||
fn from(flags: InitializeFlags) -> Self { | ||
flags.flags | ||
} | ||
} | ||
|
||
impl TryFrom<CK_FLAGS> for InitializeFlags { | ||
type Error = Error; | ||
|
||
fn try_from(flags: CK_FLAGS) -> Result<Self> { | ||
if flags & !(CKF_OS_LOCKING_OK | CKF_LIBRARY_CANT_CREATE_OS_THREADS) != 0 { | ||
Err(Error::InvalidValue) | ||
} else { | ||
Ok(Self { flags }) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Copyright 2021 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
//! General-purpose functions | ||
|
||
use crate::context::{CInitializeArgs, Info, Pkcs11}; | ||
use crate::error::{Result, Rv}; | ||
use cryptoki_sys::{CK_C_INITIALIZE_ARGS, CK_INFO}; | ||
use std::ptr; | ||
|
||
// See public docs on stub in parent mod.rs | ||
#[inline(always)] | ||
pub(super) fn initialize(ctx: &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; | ||
unsafe { | ||
Rv::from(get_pkcs11!(ctx, C_Initialize)( | ||
init_args_ptr as *mut CK_C_INITIALIZE_ARGS as *mut ::std::ffi::c_void, | ||
)) | ||
.into_result() | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
pub(super) fn finalize_private(ctx: &Pkcs11) -> Result<()> { | ||
// Safe because Session contain a reference to self so that this function can not be called | ||
// while there are live Session instances. | ||
unsafe { Rv::from(get_pkcs11!(ctx, C_Finalize)(ptr::null_mut())).into_result() } | ||
} | ||
|
||
// See public docs on stub in parent mod.rs | ||
#[inline(always)] | ||
pub(super) fn get_library_info(ctx: &Pkcs11) -> Result<Info> { | ||
let mut info = CK_INFO::default(); | ||
unsafe { | ||
Rv::from(get_pkcs11!(ctx, C_GetInfo)(&mut info)).into_result()?; | ||
Ok(Info::new(info)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright 2021 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
//! PKCS11 library information | ||
|
||
use crate::string_from_blank_padded; | ||
use crate::types::Version; | ||
use cryptoki_sys::*; | ||
use std::ops::Deref; | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
/// Type identifying the PKCS#11 library information | ||
pub struct Info { | ||
val: CK_INFO, | ||
} | ||
|
||
impl Info { | ||
pub(crate) fn new(val: CK_INFO) -> Self { | ||
Self { val } | ||
} | ||
|
||
/// Returns the version of Cryptoki that the library is compatible with | ||
pub fn cryptoki_version(&self) -> Version { | ||
self.val.cryptokiVersion.into() | ||
} | ||
|
||
/// Returns the flags of the library (should be zero!) | ||
pub fn flags(&self) -> CK_FLAGS { | ||
self.val.flags | ||
} | ||
|
||
/// Returns the description of the library | ||
pub fn library_description(&self) -> String { | ||
string_from_blank_padded(&self.val.libraryDescription) | ||
} | ||
|
||
/// Returns the version of the library | ||
pub fn library_version(&self) -> Version { | ||
self.val.libraryVersion.into() | ||
} | ||
|
||
/// Returns the manufacturer of the library | ||
pub fn manufacturer_id(&self) -> String { | ||
string_from_blank_padded(&self.val.manufacturerID) | ||
} | ||
} | ||
|
||
impl Deref for Info { | ||
type Target = CK_INFO; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.val | ||
} | ||
} | ||
|
||
impl From<Info> for CK_INFO { | ||
fn from(info: Info) -> Self { | ||
*info | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
// Copyright 2021 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
//! Pkcs11 context and initialization types | ||
|
||
/// Directly get the PKCS #11 operation from the context structure and check for null pointers. | ||
macro_rules! get_pkcs11 { | ||
($pkcs11:expr, $func_name:ident) => { | ||
($pkcs11 | ||
.function_list | ||
.$func_name | ||
.ok_or(crate::error::Error::NullFunctionPointer)?) | ||
}; | ||
} | ||
|
||
mod flags; | ||
mod general_purpose; | ||
mod info; | ||
mod locking; | ||
mod session_management; | ||
mod slot_token_management; | ||
|
||
pub use flags::*; | ||
pub use info::*; | ||
pub use locking::*; | ||
|
||
use crate::error::{Error, Result, Rv}; | ||
use crate::mechanism::{MechanismInfo, MechanismType}; | ||
use crate::session::{Session, SessionFlags}; | ||
use crate::slot::{Slot, SlotInfo, TokenInfo}; | ||
|
||
use derivative::Derivative; | ||
use log::error; | ||
use std::mem; | ||
use std::path::Path; | ||
|
||
/// Main PKCS11 context. Should usually be unique per application. | ||
#[derive(Derivative)] | ||
#[derivative(Debug)] | ||
pub struct Pkcs11 { | ||
// Even if this field is never read, it is needed for the pointers in function_list to remain | ||
// valid. | ||
#[derivative(Debug = "ignore")] | ||
_pkcs11_lib: cryptoki_sys::Pkcs11, | ||
pub(crate) function_list: cryptoki_sys::_CK_FUNCTION_LIST, | ||
} | ||
|
||
impl Pkcs11 { | ||
/// Instantiate a new context from the path of a PKCS11 dynamic llibrary implementation. | ||
pub fn new<P>(filename: P) -> Result<Self> | ||
where | ||
P: AsRef<Path>, | ||
{ | ||
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 { | ||
_pkcs11_lib: pkcs11_lib, | ||
function_list: *list_ptr, | ||
}) | ||
} | ||
} | ||
|
||
/// Initialize the PKCS11 library | ||
pub fn initialize(&self, init_args: CInitializeArgs) -> Result<()> { | ||
general_purpose::initialize(self, init_args) | ||
} | ||
|
||
/// 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<Info> { | ||
general_purpose::get_library_info(self) | ||
} | ||
|
||
/// Get all slots available with a token | ||
pub fn get_slots_with_token(&self) -> Result<Vec<Slot>> { | ||
slot_token_management::get_slots_with_token(self) | ||
} | ||
|
||
/// Get all slots available with a token | ||
pub fn get_slots_with_initialized_token(&self) -> Result<Vec<Slot>> { | ||
slot_token_management::get_slots_with_initialized_token(self) | ||
} | ||
|
||
/// Get all slots | ||
pub fn get_all_slots(&self) -> Result<Vec<Slot>> { | ||
slot_token_management::get_all_slots(self) | ||
} | ||
|
||
/// 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<SlotInfo> { | ||
slot_token_management::get_slot_info(self, slot) | ||
} | ||
|
||
/// Returns information about a specific token | ||
pub fn get_token_info(&self, slot: Slot) -> Result<TokenInfo> { | ||
slot_token_management::get_token_info(self, slot) | ||
} | ||
|
||
/// Get all mechanisms support by a slot | ||
pub fn get_mechanism_list(&self, slot: Slot) -> Result<Vec<MechanismType>> { | ||
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<MechanismInfo> { | ||
slot_token_management::get_mechanism_info(self, slot, type_) | ||
} | ||
|
||
/// Open a new session with no callback set | ||
pub fn open_session_no_callback(&self, slot_id: Slot, flags: SessionFlags) -> Result<Session> { | ||
session_management::open_session_no_callback(self, slot_id, flags) | ||
} | ||
} | ||
|
||
impl Drop for Pkcs11 { | ||
fn drop(&mut self) { | ||
if let Err(e) = general_purpose::finalize_private(self) { | ||
error!("Failed to finalize: {}", e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright 2021 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
//! Session management functions | ||
|
||
use crate::context::Pkcs11; | ||
use crate::error::{Result, Rv}; | ||
use crate::session::{Session, SessionFlags}; | ||
use crate::slot::Slot; | ||
use std::convert::TryInto; | ||
|
||
// See public docs on stub in parent mod.rs | ||
#[inline(always)] | ||
pub(super) fn open_session_no_callback( | ||
ctx: &Pkcs11, | ||
slot_id: Slot, | ||
flags: SessionFlags, | ||
) -> Result<Session> { | ||
let mut session_handle = 0; | ||
|
||
unsafe { | ||
Rv::from(get_pkcs11!(ctx, C_OpenSession)( | ||
slot_id.try_into()?, | ||
flags.into(), | ||
// 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, ctx)) | ||
} |
Oops, something went wrong.