use std::borrow::Cow;
use std::cmp::Ordering;
use crate::error::{Error, Result};
use crate::misc::{sizeof, void_ptr, zeromem};
use crate::pkcs11::vendor::{KRA_LOGIN_ATTEMPTS, KRA_MAX_LOGIN_ATTEMPTS};
use crate::pkcs11::*;
#[cfg(feature = "nssdb")]
use crate::pkcs11::vendor::nss::*;
use ossl::BorrowedReference;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum AttrType {
BoolType,
NumType,
StringType,
BytesType,
UlongArrayType,
DateType,
DenyType,
IgnoreType,
}
impl AttrType {
#[allow(dead_code)]
pub fn attr_name_to_id_type(s: &String) -> Result<(CK_ULONG, AttrType)> {
match Attrmap::search_by_name(s) {
Some(a) => Ok((a.id, a.atype)),
None => Err(Error::not_found(s.clone())),
}
}
pub fn attr_id_to_attrtype(id: CK_ULONG) -> Result<AttrType> {
match Attrmap::search_by_id(id) {
Some(a) => Ok(a.atype),
None => Err(CKR_ATTRIBUTE_TYPE_INVALID)?,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct Attrmap<'a> {
id: CK_ULONG,
name: &'a str,
atype: AttrType,
}
impl PartialOrd for Attrmap<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Attrmap<'_> {
fn cmp(&self, other: &Self) -> Ordering {
if self.id < other.id {
return Ordering::Less;
}
if self.id > other.id {
return Ordering::Greater;
}
Ordering::Equal
}
}
impl Attrmap<'_> {
pub fn search_by_id(id: CK_ULONG) -> Option<&'static Attrmap<'static>> {
match &ATTRMAP.binary_search(&Attrmap {
id: id,
name: "",
atype: AttrType::StringType,
}) {
Ok(i) => Some(&ATTRMAP[*i]),
Err(_) => None,
}
}
pub fn search_by_name(s: &String) -> Option<&'static Attrmap<'static>> {
for a in ATTRMAP {
if a.name == s {
return Some(a);
}
}
None
}
}
macro_rules! attrmap_element {
($id:expr; as $attrtype:ident) => {
Attrmap {
id: $id,
name: stringify!($id),
atype: AttrType::$attrtype,
}
};
}
static ATTRMAP: &[Attrmap<'_>] = &[
attrmap_element!(CKA_CLASS; as NumType),
attrmap_element!(CKA_TOKEN; as BoolType),
attrmap_element!(CKA_PRIVATE; as BoolType),
attrmap_element!(CKA_LABEL; as StringType),
attrmap_element!(CKA_UNIQUE_ID; as StringType),
attrmap_element!(CKA_APPLICATION; as StringType),
attrmap_element!(CKA_VALUE; as BytesType),
attrmap_element!(CKA_OBJECT_ID; as BytesType),
attrmap_element!(CKA_CERTIFICATE_TYPE; as NumType),
attrmap_element!(CKA_ISSUER; as BytesType),
attrmap_element!(CKA_SERIAL_NUMBER; as BytesType),
attrmap_element!(CKA_AC_ISSUER; as BytesType),
attrmap_element!(CKA_OWNER; as BytesType),
attrmap_element!(CKA_ATTR_TYPES; as BytesType),
attrmap_element!(CKA_TRUSTED; as BoolType),
attrmap_element!(CKA_CERTIFICATE_CATEGORY; as NumType),
attrmap_element!(CKA_JAVA_MIDP_SECURITY_DOMAIN; as NumType),
attrmap_element!(CKA_URL; as StringType),
attrmap_element!(CKA_HASH_OF_SUBJECT_PUBLIC_KEY; as BytesType),
attrmap_element!(CKA_HASH_OF_ISSUER_PUBLIC_KEY; as BytesType),
attrmap_element!(CKA_NAME_HASH_ALGORITHM; as NumType),
attrmap_element!(CKA_CHECK_VALUE; as IgnoreType),
attrmap_element!(CKA_KEY_TYPE; as NumType),
attrmap_element!(CKA_SUBJECT; as BytesType),
attrmap_element!(CKA_ID; as BytesType),
attrmap_element!(CKA_SENSITIVE; as BoolType),
attrmap_element!(CKA_ENCRYPT; as BoolType),
attrmap_element!(CKA_DECRYPT; as BoolType),
attrmap_element!(CKA_WRAP; as BoolType),
attrmap_element!(CKA_UNWRAP; as BoolType),
attrmap_element!(CKA_SIGN; as BoolType),
attrmap_element!(CKA_SIGN_RECOVER; as BoolType),
attrmap_element!(CKA_VERIFY; as BoolType),
attrmap_element!(CKA_VERIFY_RECOVER; as BoolType),
attrmap_element!(CKA_DERIVE; as BoolType),
attrmap_element!(CKA_START_DATE; as DateType),
attrmap_element!(CKA_END_DATE; as DateType),
attrmap_element!(CKA_MODULUS; as BytesType),
attrmap_element!(CKA_MODULUS_BITS; as NumType),
attrmap_element!(CKA_PUBLIC_EXPONENT; as BytesType),
attrmap_element!(CKA_PRIVATE_EXPONENT; as BytesType),
attrmap_element!(CKA_PRIME_1; as BytesType),
attrmap_element!(CKA_PRIME_2; as BytesType),
attrmap_element!(CKA_EXPONENT_1; as BytesType),
attrmap_element!(CKA_EXPONENT_2; as BytesType),
attrmap_element!(CKA_COEFFICIENT; as BytesType),
attrmap_element!(CKA_PUBLIC_KEY_INFO; as BytesType),
attrmap_element!(CKA_PRIME; as BytesType),
attrmap_element!(CKA_SUBPRIME; as BytesType),
attrmap_element!(CKA_BASE; as BytesType),
attrmap_element!(CKA_PRIME_BITS; as BytesType),
attrmap_element!(CKA_SUBPRIME_BITS; as NumType),
attrmap_element!(CKA_VALUE_BITS; as NumType),
attrmap_element!(CKA_VALUE_LEN; as NumType),
attrmap_element!(CKA_EXTRACTABLE; as BoolType),
attrmap_element!(CKA_LOCAL; as BoolType),
attrmap_element!(CKA_NEVER_EXTRACTABLE; as BoolType),
attrmap_element!(CKA_ALWAYS_SENSITIVE; as BoolType),
attrmap_element!(CKA_KEY_GEN_MECHANISM; as NumType),
attrmap_element!(CKA_MODIFIABLE; as BoolType),
attrmap_element!(CKA_COPYABLE; as BoolType),
attrmap_element!(CKA_DESTROYABLE; as BoolType),
attrmap_element!(CKA_EC_PARAMS; as BytesType),
attrmap_element!(CKA_EC_POINT; as BytesType),
attrmap_element!(CKA_ALWAYS_AUTHENTICATE; as BoolType),
attrmap_element!(CKA_WRAP_WITH_TRUSTED; as BoolType),
attrmap_element!(CKA_OTP_FORMAT; as NumType),
attrmap_element!(CKA_OTP_LENGTH; as NumType),
attrmap_element!(CKA_OTP_TIME_INTERVAL; as NumType),
attrmap_element!(CKA_OTP_USER_FRIENDLY_MODE; as BoolType),
attrmap_element!(CKA_OTP_CHALLENGE_REQUIREMENT; as NumType),
attrmap_element!(CKA_OTP_TIME_REQUIREMENT; as NumType),
attrmap_element!(CKA_OTP_COUNTER_REQUIREMENT; as NumType),
attrmap_element!(CKA_OTP_PIN_REQUIREMENT; as NumType),
attrmap_element!(CKA_OTP_USER_IDENTIFIER; as StringType),
attrmap_element!(CKA_OTP_SERVICE_IDENTIFIER; as StringType),
attrmap_element!(CKA_OTP_SERVICE_LOGO; as BytesType),
attrmap_element!(CKA_OTP_SERVICE_LOGO_TYPE; as StringType),
attrmap_element!(CKA_OTP_COUNTER; as BytesType),
attrmap_element!(CKA_OTP_TIME; as StringType),
attrmap_element!(CKA_GOSTR3410_PARAMS; as BytesType),
attrmap_element!(CKA_GOSTR3411_PARAMS; as BytesType),
attrmap_element!(CKA_GOST28147_PARAMS; as BytesType),
attrmap_element!(CKA_HW_FEATURE_TYPE; as NumType),
attrmap_element!(CKA_RESET_ON_INIT; as BoolType),
attrmap_element!(CKA_HAS_RESET; as BoolType),
attrmap_element!(CKA_PIXEL_X; as NumType),
attrmap_element!(CKA_PIXEL_Y; as NumType),
attrmap_element!(CKA_RESOLUTION; as NumType),
attrmap_element!(CKA_CHAR_ROWS; as NumType),
attrmap_element!(CKA_CHAR_COLUMNS; as NumType),
attrmap_element!(CKA_COLOR; as BoolType),
attrmap_element!(CKA_BITS_PER_PIXEL; as NumType),
attrmap_element!(CKA_CHAR_SETS; as StringType),
attrmap_element!(CKA_ENCODING_METHODS; as StringType),
attrmap_element!(CKA_MIME_TYPES; as StringType),
attrmap_element!(CKA_MECHANISM_TYPE; as NumType),
attrmap_element!(CKA_REQUIRED_CMS_ATTRIBUTES; as BytesType),
attrmap_element!(CKA_DEFAULT_CMS_ATTRIBUTES; as BytesType),
attrmap_element!(CKA_SUPPORTED_CMS_ATTRIBUTES; as BytesType),
attrmap_element!(CKA_PROFILE_ID; as NumType),
attrmap_element!(CKA_X2RATCHET_BAG; as BytesType),
attrmap_element!(CKA_X2RATCHET_BAGSIZE; as NumType),
attrmap_element!(CKA_X2RATCHET_BOBS1STMSG; as BoolType),
attrmap_element!(CKA_X2RATCHET_CKR; as BytesType),
attrmap_element!(CKA_X2RATCHET_CKS; as BytesType),
attrmap_element!(CKA_X2RATCHET_DHP; as BytesType),
attrmap_element!(CKA_X2RATCHET_DHR; as BytesType),
attrmap_element!(CKA_X2RATCHET_DHS; as BytesType),
attrmap_element!(CKA_X2RATCHET_HKR; as BytesType),
attrmap_element!(CKA_X2RATCHET_HKS; as BytesType),
attrmap_element!(CKA_X2RATCHET_ISALICE; as BoolType),
attrmap_element!(CKA_X2RATCHET_NHKR; as BytesType),
attrmap_element!(CKA_X2RATCHET_NHKS; as BytesType),
attrmap_element!(CKA_X2RATCHET_NR; as NumType),
attrmap_element!(CKA_X2RATCHET_NS; as NumType),
attrmap_element!(CKA_X2RATCHET_PNS; as NumType),
attrmap_element!(CKA_X2RATCHET_RK; as BytesType),
attrmap_element!(CKA_HSS_LEVELS; as NumType),
attrmap_element!(CKA_HSS_LMS_TYPE; as NumType),
attrmap_element!(CKA_HSS_LMOTS_TYPE; as NumType),
attrmap_element!(CKA_HSS_LMS_TYPES; as BytesType),
attrmap_element!(CKA_HSS_LMOTS_TYPES; as BytesType),
attrmap_element!(CKA_HSS_KEYS_REMAINING; as NumType),
attrmap_element!(CKA_PARAMETER_SET; as NumType),
attrmap_element!(CKA_OBJECT_VALIDATION_FLAGS; as NumType),
attrmap_element!(CKA_VALIDATION_TYPE; as NumType),
attrmap_element!(CKA_VALIDATION_VERSION; as BytesType),
attrmap_element!(CKA_VALIDATION_LEVEL; as NumType),
attrmap_element!(CKA_VALIDATION_MODULE_ID; as StringType),
attrmap_element!(CKA_VALIDATION_FLAG; as NumType),
attrmap_element!(CKA_VALIDATION_AUTHORITY_TYPE; as NumType),
attrmap_element!(CKA_VALIDATION_COUNTRY; as StringType),
attrmap_element!(CKA_VALIDATION_CERTIFICATE_IDENTIFIER; as StringType),
attrmap_element!(CKA_VALIDATION_CERTIFICATE_URI; as StringType),
attrmap_element!(CKA_VALIDATION_VENDOR_URI; as StringType),
attrmap_element!(CKA_VALIDATION_PROFILE; as StringType),
attrmap_element!(CKA_ENCAPSULATE_TEMPLATE; as DenyType),
attrmap_element!(CKA_DECAPSULATE_TEMPLATE; as DenyType),
attrmap_element!(CKA_TRUST_SERVER_AUTH; as NumType),
attrmap_element!(CKA_TRUST_CLIENT_AUTH; as NumType),
attrmap_element!(CKA_TRUST_CODE_SIGNING; as NumType),
attrmap_element!(CKA_TRUST_EMAIL_PROTECTION; as NumType),
attrmap_element!(CKA_TRUST_IPSEC_IKE; as NumType),
attrmap_element!(CKA_TRUST_TIME_STAMPING; as NumType),
attrmap_element!(CKA_TRUST_OCSP_SIGNING; as NumType),
attrmap_element!(CKA_ENCAPSULATE; as BoolType),
attrmap_element!(CKA_DECAPSULATE; as BoolType),
attrmap_element!(CKA_HASH_OF_CERTIFICATE; as BytesType),
attrmap_element!(CKA_PUBLIC_CRC64_VALUE; as BytesType),
attrmap_element!(CKA_SEED; as BytesType),
attrmap_element!(CKA_WRAP_TEMPLATE; as DenyType),
attrmap_element!(CKA_UNWRAP_TEMPLATE; as DenyType),
attrmap_element!(CKA_DERIVE_TEMPLATE; as DenyType),
attrmap_element!(CKA_ALLOWED_MECHANISMS; as UlongArrayType),
attrmap_element!(CKA_VENDOR_DEFINED; as DenyType),
attrmap_element!(KRA_MAX_LOGIN_ATTEMPTS; as NumType),
attrmap_element!(KRA_LOGIN_ATTEMPTS; as NumType),
#[cfg(feature = "nssdb")]
attrmap_element!(CKA_NSS_TRUST_SERVER_AUTH; as NumType),
#[cfg(feature = "nssdb")]
attrmap_element!(CKA_NSS_TRUST_CLIENT_AUTH; as NumType),
#[cfg(feature = "nssdb")]
attrmap_element!(CKA_NSS_TRUST_CODE_SIGNING; as NumType),
#[cfg(feature = "nssdb")]
attrmap_element!(CKA_NSS_TRUST_EMAIL_PROTECTION; as NumType),
#[cfg(feature = "nssdb")]
attrmap_element!(CKA_NSS_TRUST_STEP_UP_APPROVED; as NumType),
#[cfg(feature = "nssdb")]
attrmap_element!(CKA_NSS_CERT_SHA1_HASH; as BytesType),
#[cfg(feature = "nssdb")]
attrmap_element!(CKA_NSS_CERT_MD5_HASH; as BytesType),
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_order_of_attrmap() {
let mut copy = (*ATTRMAP).to_vec();
copy.sort();
assert_eq!(ATTRMAP, copy.as_slice());
}
}
#[derive(Debug, Clone)]
pub struct Attribute {
ck_type: CK_ULONG,
attrtype: AttrType,
value: Vec<u8>,
}
impl Attribute {
pub fn get_type(&self) -> CK_ULONG {
self.ck_type
}
pub fn get_attrtype(&self) -> AttrType {
self.attrtype
}
pub fn get_value(&self) -> &Vec<u8> {
&self.value
}
pub fn match_ck_attr(&self, attr: &CK_ATTRIBUTE) -> bool {
if self.ck_type != attr.type_ {
return false;
}
match attr.to_buf() {
Ok(buf) => buf == self.value,
Err(_) => false,
}
}
#[allow(dead_code)]
pub fn name(&self) -> String {
match Attrmap::search_by_id(self.ck_type) {
Some(a) => return a.name.to_string(),
None => return self.ck_type.to_string(),
}
}
pub fn to_bool(&self) -> Result<bool> {
if self.attrtype != AttrType::BoolType {
return Err(CKR_ATTRIBUTE_TYPE_INVALID)?;
}
if self.value.len() != 1 {
return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
}
if self.value[0] == 0 {
return Ok(false);
}
Ok(true)
}
pub fn to_ulong(&self) -> Result<CK_ULONG> {
if self.attrtype != AttrType::NumType {
return Err(CKR_ATTRIBUTE_TYPE_INVALID)?;
}
if self.value.len() != std::mem::size_of::<CK_ULONG>() {
return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
}
Ok(CK_ULONG::from_ne_bytes(
self.value.as_slice().try_into().unwrap(),
))
}
pub fn to_string(&self) -> Result<String> {
if self.attrtype != AttrType::StringType {
return Err(CKR_ATTRIBUTE_TYPE_INVALID)?;
}
match std::str::from_utf8(&self.value) {
Ok(s) => Ok(s.to_string()),
Err(_) => Err(CKR_ATTRIBUTE_VALUE_INVALID)?,
}
}
pub fn to_bytes(&self) -> Result<&Vec<u8>> {
if self.attrtype != AttrType::BytesType {
return Err(CKR_ATTRIBUTE_TYPE_INVALID)?;
}
Ok(&self.value)
}
pub fn to_ulong_array(&self) -> Result<Vec<CK_ULONG>> {
if self.attrtype != AttrType::UlongArrayType {
return Err(CKR_ATTRIBUTE_TYPE_INVALID)?;
}
let ulen = std::mem::size_of::<CK_ULONG>();
if self.value.len() % ulen != 0 {
return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
}
let vlen = self.value.len() / ulen;
let mut v = Vec::<CK_ULONG>::with_capacity(vlen);
let mut idx = 0;
while idx < self.value.len() {
let elem = &self.value[idx..(idx + ulen)];
idx += ulen;
let ulongval = CK_ULONG::from_ne_bytes(elem.try_into()?);
v.push(ulongval);
}
Ok(v)
}
pub fn to_date_string(&self) -> Result<String> {
if self.attrtype != AttrType::DateType {
return Err(CKR_ATTRIBUTE_TYPE_INVALID)?;
}
if self.value.len() == 0 {
return Ok(String::new());
}
if self.value.len() != 8 {
return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
}
let chars: [char; 10] = [
char::from(self.value[0]),
char::from(self.value[1]),
char::from(self.value[2]),
char::from(self.value[3]),
'-',
char::from(self.value[4]),
char::from(self.value[5]),
'-',
char::from(self.value[6]),
char::from(self.value[7]),
];
Ok(chars.iter().collect())
}
pub fn zeroize(&mut self) {
zeromem(self.value.as_mut_slice());
}
pub fn from_date_bytes(t: CK_ULONG, val: Vec<u8>) -> Attribute {
Attribute {
ck_type: t,
attrtype: AttrType::DateType,
value: val,
}
}
pub fn from_ignore(t: CK_ULONG, _val: Option<()>) -> Attribute {
Attribute {
ck_type: t,
attrtype: AttrType::IgnoreType,
value: Vec::new(),
}
}
#[cfg(feature = "nssdb")]
pub fn from_attr_slice(
id: CK_ULONG,
at: AttrType,
val: &[u8],
) -> Attribute {
Attribute {
ck_type: id,
attrtype: at,
value: val.to_vec(),
}
}
pub fn from_ulong_bytevec(id: CK_ULONG, val: Vec<u8>) -> Attribute {
Attribute {
ck_type: id,
attrtype: AttrType::UlongArrayType,
value: val,
}
}
pub fn from_bool(t: CK_ULONG, val: bool) -> Attribute {
Attribute {
ck_type: t,
attrtype: AttrType::BoolType,
value: Vec::from(if val { &[1u8][..] } else { &[0u8][..] }),
}
}
pub fn from_ulong(t: CK_ULONG, val: CK_ULONG) -> Attribute {
Attribute {
ck_type: t,
attrtype: AttrType::NumType,
value: Vec::from(val.to_ne_bytes()),
}
}
#[allow(dead_code)]
pub fn from_u64(t: CK_ULONG, val: u64) -> Attribute {
let inval = CK_ULONG::try_from(val).unwrap();
Self::from_ulong(t, inval)
}
pub fn from_string(t: CK_ULONG, val: String) -> Attribute {
Attribute {
ck_type: t,
attrtype: AttrType::StringType,
value: Vec::from(val.as_bytes()),
}
}
pub fn from_bytes(t: CK_ULONG, val: Vec<u8>) -> Attribute {
Attribute {
ck_type: t,
attrtype: AttrType::BytesType,
value: val,
}
}
pub fn from_ulong_array(t: CK_ULONG, val: Vec<CK_ULONG>) -> Attribute {
let ulen = std::mem::size_of::<CK_ULONG>();
let mut v = Vec::<u8>::with_capacity(val.len() * ulen);
for e in val.iter() {
for b in e.to_ne_bytes().iter() {
v.push(*b);
}
}
Attribute {
ck_type: t,
attrtype: AttrType::UlongArrayType,
value: v,
}
}
pub fn from_date(t: CK_ULONG, val: CK_DATE) -> Attribute {
let mut v = vec![0u8; 8];
v[0] = val.year[0];
v[1] = val.year[1];
v[2] = val.year[2];
v[3] = val.year[3];
v[4] = val.month[0];
v[5] = val.month[1];
v[6] = val.day[0];
v[7] = val.day[1];
Attribute {
ck_type: t,
attrtype: AttrType::DateType,
value: v,
}
}
pub fn from_ck_attr(attr: &CK_ATTRIBUTE) -> Result<Attribute> {
let atype = match Attrmap::search_by_id(attr.type_) {
Some(a) => a.atype,
None => return Err(CKR_ATTRIBUTE_TYPE_INVALID)?,
};
match atype {
AttrType::BoolType => {
Ok(Attribute::from_bool(attr.type_, attr.to_bool()?))
}
AttrType::NumType => {
Ok(Attribute::from_ulong(attr.type_, attr.to_ulong()?))
}
AttrType::StringType => {
Ok(Attribute::from_string(attr.type_, attr.to_string()?))
}
AttrType::BytesType => {
Ok(Attribute::from_bytes(attr.type_, attr.to_buf()?))
}
AttrType::UlongArrayType => {
Ok(Attribute::from_ulong_bytevec(attr.type_, attr.to_buf()?))
}
AttrType::DateType => {
Ok(Attribute::from_date(attr.type_, attr.to_date()?))
}
AttrType::DenyType => Err(CKR_ATTRIBUTE_TYPE_INVALID)?,
AttrType::IgnoreType => {
Ok(Attribute::from_ignore(attr.type_, None))
}
}
}
}
#[derive(Debug)]
pub struct RemovedAttr<'a>(CK_ATTRIBUTE, std::marker::PhantomData<&'a ()>);
impl<'a> std::ops::Deref for RemovedAttr<'a> {
type Target = CK_ATTRIBUTE;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Debug)]
pub struct CkAttrs<'a> {
v: Vec<Vec<u8>>,
p: Cow<'a, [CK_ATTRIBUTE]>,
pub zeroize: bool,
br: Vec<BorrowedReference<'a>>,
}
impl Drop for CkAttrs<'_> {
fn drop(&mut self) {
if self.zeroize {
while let Some(mut elem) = self.v.pop() {
zeromem(elem.as_mut_slice());
}
}
}
}
#[allow(dead_code)]
impl<'a> CkAttrs<'a> {
pub fn new() -> CkAttrs<'static> {
Self::with_capacity(0)
}
pub fn with_capacity(capacity: usize) -> CkAttrs<'static> {
CkAttrs {
v: Vec::new(),
p: Cow::Owned(Vec::with_capacity(capacity)),
zeroize: false,
br: Vec::new(),
}
}
pub fn from_ptr(
a: *mut CK_ATTRIBUTE,
l: CK_ULONG,
) -> Result<CkAttrs<'static>> {
if a.is_null() {
return Err(CKR_ARGUMENTS_BAD)?;
}
Ok(CkAttrs {
v: Vec::new(),
p: Cow::Borrowed(unsafe {
std::slice::from_raw_parts(a, usize::try_from(l)?)
}),
zeroize: false,
br: Vec::new(),
})
}
pub fn from(a: &'a [CK_ATTRIBUTE]) -> CkAttrs<'a> {
CkAttrs {
v: Vec::new(),
p: Cow::Borrowed(a),
zeroize: false,
br: Vec::new(),
}
}
pub fn from_attributes(attributes: &'a [Attribute]) -> Result<CkAttrs<'a>> {
let mut ck_attrs = CkAttrs::with_capacity(attributes.len());
for attr in attributes {
ck_attrs.add_slice(attr.ck_type, &attr.value)?;
}
Ok(ck_attrs)
}
fn attr_from_last(&self, typ: CK_ATTRIBUTE_TYPE) -> Result<CK_ATTRIBUTE> {
if let Some(r) = self.v.last() {
Ok(CK_ATTRIBUTE {
type_: typ,
pValue: void_ptr!(r.as_ptr()),
ulValueLen: CK_ULONG::try_from(r.len())?,
})
} else {
Err(CKR_GENERAL_ERROR)?
}
}
pub fn add_owned_slice(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: &[u8],
) -> Result<()> {
self.v.push(val.to_vec());
let a = self.attr_from_last(typ)?;
self.p.to_mut().push(a);
Ok(())
}
pub fn add_owned_ulong(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: CK_ULONG,
) -> Result<()> {
self.v.push(val.to_ne_bytes().to_vec());
let a = self.attr_from_last(typ)?;
self.p.to_mut().push(a);
Ok(())
}
pub fn add_owned_bool(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: CK_BBOOL,
) -> Result<()> {
self.v.push(val.to_ne_bytes().to_vec());
let a = self.attr_from_last(typ)?;
self.p.to_mut().push(a);
Ok(())
}
pub fn add_vec(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: Vec<u8>,
) -> Result<()> {
self.v.push(val);
let a = self.attr_from_last(typ)?;
self.p.to_mut().push(a);
Ok(())
}
pub fn add_slice(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: &'a [u8],
) -> Result<()> {
self.p.to_mut().push(CK_ATTRIBUTE {
type_: typ,
pValue: val.as_ptr() as *mut std::ffi::c_void,
ulValueLen: CK_ULONG::try_from(val.len())?,
});
self.br.push(BorrowedReference::Slice(val));
Ok(())
}
pub fn add_ulong(&mut self, typ: CK_ATTRIBUTE_TYPE, val: &'a CK_ULONG) {
self.p.to_mut().push(CK_ATTRIBUTE {
type_: typ,
pValue: val as *const CK_ULONG as *mut std::ffi::c_void,
ulValueLen: sizeof!(CK_ULONG),
});
self.br.push(BorrowedReference::Ulong(val));
}
pub fn add_bool(&mut self, typ: CK_ATTRIBUTE_TYPE, val: &'a CK_BBOOL) {
self.p.to_mut().push(CK_ATTRIBUTE {
type_: typ,
pValue: val as *const CK_BBOOL as *mut std::ffi::c_void,
ulValueLen: sizeof!(CK_BBOOL),
});
self.br.push(BorrowedReference::CharBool(val));
}
pub fn add_missing_slice(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: &'a [u8],
) -> Result<()> {
match self.p.as_ref().iter().find(|a| a.type_ == typ) {
Some(_) => Ok(()),
None => self.add_slice(typ, val),
}
}
pub fn add_missing_ulong(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: &'a CK_ULONG,
) {
match self.p.as_ref().iter().find(|a| a.type_ == typ) {
Some(_) => (),
None => self.add_ulong(typ, val),
}
}
pub fn add_missing_bool(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: &'a CK_BBOOL,
) {
match self.p.as_ref().iter().find(|a| a.type_ == typ) {
Some(_) => (),
None => self.add_bool(typ, val),
}
}
pub fn remove_ulong(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
) -> Result<Option<CK_ULONG>> {
match self.p.as_ref().iter().position(|a| a.type_ == typ) {
Some(idx) => Ok(Some(self.p.to_mut().swap_remove(idx).to_ulong()?)),
None => return Ok(None),
}
}
pub fn remove_attr(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
) -> Option<RemovedAttr<'a>> {
match self.p.as_ref().iter().position(|a| a.type_ == typ) {
Some(idx) => Some(RemovedAttr(
self.p.to_mut().swap_remove(idx),
std::marker::PhantomData,
)),
None => None,
}
}
pub fn len(&self) -> usize {
self.p.as_ref().len()
}
pub fn as_ptr(&self) -> *const CK_ATTRIBUTE {
self.p.as_ref().as_ptr()
}
pub fn as_mut_ptr(&mut self) -> *mut CK_ATTRIBUTE {
self.p.to_mut().as_mut_ptr()
}
pub fn as_slice(&'a self) -> &'a [CK_ATTRIBUTE] {
self.p.as_ref()
}
pub fn find_attr(
&'a self,
typ: CK_ATTRIBUTE_TYPE,
) -> Option<&'a CK_ATTRIBUTE> {
match self.p.as_ref().iter().find(|a| a.type_ == typ) {
Some(ref a) => Some(a),
None => None,
}
}
pub fn insert_unique_vec(
&mut self,
typ: CK_ATTRIBUTE_TYPE,
val: Vec<u8>,
) -> Result<()> {
self.v.push(val);
let attr = self.attr_from_last(typ)?;
match self.p.as_ref().iter().position(|a| a.type_ == typ) {
Some(idx) => self.p.to_mut()[idx] = attr,
None => self.p.to_mut().push(attr),
}
Ok(())
}
pub fn get_ulong(
&'a self,
typ: CK_ATTRIBUTE_TYPE,
) -> Result<Option<CK_ULONG>> {
match self.p.as_ref().iter().find(|a| a.type_ == typ) {
Some(ref a) => match a.to_ulong() {
Ok(l) => Ok(Some(l)),
Err(_) => Err(CKR_TEMPLATE_INCONSISTENT)?,
},
None => Ok(None),
}
}
}