1use anyhow::{Ok, Result};
10use clap::ValueEnum;
11use cryptoki::mechanism::rsa::{PkcsMgfType, PkcsOaepParams, PkcsOaepSource};
12use cryptoki::mechanism::vendor_defined::{CKM_VENDOR_DEFINED, VendorDefinedMechanism};
13use cryptoki::mechanism::{Mechanism, MechanismType};
14use cryptoki::object::{Attribute, ObjectHandle};
15use cryptoki::session::Session;
16use serde::{Deserialize, Serialize};
17use strum::{Display, EnumString};
18
19use crate::error::HsmError;
20use crate::util::attribute::{AttributeMap, AttributeType, KeyType, ObjectClass};
21use crate::util::helper;
22
23#[derive(
25 Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Display, EnumString, ValueEnum,
26)]
27#[strum(ascii_case_insensitive)]
28pub enum Wrap {
29 AesKeyWrap,
30 AesKeyWrapPad,
31 RsaPkcs,
32 RsaPkcsOaep,
33 VendorThalesAesKwp,
34}
35
36#[derive(
38 Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Display, EnumString, ValueEnum,
39)]
40#[strum(ascii_case_insensitive)]
41pub enum WrapPrivateKey {
42 AesKeyWrap,
43 AesKeyWrapPad,
44 VendorThalesAesKwp,
45}
46
47impl From<WrapPrivateKey> for Wrap {
48 fn from(wrap: WrapPrivateKey) -> Self {
49 match wrap {
50 WrapPrivateKey::AesKeyWrap => Wrap::AesKeyWrap,
51 WrapPrivateKey::AesKeyWrapPad => Wrap::AesKeyWrapPad,
52 WrapPrivateKey::VendorThalesAesKwp => Wrap::VendorThalesAesKwp,
53 }
54 }
55}
56
57impl Wrap {
58 const CKM_THALES_AES_KWP: u64 = CKM_VENDOR_DEFINED | 0x00000171;
60
61 pub fn mechanism(&self) -> Result<Mechanism<'_>> {
62 match self {
63 Wrap::AesKeyWrap => Ok(Mechanism::AesKeyWrap),
64 Wrap::AesKeyWrapPad => Ok(Mechanism::AesKeyWrapPad),
65 Wrap::RsaPkcs => Ok(Mechanism::RsaPkcs),
66 Wrap::RsaPkcsOaep => Ok(Mechanism::RsaPkcsOaep(PkcsOaepParams::new(
67 MechanismType::SHA256,
68 PkcsMgfType::MGF1_SHA256,
69 PkcsOaepSource::empty(),
70 ))),
71 Wrap::VendorThalesAesKwp => {
72 Ok(Mechanism::VendorDefined(VendorDefinedMechanism::new::<()>(
73 MechanismType::new_vendor_defined(Wrap::CKM_THALES_AES_KWP)?,
74 None,
75 )))
76 }
77 }
78 }
79
80 pub fn wrapping_key(&self, session: &Session, label: Option<&str>) -> Result<ObjectHandle> {
81 let mut attrs = helper::search_spec(None, label)?;
82 attrs.push(Attribute::Wrap(true));
83 match self {
84 Wrap::AesKeyWrap | Wrap::AesKeyWrapPad | Wrap::VendorThalesAesKwp => {
85 attrs.push(Attribute::KeyType(KeyType::Aes.try_into()?));
86 attrs.push(Attribute::Class(ObjectClass::SecretKey.try_into()?));
87 helper::find_one_object(session, &attrs)
88 }
89 Wrap::RsaPkcs | Wrap::RsaPkcsOaep => {
90 attrs.push(Attribute::KeyType(KeyType::Rsa.try_into()?));
91 attrs.push(Attribute::Class(ObjectClass::PublicKey.try_into()?));
92 helper::find_one_object(session, &attrs)
93 }
94 }
95 }
96
97 pub fn unwrapping_key(&self, session: &Session, label: Option<&str>) -> Result<ObjectHandle> {
98 let mut attrs = helper::search_spec(None, label)?;
99 attrs.push(Attribute::Unwrap(true));
100 match self {
101 Wrap::AesKeyWrap | Wrap::AesKeyWrapPad | Wrap::VendorThalesAesKwp => {
102 attrs.push(Attribute::KeyType(KeyType::Aes.try_into()?));
103 attrs.push(Attribute::Class(ObjectClass::SecretKey.try_into()?));
104 helper::find_one_object(session, &attrs)
105 }
106 Wrap::RsaPkcs | Wrap::RsaPkcsOaep => {
107 attrs.push(Attribute::KeyType(KeyType::Rsa.try_into()?));
108 attrs.push(Attribute::Class(ObjectClass::PrivateKey.try_into()?));
109 helper::find_one_object(session, &attrs)
110 }
111 }
112 }
113
114 pub fn check_key(&self, session: &Session, key: ObjectHandle) -> Result<()> {
115 let map = AttributeMap::from_object(session, key)?;
116
117 let extractable: bool = map
118 .get(&AttributeType::Extractable)
119 .ok_or_else(|| HsmError::KeyError("Key does not have an extractable attribute".into()))?
120 .try_into()
121 .map_err(HsmError::AttributeError)?;
122 if !extractable {
123 Err(HsmError::KeyError("Key is not extractable".into()))?;
124 }
125
126 let key_type: KeyType = map
127 .get(&AttributeType::KeyType)
128 .ok_or_else(|| HsmError::KeyError("Key does not have a key type attribute".into()))?
129 .try_into()
130 .map_err(HsmError::AttributeError)?;
131
132 if *self == Wrap::RsaPkcsOaep || *self == Wrap::RsaPkcs {
133 let result = match key_type {
134 KeyType::Aes => Ok(()),
135 KeyType::GenericSecret => Ok(()),
136 _ => Err(HsmError::KeyError(format!(
137 "Unsupported key type: {key_type:?}"
138 )))?,
139 };
140 result?;
141 }
142
143 Ok(())
144 }
145
146 pub fn wrap(
147 &self,
148 session: &Session,
149 key: ObjectHandle,
150 wrapping_key_label: Option<&str>,
151 ) -> Result<Vec<u8>> {
152 self.check_key(session, key)?;
153 let wrapping_key = self.wrapping_key(session, wrapping_key_label)?;
154 let mechanism = self.mechanism()?;
155 Ok(session.wrap_key(&mechanism, wrapping_key, key)?)
156 }
157
158 pub fn unwrap(
159 &self,
160 session: &Session,
161 wrapped_key: &[u8],
162 wrapping_key_label: Option<&str>,
163 template: &AttributeMap,
164 ) -> Result<ObjectHandle> {
165 let wrapping_key = self.unwrapping_key(session, wrapping_key_label)?;
166 let mechanism = self.mechanism()?;
167 Ok(session.unwrap_key(
168 &mechanism,
169 wrapping_key,
170 wrapped_key,
171 template.to_vec()?.as_slice(),
172 )?)
173 }
174}