use crate::context::Pkcs11;
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 std::convert::{TryFrom, TryInto};
use crate::error::RvError::BufferTooSmall;
#[inline(always)]
pub(super) fn get_slots(ctx: &Pkcs11, with_token: CK_BBOOL) -> Result<Vec<Slot>> {
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];
let rval = unsafe {
get_pkcs11!(ctx, C_GetSlotList)(with_token, slots.as_mut_ptr(), &mut slot_count)
};
if !matches!(Rv::from(rval), Rv::Error(BufferTooSmall)) {
Rv::from(rval).into_result()?;
break;
}
}
slots.truncate(slot_count as usize);
Ok(slots.into_iter().map(Slot::new).collect())
}
#[inline(always)]
pub(super) fn get_slots_with_initialized_token(ctx: &Pkcs11) -> Result<Vec<Slot>> {
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()
}
#[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()
}
}
#[inline(always)]
pub(super) fn get_slot_info(ctx: &Pkcs11, slot: Slot) -> Result<SlotInfo> {
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))
}
}
#[inline(always)]
pub(super) fn get_token_info(ctx: &Pkcs11, slot: Slot) -> Result<TokenInfo> {
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)
}
}
#[inline(always)]
pub(super) fn get_mechanism_list(ctx: &Pkcs11, slot: Slot) -> Result<Vec<MechanismType>> {
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()?;
}
let mut mechanisms = vec![0; mechanism_count.try_into()?];
unsafe {
Rv::from(get_pkcs11!(ctx, C_GetMechanismList)(
slot.try_into()?,
mechanisms.as_mut_ptr(),
&mut mechanism_count,
))
.into_result()?;
}
mechanisms.truncate(mechanism_count.try_into()?);
Ok(mechanisms
.into_iter()
.filter_map(|type_| type_.try_into().ok())
.collect())
}
#[inline(always)]
pub(super) fn get_mechanism_info(
ctx: &Pkcs11,
slot: Slot,
type_: MechanismType,
) -> Result<MechanismInfo> {
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))
}
}