1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //! KeyPolicy serialization facilities
18
19 use alloc::collections::btree_set::BTreeSet;
20 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::types::{
21 KeyLifetime::KeyLifetime, KeyPermissions::KeyPermissions, KeyType::KeyType, KeyUse::KeyUse,
22 };
23 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::KeyPolicy::KeyPolicy;
24 use ciborium::Value;
25 use coset::{AsCborValue, CborSerializable, CoseError};
26
27 use crate::{aidl_enum_wrapper, cose_enum_gen};
28 use crate::{err::HwCryptoError, hwcrypto_err};
29
30 aidl_enum_wrapper! {
31 aidl_name: KeyUse,
32 wrapper_name: KeyUseSerializable,
33 fields: [ENCRYPT, DECRYPT, ENCRYPT_DECRYPT, SIGN, DERIVE, WRAP]
34 }
35
36 aidl_enum_wrapper! {
37 aidl_name: KeyLifetime,
38 wrapper_name: KeyLifetimeSerializable,
39 fields: [EPHEMERAL, HARDWARE, PORTABLE]
40 }
41
42 aidl_enum_wrapper! {
43 aidl_name: KeyType,
44 wrapper_name: KeyTypeSerializable,
45 fields: [AES_128_CBC_NO_PADDING, AES_128_CBC_PKCS7_PADDING, AES_128_CTR, AES_128_GCM, AES_128_CMAC,
46 AES_256_CBC_NO_PADDING, AES_256_CBC_PKCS7_PADDING, AES_256_CTR, AES_256_GCM, AES_256_CMAC,
47 HMAC_SHA256, HMAC_SHA512,
48 RSA2048_PKCS1_5_SHA256, RSA2048_PSS_SHA256, ECC_NIST_P256_SIGN_NO_PADDING, ECC_NIST_P256_SIGN_SHA256,
49 ECC_NIST_P521_SIGN_NO_PADDING, ECC_NIST_P521_SIGN_SHA512,
50 ECC_ED25519_SIGN]
51 }
52
53 aidl_enum_wrapper! {
54 aidl_name: KeyPermissions,
55 wrapper_name: KeyPermissionsSerializable,
56 fields: [ALLOW_EPHEMERAL_KEY_WRAPPING, ALLOW_HARDWARE_KEY_WRAPPING, ALLOW_PORTABLE_KEY_WRAPPING]
57 }
58
59 #[derive(Debug, PartialEq)]
60 struct SerializableKeyPolicy {
61 key_lifetime: KeyLifetimeSerializable,
62 key_permissions: BTreeSet<KeyPermissionsSerializable>,
63 key_usage: KeyUseSerializable,
64 key_type: KeyTypeSerializable,
65 management_key: bool,
66 }
67
68 impl SerializableKeyPolicy {
new(key_policy: &KeyPolicy) -> Result<Self, crate::err::HwCryptoError>69 fn new(key_policy: &KeyPolicy) -> Result<Self, crate::err::HwCryptoError> {
70 let mut key_permissions = BTreeSet::new();
71 for permission in &key_policy.keyPermissions {
72 key_permissions.insert(KeyPermissionsSerializable(*permission));
73 }
74 Ok(Self {
75 key_lifetime: KeyLifetimeSerializable(key_policy.keyLifetime),
76 key_permissions,
77 key_usage: KeyUseSerializable(key_policy.usage),
78 key_type: KeyTypeSerializable(key_policy.keyType),
79 management_key: key_policy.keyManagementKey,
80 })
81 }
82 }
83
84 impl TryFrom<&KeyPolicy> for SerializableKeyPolicy {
85 type Error = crate::err::HwCryptoError;
86
try_from(value: &KeyPolicy) -> Result<Self, Self::Error>87 fn try_from(value: &KeyPolicy) -> Result<Self, Self::Error> {
88 Self::new(value)
89 }
90 }
91
92 impl TryFrom<KeyPolicy> for SerializableKeyPolicy {
93 type Error = crate::err::HwCryptoError;
94
try_from(value: KeyPolicy) -> Result<Self, Self::Error>95 fn try_from(value: KeyPolicy) -> Result<Self, Self::Error> {
96 (&value).try_into()
97 }
98 }
99
100 impl TryFrom<&SerializableKeyPolicy> for KeyPolicy {
101 type Error = crate::err::HwCryptoError;
102
try_from(value: &SerializableKeyPolicy) -> Result<Self, Self::Error>103 fn try_from(value: &SerializableKeyPolicy) -> Result<Self, Self::Error> {
104 let mut key_permissions = Vec::new();
105 key_permissions.try_reserve(value.key_permissions.len())?;
106 // permissions on the returned key policy will be sorted because they are retrieved that
107 // way from the SerializableKeyPolicy
108 for permission in &value.key_permissions {
109 key_permissions.push((*permission).into());
110 }
111 Ok(Self {
112 keyLifetime: value.key_lifetime.into(),
113 keyPermissions: key_permissions,
114 usage: value.key_usage.into(),
115 keyType: value.key_type.into(),
116 keyManagementKey: value.management_key,
117 })
118 }
119 }
120
121 impl TryFrom<SerializableKeyPolicy> for KeyPolicy {
122 type Error = crate::err::HwCryptoError;
123
try_from(value: SerializableKeyPolicy) -> Result<Self, Self::Error>124 fn try_from(value: SerializableKeyPolicy) -> Result<Self, Self::Error> {
125 (&value).try_into()
126 }
127 }
128
129 cose_enum_gen! {
130 enum HeaderCoseLabels {
131 KeyUsage = -65701,
132 KeyLifetime = -65702,
133 KeyPermissions = -65703,
134 KeyType = -65704,
135 ManagementKey = -65705,
136 }
137 }
138
139 impl AsCborValue for SerializableKeyPolicy {
to_cbor_value(self) -> Result<Value, CoseError>140 fn to_cbor_value(self) -> Result<Value, CoseError> {
141 let mut cbor_map = Vec::<(Value, Value)>::new();
142 let key = Value::Integer((HeaderCoseLabels::KeyLifetime as i64).into());
143 let value = Value::Integer(self.key_lifetime.into());
144 cbor_map.try_reserve_exact(5).map_err(|_| CoseError::EncodeFailed)?;
145 cbor_map.push((key, value));
146
147 // Creating key permissions array
148 // We need this array to always be sorted so the created CBOR structure will always match
149 // if the input vector has the same permissions, this is currently provided by
150 // `BTreeSet::into_iter` always returning the elements ordered in ascending order.
151 let mut permissions = Vec::new();
152 permissions.try_reserve(self.key_permissions.len()).map_err(|_| CoseError::EncodeFailed)?;
153 for permission in self.key_permissions.into_iter() {
154 permissions.push(Value::Integer(permission.into()));
155 }
156 let key = Value::Integer((HeaderCoseLabels::KeyPermissions as i64).into());
157 let value = Value::Array(permissions);
158 cbor_map.push((key, value));
159
160 let key = Value::Integer((HeaderCoseLabels::KeyUsage as i64).into());
161 let value = Value::Integer(self.key_usage.into());
162 cbor_map.push((key, value));
163
164 let key = Value::Integer((HeaderCoseLabels::KeyType as i64).into());
165 let value = Value::Integer(self.key_type.into());
166 cbor_map.push((key, value));
167
168 let key = Value::Integer((HeaderCoseLabels::ManagementKey as i64).into());
169 let value = Value::Bool(self.management_key.into());
170 cbor_map.push((key, value));
171
172 Ok(Value::Map(cbor_map))
173 }
174
from_cbor_value(value: Value) -> Result<Self, CoseError>175 fn from_cbor_value(value: Value) -> Result<Self, CoseError> {
176 let key_policy = value.into_map().map_err(|_| CoseError::ExtraneousData)?;
177
178 let mut key_lifetime: Option<KeyLifetimeSerializable> = None;
179 let mut key_permissions: Option<BTreeSet<KeyPermissionsSerializable>> = None;
180 let mut key_usage: Option<KeyUseSerializable> = None;
181 let mut key_type: Option<KeyTypeSerializable> = None;
182 let mut management_key: Option<bool> = None;
183
184 for (map_key, map_val) in key_policy {
185 let key = map_key.into_integer().map_err(|_| CoseError::ExtraneousData)?;
186 match key.try_into()? {
187 HeaderCoseLabels::KeyLifetime => {
188 key_lifetime = Some(
189 map_val
190 .as_integer()
191 .ok_or(CoseError::EncodeFailed)?
192 .try_into()
193 .map_err(|_| CoseError::EncodeFailed)?,
194 );
195 }
196 HeaderCoseLabels::KeyPermissions => {
197 let mut permissions = BTreeSet::new();
198 for permission in map_val.as_array().ok_or(CoseError::EncodeFailed)? {
199 permissions.insert(
200 permission
201 .as_integer()
202 .ok_or(CoseError::EncodeFailed)?
203 .try_into()
204 .map_err(|_| CoseError::EncodeFailed)?,
205 );
206 }
207 key_permissions = Some(permissions);
208 }
209 HeaderCoseLabels::KeyUsage => {
210 key_usage = Some(
211 map_val
212 .as_integer()
213 .ok_or(CoseError::EncodeFailed)?
214 .try_into()
215 .map_err(|_| CoseError::EncodeFailed)?,
216 );
217 }
218 HeaderCoseLabels::KeyType => {
219 key_type = Some(
220 map_val
221 .as_integer()
222 .ok_or(CoseError::EncodeFailed)?
223 .try_into()
224 .map_err(|_| CoseError::EncodeFailed)?,
225 );
226 }
227 HeaderCoseLabels::ManagementKey => {
228 management_key = Some(map_val.as_bool().ok_or(CoseError::EncodeFailed)?);
229 }
230 }
231 }
232
233 let key_lifetime = key_lifetime.ok_or(CoseError::EncodeFailed)?;
234 let key_permissions = key_permissions.ok_or(CoseError::EncodeFailed)?;
235 let key_usage = key_usage.ok_or(CoseError::EncodeFailed)?;
236 let key_type = key_type.ok_or(CoseError::EncodeFailed)?;
237 let management_key = management_key.ok_or(CoseError::EncodeFailed)?;
238
239 Ok(SerializableKeyPolicy {
240 key_lifetime,
241 key_permissions,
242 key_usage,
243 key_type,
244 management_key,
245 })
246 }
247 }
248
249 pub static AES_SYMMETRIC_KEY_USES_MASK: i32 = KeyUse::ENCRYPT_DECRYPT.0 | KeyUse::WRAP.0;
250 pub static HMAC_KEY_USES_MASK: i32 = KeyUse::DERIVE.0;
251
check_key_policy(key_policy: &KeyPolicy) -> Result<(), HwCryptoError>252 pub fn check_key_policy(key_policy: &KeyPolicy) -> Result<(), HwCryptoError> {
253 match key_policy.keyType {
254 KeyType::AES_128_CBC_NO_PADDING
255 | KeyType::AES_128_CBC_PKCS7_PADDING
256 | KeyType::AES_128_CTR
257 | KeyType::AES_128_GCM
258 | KeyType::AES_256_CBC_NO_PADDING
259 | KeyType::AES_256_CBC_PKCS7_PADDING
260 | KeyType::AES_256_CTR
261 | KeyType::AES_256_GCM => {
262 if (key_policy.usage.0 & !AES_SYMMETRIC_KEY_USES_MASK) != 0 {
263 Err(hwcrypto_err!(
264 BAD_PARAMETER,
265 "usage not supported for AES symmetric key: {}",
266 key_policy.usage.0
267 ))
268 } else {
269 Ok(())
270 }
271 }
272 KeyType::HMAC_SHA256 | KeyType::HMAC_SHA512 => {
273 if (key_policy.usage.0 & !HMAC_KEY_USES_MASK) != 0 {
274 Err(hwcrypto_err!(
275 BAD_PARAMETER,
276 "usage not supported for HMAC key: {}",
277 key_policy.usage.0
278 ))
279 } else {
280 Ok(())
281 }
282 }
283 KeyType::AES_128_CMAC
284 | KeyType::AES_256_CMAC
285 | KeyType::RSA2048_PSS_SHA256
286 | KeyType::RSA2048_PKCS1_5_SHA256
287 | KeyType::ECC_NIST_P256_SIGN_NO_PADDING
288 | KeyType::ECC_NIST_P256_SIGN_SHA256
289 | KeyType::ECC_NIST_P521_SIGN_NO_PADDING
290 | KeyType::ECC_NIST_P521_SIGN_SHA512
291 | KeyType::ECC_ED25519_SIGN => {
292 Err(hwcrypto_err!(UNSUPPORTED, "key type not supported yet"))
293 }
294 _ => Err(hwcrypto_err!(BAD_PARAMETER, "unknown keytype provided {:?}", key_policy.keyType)),
295 }
296 }
297
cbor_serialize_key_policy(key_policy: &KeyPolicy) -> Result<Vec<u8>, HwCryptoError>298 pub fn cbor_serialize_key_policy(key_policy: &KeyPolicy) -> Result<Vec<u8>, HwCryptoError> {
299 let serializable_key_policy: SerializableKeyPolicy = key_policy.try_into()?;
300 serializable_key_policy
301 .to_cbor_value()?
302 .to_vec()
303 .map_err(|_| hwcrypto_err!(SERIALIZATION_ERROR, "couldn't serialize policy"))
304 }
305
cbor_policy_to_aidl(cbor_key_policy: &[u8]) -> Result<KeyPolicy, HwCryptoError>306 pub fn cbor_policy_to_aidl(cbor_key_policy: &[u8]) -> Result<KeyPolicy, HwCryptoError> {
307 let policy =
308 SerializableKeyPolicy::from_cbor_value(Value::from_slice(cbor_key_policy)?)?.try_into()?;
309 check_key_policy(&policy)?;
310 Ok(policy)
311 }
312
313 #[cfg(test)]
314 mod tests {
315 use super::*;
316 use test::{expect, expect_eq};
317
318 #[test]
serialize_policy()319 fn serialize_policy() {
320 let policy = KeyPolicy {
321 usage: KeyUse::ENCRYPT,
322 keyLifetime: KeyLifetime::EPHEMERAL,
323 keyPermissions: Vec::new(),
324 keyType: KeyType::AES_256_GCM,
325 keyManagementKey: false,
326 };
327
328 let serialize_result = cbor_serialize_key_policy(&policy);
329 expect!(serialize_result.is_ok(), "couldn't serialize policy");
330 let serialized_policy = serialize_result.unwrap();
331 let deserialization = cbor_policy_to_aidl(serialized_policy.as_slice());
332 expect!(deserialization.is_ok(), "couldn't deserialize policy");
333 let deserialized_policy = deserialization.unwrap();
334 let policy: SerializableKeyPolicy = policy.try_into().unwrap();
335 let deserialized_policy: SerializableKeyPolicy = (&deserialized_policy).try_into().unwrap();
336 expect_eq!(policy, deserialized_policy, "policies should match");
337 }
338
339 #[test]
bad_policies()340 fn bad_policies() {
341 let mut policy = KeyPolicy {
342 usage: KeyUse::SIGN,
343 keyLifetime: KeyLifetime::EPHEMERAL,
344 keyPermissions: Vec::new(),
345 keyType: KeyType::AES_256_GCM,
346 keyManagementKey: false,
347 };
348 let serialize_result = cbor_serialize_key_policy(&policy);
349 expect!(serialize_result.is_ok(), "couldn't serialize policy");
350 let serialized_policy = serialize_result.unwrap();
351 let deserialization = cbor_policy_to_aidl(serialized_policy.as_slice());
352 expect!(deserialization.is_err(), "shouldn't be able to deserailize incorrect policy");
353
354 policy.usage = KeyUse::DERIVE;
355 let serialize_result = cbor_serialize_key_policy(&policy);
356 expect!(serialize_result.is_ok(), "couldn't serialize policy");
357 let serialized_policy = serialize_result.unwrap();
358 let deserialization = cbor_policy_to_aidl(serialized_policy.as_slice());
359 expect!(deserialization.is_err(), "shouldn't be able to deserailize incorrect policy");
360
361 policy.keyType = KeyType::HMAC_SHA256;
362 policy.usage = KeyUse::ENCRYPT;
363 let serialize_result = cbor_serialize_key_policy(&policy);
364 expect!(serialize_result.is_ok(), "couldn't serialize policy");
365 let serialized_policy = serialize_result.unwrap();
366 let deserialization = cbor_policy_to_aidl(serialized_policy.as_slice());
367 expect!(deserialization.is_err(), "shouldn't be able to deserailize incorrect policy");
368
369 policy.usage = KeyUse::DECRYPT;
370 let serialize_result = cbor_serialize_key_policy(&policy);
371 expect!(serialize_result.is_ok(), "couldn't serialize policy");
372 let serialized_policy = serialize_result.unwrap();
373 let deserialization = cbor_policy_to_aidl(serialized_policy.as_slice());
374 expect!(deserialization.is_err(), "shouldn't be able to deserailize incorrect policy");
375
376 policy.keyType = KeyType::HMAC_SHA512;
377 policy.usage = KeyUse::ENCRYPT_DECRYPT;
378 let serialize_result = cbor_serialize_key_policy(&policy);
379 expect!(serialize_result.is_ok(), "couldn't serialize policy");
380 let serialized_policy = serialize_result.unwrap();
381 let deserialization = cbor_policy_to_aidl(serialized_policy.as_slice());
382 expect!(deserialization.is_err(), "shouldn't be able to deserailize incorrect policy");
383 }
384 }
385