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 //! Implementation of the `IOpaqueKey` AIDL interface. It is used as a handle to key material
18
19 use android_hardware_security_see::aidl::android::hardware::security::see::hwcrypto::types::{
20 KeyLifetime::KeyLifetime, KeyPermissions::KeyPermissions, KeyType::KeyType, KeyUse::KeyUse,
21 };
22 use android_hardware_security_see::aidl::android::hardware::security::see::hwcrypto::{
23 IOpaqueKey::{BnOpaqueKey, IOpaqueKey},
24 KeyPolicy::KeyPolicy,
25 };
26 use android_hardware_security_see::binder;
27 use binder::binder_impl::Binder;
28 use core::fmt;
29 use hwcryptohal_common::{err::HwCryptoError, hwcrypto_err};
30 use kmr_common::{
31 crypto::{self, Aes, CurveType, Hkdf, Hmac, KeyMaterial, OpaqueOr, Rng},
32 explicit, FallibleAllocExt,
33 };
34 use kmr_wire::keymint::EcCurve;
35 use std::sync::OnceLock;
36
37 use crate::crypto_provider;
38
39 /// Number of bytes of unique value used to check if a key was created on current HWCrypto boot.
40 const UNIQUE_VALUE_SIZEOF: usize = 32;
41
42 /// Struct to wrap boot unique counter. It is used to tag objects to the current boot.
43 #[derive(Clone)]
44 struct BootUniqueValue([u8; UNIQUE_VALUE_SIZEOF]);
45
46 impl fmt::Debug for BootUniqueValue {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 write!(f, "[BootUniqueValue size: {}; data redacted]", UNIQUE_VALUE_SIZEOF)
49 }
50 }
51
52 impl PartialEq for BootUniqueValue {
eq(&self, other: &Self) -> bool53 fn eq(&self, other: &Self) -> bool {
54 openssl::memcmp::eq(&self.0, &other.0)
55 }
56 }
57
58 impl Eq for BootUniqueValue {}
59
60 impl BootUniqueValue {
new() -> Result<BootUniqueValue, HwCryptoError>61 fn new() -> Result<BootUniqueValue, HwCryptoError> {
62 get_boot_unique_value()
63 }
64 }
65
66 // Boot unique value is lazily initialized on the first call to retrieve it
67 static BOOT_UNIQUE_VALUE: OnceLock<BootUniqueValue> = OnceLock::new();
68
69 /// Retrieves boot unique value used to check if the key material was created on this boot. It
70 /// lazily initializes it.
get_boot_unique_value() -> Result<BootUniqueValue, HwCryptoError>71 fn get_boot_unique_value() -> Result<BootUniqueValue, HwCryptoError> {
72 // The function returns a `Result` even if it is currently infallible to allow replacing its
73 // current implementation with one that can fail when trying to retrieve a random number.
74 // If the RNG changes to a fallible one we could use `get_or_try_init`.
75 let boot_unique_value = BOOT_UNIQUE_VALUE.get_or_init(|| {
76 let mut rng = crypto_provider::RngImpl::default();
77 let mut new_boot_unique_value = BootUniqueValue([0u8; UNIQUE_VALUE_SIZEOF]);
78 rng.fill_bytes(&mut new_boot_unique_value.0[..]);
79 new_boot_unique_value
80 });
81 Ok(boot_unique_value.clone())
82 }
83
84 /// Header for a `ClearKey` which contains the key policy along with some data needed to manipulate
85 /// the key.
86 #[derive(Debug)]
87 #[allow(dead_code)]
88 pub(crate) struct KeyHeader {
89 boot_unique_value: BootUniqueValue,
90 expiration_time: Option<u64>,
91 key_lifetime: KeyLifetime,
92 key_permissions: Vec<KeyPermissions>,
93 key_usage: KeyUse,
94 key_type: KeyType,
95 management_key: bool,
96 }
97
98 impl KeyHeader {
new(policy: &KeyPolicy) -> Result<Self, HwCryptoError>99 fn new(policy: &KeyPolicy) -> Result<Self, HwCryptoError> {
100 let mut key_permissions = Vec::new();
101 key_permissions.try_extend_from_slice(&policy.keyPermissions[..])?;
102 Ok(Self {
103 boot_unique_value: BootUniqueValue::new()?,
104 expiration_time: None,
105 key_lifetime: policy.keyLifetime,
106 key_permissions,
107 key_usage: policy.usage,
108 key_type: policy.keyType,
109 management_key: policy.keyManagementKey,
110 })
111 }
112
get_policy(&self) -> Result<KeyPolicy, HwCryptoError>113 fn get_policy(&self) -> Result<KeyPolicy, HwCryptoError> {
114 let mut key_permissions = Vec::new();
115 key_permissions.try_extend_from_slice(&self.key_permissions[..])?;
116 Ok(KeyPolicy {
117 usage: self.key_usage,
118 keyLifetime: self.key_lifetime,
119 keyPermissions: key_permissions,
120 keyType: self.key_type,
121 keyManagementKey: self.management_key,
122 })
123 }
124
try_clone(&self) -> Result<Self, HwCryptoError>125 fn try_clone(&self) -> Result<Self, HwCryptoError> {
126 let mut key_permissions = Vec::new();
127 key_permissions.try_extend_from_slice(&self.key_permissions[..])?;
128 Ok(Self {
129 boot_unique_value: self.boot_unique_value.clone(),
130 expiration_time: self.expiration_time,
131 key_lifetime: self.key_lifetime,
132 key_permissions,
133 key_usage: self.key_usage,
134 key_type: self.key_type,
135 management_key: self.management_key,
136 })
137 }
138 }
139
140 /// `IOpaqueKey` implementation.
141 #[allow(dead_code)]
142 pub struct OpaqueKey {
143 pub(crate) key_header: KeyHeader,
144 pub(crate) key_material: KeyMaterial,
145 }
146
147 impl TryFrom<&binder::Strong<dyn IOpaqueKey>> for OpaqueKey {
148 type Error = HwCryptoError;
149
try_from(value: &binder::Strong<dyn IOpaqueKey>) -> Result<OpaqueKey, Self::Error>150 fn try_from(value: &binder::Strong<dyn IOpaqueKey>) -> Result<OpaqueKey, Self::Error> {
151 let binder = value.as_binder();
152 let remote = binder.is_remote();
153 if remote {
154 return Err(hwcrypto_err!(UNSUPPORTED, "binder is not local"));
155 }
156 let binder_key: Binder<BnOpaqueKey> =
157 binder.try_into().expect("because binder is local this should not fail");
158 let opaque_key_material = (*binder_key).downcast_binder::<OpaqueKey>();
159 match opaque_key_material {
160 Some(key) => key.try_clone(),
161 None => Err(hwcrypto_err!(UNSUPPORTED, "couldn't cast back key")),
162 }
163 }
164 }
165
166 impl OpaqueKey {
new_binder( policy: &KeyPolicy, key_material: KeyMaterial, ) -> binder::Result<binder::Strong<dyn IOpaqueKey>>167 pub(crate) fn new_binder(
168 policy: &KeyPolicy,
169 key_material: KeyMaterial,
170 ) -> binder::Result<binder::Strong<dyn IOpaqueKey>> {
171 let key_header = KeyHeader::new(policy)?;
172 check_key_material_with_policy(&key_material, policy)?;
173 let opaque_key = OpaqueKey { key_header, key_material };
174 let opaque_keybinder =
175 BnOpaqueKey::new_binder(opaque_key, binder::BinderFeatures::default());
176 Ok(opaque_keybinder)
177 }
178
try_clone(&self) -> Result<Self, HwCryptoError>179 fn try_clone(&self) -> Result<Self, HwCryptoError> {
180 let key_header = self.key_header.try_clone()?;
181 let key_material = self.key_material.clone();
182 Ok(OpaqueKey { key_header, key_material })
183 }
184
new_opaque_key_from_raw_bytes( policy: &KeyPolicy, key_material: Vec<u8>, ) -> binder::Result<binder::Strong<dyn IOpaqueKey>>185 fn new_opaque_key_from_raw_bytes(
186 policy: &KeyPolicy,
187 key_material: Vec<u8>,
188 ) -> binder::Result<binder::Strong<dyn IOpaqueKey>> {
189 let key_material = generate_key_material(&policy.keyType, Some(key_material))?;
190 OpaqueKey::new_binder(policy, key_material)
191 }
192
check_key_derivation_parameters( &self, policy: &KeyPolicy, ) -> Result<(), HwCryptoError>193 pub(crate) fn check_key_derivation_parameters(
194 &self,
195 policy: &KeyPolicy,
196 ) -> Result<(), HwCryptoError> {
197 // Check that we are trying to derive a supported key type
198 check_type_derived_key(policy.keyType)?;
199 // Check that the requested lifetime is compatible with the provided key lifetime
200 if !self.derivation_allowed_lifetime(policy.keyLifetime)? {
201 return Err(hwcrypto_err!(
202 BAD_PARAMETER,
203 "requested lifetime cannot be used {:?}",
204 &policy.keyLifetime
205 ));
206 }
207 // Check that the derivation key can be used to derive keys (KeyPermissions/KeyPolicies)
208 self.key_can_be_used_for_derivation()
209 }
210
derive_raw_key_material( &self, context: &[u8], derived_key_size: usize, ) -> Result<Vec<u8>, HwCryptoError>211 pub(crate) fn derive_raw_key_material(
212 &self,
213 context: &[u8],
214 derived_key_size: usize,
215 ) -> Result<Vec<u8>, HwCryptoError> {
216 match &self.key_material {
217 KeyMaterial::Hmac(key) => {
218 let hkdf = crypto_provider::HmacImpl;
219 let explicit_key = explicit!(key).map_err(|_| {
220 hwcrypto_err!(BAD_PARAMETER, "only explicit HMAC keys supported")
221 })?;
222 let raw_key = hkdf
223 .hkdf(&[], &explicit_key.0, context, derived_key_size)
224 .map_err(|e| hwcrypto_err!(GENERIC_ERROR, "couldn't derive key {:?}", e))?;
225 Ok(raw_key)
226 }
227 _ => Err(hwcrypto_err!(BAD_PARAMETER, "only HMAC keys supported")),
228 }
229 }
230
derive_key( &self, policy: &KeyPolicy, context: &[u8], ) -> binder::Result<binder::Strong<dyn IOpaqueKey>>231 pub(crate) fn derive_key(
232 &self,
233 policy: &KeyPolicy,
234 context: &[u8],
235 ) -> binder::Result<binder::Strong<dyn IOpaqueKey>> {
236 self.check_key_derivation_parameters(policy)?;
237 let derived_key_size = get_key_size_in_bytes(&policy.keyType)?;
238 let raw_key_material = self.derive_raw_key_material(context, derived_key_size)?;
239 Self::new_opaque_key_from_raw_bytes(policy, raw_key_material)
240 }
241
derivation_allowed_lifetime( &self, derived_key_lifetime: KeyLifetime, ) -> Result<bool, HwCryptoError>242 fn derivation_allowed_lifetime(
243 &self,
244 derived_key_lifetime: KeyLifetime,
245 ) -> Result<bool, HwCryptoError> {
246 validate_lifetime(self.key_header.key_lifetime)?;
247 validate_lifetime(derived_key_lifetime)?;
248 match self.key_header.key_lifetime {
249 //ephemeral keys can be used to derive/wrap any other key
250 KeyLifetime::EPHEMERAL => Ok(true),
251 KeyLifetime::HARDWARE => {
252 // Hardware keys cannot be used to derive/wrap ephemeral keys
253 if derived_key_lifetime.0 == KeyLifetime::EPHEMERAL.0 {
254 Ok(false)
255 } else {
256 Ok(true)
257 }
258 }
259 KeyLifetime::PORTABLE => {
260 // portable keys can only derive/wrap other portable keys
261 if derived_key_lifetime.0 == KeyLifetime::PORTABLE.0 {
262 Ok(true)
263 } else {
264 Ok(false)
265 }
266 }
267 _ => Err(hwcrypto_err!(
268 UNSUPPORTED,
269 "unsupported Key lifetime {:?}",
270 self.key_header.key_lifetime
271 )),
272 }
273 }
274
key_can_be_used_for_derivation(&self) -> Result<(), HwCryptoError>275 fn key_can_be_used_for_derivation(&self) -> Result<(), HwCryptoError> {
276 match self.key_material {
277 KeyMaterial::Hmac(_) => Ok(()),
278 _ => Err(hwcrypto_err!(UNSUPPORTED, "Only HMAC keys can be used for key derivation")),
279 }?;
280 if self.key_header.key_usage != KeyUse::DERIVE {
281 return Err(hwcrypto_err!(BAD_PARAMETER, "key was not exclusively a derive key"));
282 }
283 Ok(())
284 }
285 }
286
287 impl binder::Interface for OpaqueKey {}
288
289 impl IOpaqueKey for OpaqueKey {
exportWrappedKey( &self, _wrapping_key: &binder::Strong<dyn IOpaqueKey>, ) -> binder::Result<Vec<u8>>290 fn exportWrappedKey(
291 &self,
292 _wrapping_key: &binder::Strong<dyn IOpaqueKey>,
293 ) -> binder::Result<Vec<u8>> {
294 Err(binder::Status::new_exception_str(
295 binder::ExceptionCode::UNSUPPORTED_OPERATION,
296 Some("export_wrapped_key has not been implemented yet"),
297 ))
298 }
299
getKeyPolicy(&self) -> binder::Result<KeyPolicy>300 fn getKeyPolicy(&self) -> binder::Result<KeyPolicy> {
301 Ok(self.key_header.get_policy()?)
302 }
303
getPublicKey(&self) -> binder::Result<Vec<u8>>304 fn getPublicKey(&self) -> binder::Result<Vec<u8>> {
305 Err(binder::Status::new_exception_str(
306 binder::ExceptionCode::UNSUPPORTED_OPERATION,
307 Some("get_public_key has not been implemented yet"),
308 ))
309 }
310 }
311
check_key_material_with_policy( key_material: &KeyMaterial, policy: &KeyPolicy, ) -> Result<(), HwCryptoError>312 pub(crate) fn check_key_material_with_policy(
313 key_material: &KeyMaterial,
314 policy: &KeyPolicy,
315 ) -> Result<(), HwCryptoError> {
316 let key_type = &policy.keyType;
317 // `KeyMaterial` doesn't fully describe the cryptographic algorithm as `KeyType` does, so we can
318 // only check if both of them are compatible, not provide a 1:1 mapping
319 match key_material {
320 KeyMaterial::Aes(aes_key) => match aes_key {
321 OpaqueOr::Opaque(_) => Err(hwcrypto_err!(BAD_PARAMETER, "opaque aes key provided")),
322 OpaqueOr::Explicit(aes_key) => match aes_key {
323 crypto::aes::Key::Aes128(km) => match *key_type {
324 KeyType::AES_128_CBC_NO_PADDING
325 | KeyType::AES_128_CBC_PKCS7_PADDING
326 | KeyType::AES_128_CTR
327 | KeyType::AES_128_GCM
328 | KeyType::AES_128_CMAC => Ok(()),
329 _ => Err(hwcrypto_err!(
330 BAD_PARAMETER,
331 "type mismatch: key material {:?} key type: {:?}",
332 km,
333 key_type
334 )),
335 },
336 crypto::aes::Key::Aes192(_) => {
337 Err(hwcrypto_err!(BAD_PARAMETER, "AES keys of length 192 are not supported"))
338 }
339 crypto::aes::Key::Aes256(km) => match *key_type {
340 KeyType::AES_256_CBC_NO_PADDING
341 | KeyType::AES_256_CBC_PKCS7_PADDING
342 | KeyType::AES_256_CTR
343 | KeyType::AES_256_GCM
344 | KeyType::AES_256_CMAC => Ok(()),
345 _ => Err(hwcrypto_err!(
346 BAD_PARAMETER,
347 "type mismatch: key material {:?} key type: {:?}",
348 km,
349 key_type
350 )),
351 },
352 },
353 },
354 KeyMaterial::TripleDes(_) => {
355 Err(hwcrypto_err!(BAD_PARAMETER, "TDES is not currently supported"))
356 }
357 KeyMaterial::Hmac(hmac_key) => match hmac_key {
358 OpaqueOr::Opaque(_) => Err(hwcrypto_err!(BAD_PARAMETER, "opaque HMAC key provided")),
359 OpaqueOr::Explicit(_) => match *key_type {
360 KeyType::HMAC_SHA256 => Ok(()),
361 KeyType::HMAC_SHA512 => Ok(()),
362 _ => Err(hwcrypto_err!(
363 BAD_PARAMETER,
364 "type mismatch for HMAC key key type: {:?}",
365 key_type
366 )),
367 },
368 },
369 KeyMaterial::Rsa(rsa_key) => match rsa_key {
370 OpaqueOr::Opaque(_) => Err(hwcrypto_err!(BAD_PARAMETER, "opaque RSA key provided")),
371 OpaqueOr::Explicit(rsa_key) => {
372 let key_size = rsa_key.size();
373 match (key_size, *key_type) {
374 (2048, KeyType::RSA2048_PSS_SHA256) => Ok(()),
375 (2048, KeyType::RSA2048_PKCS1_5_SHA256) => Ok(()),
376 _ => Err(hwcrypto_err!(
377 BAD_PARAMETER,
378 "type mismatch for RSA key length {} and type: {:?}",
379 key_size,
380 key_type
381 )),
382 }
383 }
384 },
385 KeyMaterial::Ec(curve, curve_type, _) => match (curve, *key_type) {
386 (EcCurve::P256, KeyType::ECC_NIST_P256_SIGN_NO_PADDING) => Ok(()),
387 (EcCurve::P256, KeyType::ECC_NIST_P256_SIGN_SHA256) => Ok(()),
388 (EcCurve::P521, KeyType::ECC_NIST_P521_SIGN_NO_PADDING) => Ok(()),
389 (EcCurve::P521, KeyType::ECC_NIST_P521_SIGN_SHA512) => Ok(()),
390 (EcCurve::Curve25519, _) => match (curve_type, *key_type) {
391 (CurveType::EdDsa, KeyType::ECC_ED25519_SIGN) => Ok(()),
392 _ => Err(hwcrypto_err!(
393 BAD_PARAMETER,
394 "type mismatch for Ec Key curve {:?} and type: {:?}",
395 curve,
396 key_type
397 )),
398 },
399 _ => Err(hwcrypto_err!(
400 BAD_PARAMETER,
401 "type mismatch for Ec Key curve {:?} and type: {:?}",
402 curve,
403 key_type
404 )),
405 },
406 }
407 }
408
409 // Get key size in bytesgiven the backend AES key type. Used to check if we received enough bytes
410 // from the caller for an AES key.
get_aes_variant_key_size(variant: &crypto::aes::Variant) -> usize411 fn get_aes_variant_key_size(variant: &crypto::aes::Variant) -> usize {
412 match variant {
413 crypto::aes::Variant::Aes128 => 16,
414 crypto::aes::Variant::Aes192 => 24,
415 crypto::aes::Variant::Aes256 => 32,
416 }
417 }
418
419 // Translating a policy AES `KeyType` into the type understood by the cryptographic backend we are
420 // currently used
421 // TODO: change this into a `TryFrom` once we refactor `KeyType` to be a newtype.
get_aes_variant(key_type: &KeyType) -> Result<crypto::aes::Variant, HwCryptoError>422 fn get_aes_variant(key_type: &KeyType) -> Result<crypto::aes::Variant, HwCryptoError> {
423 match *key_type {
424 KeyType::AES_128_CBC_NO_PADDING
425 | KeyType::AES_128_CBC_PKCS7_PADDING
426 | KeyType::AES_128_CTR
427 | KeyType::AES_128_GCM
428 | KeyType::AES_128_CMAC => Ok(crypto::aes::Variant::Aes128),
429 KeyType::AES_256_CBC_NO_PADDING
430 | KeyType::AES_256_CBC_PKCS7_PADDING
431 | KeyType::AES_256_CTR
432 | KeyType::AES_256_GCM
433 | KeyType::AES_256_CMAC => Ok(crypto::aes::Variant::Aes256),
434 _ => Err(hwcrypto_err!(BAD_PARAMETER, "not an AES key type: {:?}", key_type)),
435 }
436 }
437
438 // Return a keysize given a `KeyType`. Because HMAC key sizes can be defined by the
439 // caller, `key_size_bits` is needed to cover all cases.
get_key_size_in_bytes(key_type: &KeyType) -> Result<usize, HwCryptoError>440 pub(crate) fn get_key_size_in_bytes(key_type: &KeyType) -> Result<usize, HwCryptoError> {
441 match *key_type {
442 KeyType::AES_128_CBC_NO_PADDING
443 | KeyType::AES_128_CBC_PKCS7_PADDING
444 | KeyType::AES_128_CTR
445 | KeyType::AES_128_GCM
446 | KeyType::AES_128_CMAC => Ok(16),
447 KeyType::AES_256_CBC_NO_PADDING
448 | KeyType::AES_256_CBC_PKCS7_PADDING
449 | KeyType::AES_256_CTR
450 | KeyType::AES_256_GCM
451 | KeyType::AES_256_CMAC => Ok(32),
452 KeyType::HMAC_SHA256 => Ok(32),
453 KeyType::HMAC_SHA512 => Ok(64),
454 _ => unimplemented!("Only AES and HMAC has been implemented"),
455 }
456 }
457
validate_lifetime(lifetime: KeyLifetime) -> Result<(), HwCryptoError>458 fn validate_lifetime(lifetime: KeyLifetime) -> Result<(), HwCryptoError> {
459 match lifetime {
460 KeyLifetime::EPHEMERAL | KeyLifetime::HARDWARE | KeyLifetime::PORTABLE => Ok(()),
461 // AIDL structure have more values added than the ones defined on the AIDL file
462 _ => Err(hwcrypto_err!(UNSUPPORTED, "unsupported Key lifetime {:?}", lifetime)),
463 }
464 }
465
check_type_derived_key(key_type: KeyType) -> Result<(), HwCryptoError>466 fn check_type_derived_key(key_type: KeyType) -> Result<(), HwCryptoError> {
467 match key_type {
468 KeyType::AES_128_CBC_NO_PADDING
469 | KeyType::AES_128_CBC_PKCS7_PADDING
470 | KeyType::AES_128_CTR
471 | KeyType::AES_128_GCM
472 | KeyType::AES_128_CMAC
473 | KeyType::AES_256_CBC_NO_PADDING
474 | KeyType::AES_256_CBC_PKCS7_PADDING
475 | KeyType::AES_256_CTR
476 | KeyType::AES_256_GCM
477 | KeyType::AES_256_CMAC
478 | KeyType::HMAC_SHA256
479 | KeyType::HMAC_SHA512 => Ok(()),
480 _ => Err(hwcrypto_err!(BAD_PARAMETER, "Only HMAC and AES keys are supported")),
481 }
482 }
483
key_vec_to_array<T, U: std::convert::TryInto<T>>(input: U) -> Result<T, HwCryptoError>484 fn key_vec_to_array<T, U: std::convert::TryInto<T>>(input: U) -> Result<T, HwCryptoError> {
485 input
486 .try_into()
487 .map_err(|_| hwcrypto_err!(BAD_PARAMETER, "couldn't transform vector into array"))
488 }
489
490 // Create a backend-compatible cryptographic key from either a provided vector of uniform random
491 // bytes or, if this not provided, use the cryptographic backend to create it. The type is based on
492 // the policy `KeyType`. Because HMAC keys can have arbitrary sizes, include an optional
493 // `key_size_bits` for that case.
generate_key_material( key_type: &KeyType, key_random_bytes: Option<Vec<u8>>, ) -> Result<KeyMaterial, HwCryptoError>494 pub(crate) fn generate_key_material(
495 key_type: &KeyType,
496 key_random_bytes: Option<Vec<u8>>,
497 ) -> Result<KeyMaterial, HwCryptoError> {
498 let aes = crypto_provider::AesImpl;
499 let hmac = crypto_provider::HmacImpl;
500 let mut rng = crypto_provider::RngImpl::default();
501 match *key_type {
502 KeyType::AES_128_CBC_NO_PADDING
503 | KeyType::AES_128_CBC_PKCS7_PADDING
504 | KeyType::AES_128_CTR
505 | KeyType::AES_128_GCM
506 | KeyType::AES_128_CMAC
507 | KeyType::AES_256_CBC_NO_PADDING
508 | KeyType::AES_256_CBC_PKCS7_PADDING
509 | KeyType::AES_256_CTR
510 | KeyType::AES_256_GCM
511 | KeyType::AES_256_CMAC => {
512 let variant = get_aes_variant(key_type)?;
513 if let Some(key_bytes) = key_random_bytes {
514 if key_bytes.len() != get_aes_variant_key_size(&variant) {
515 return Err(hwcrypto_err!(
516 BAD_PARAMETER,
517 "for aes key needed {} bytes, received {}",
518 key_bytes.len(),
519 get_aes_variant_key_size(&variant)
520 ));
521 }
522 match variant {
523 crypto::aes::Variant::Aes128 => Ok(KeyMaterial::Aes(
524 crypto::aes::Key::Aes128(key_vec_to_array(key_bytes)?).into(),
525 )),
526 crypto::aes::Variant::Aes192 => Err(hwcrypto_err!(
527 BAD_PARAMETER,
528 "AES keys of length 192 are not supported",
529 )),
530 crypto::aes::Variant::Aes256 => Ok(KeyMaterial::Aes(
531 crypto::aes::Key::Aes256(key_vec_to_array(key_bytes)?).into(),
532 )),
533 }
534 } else {
535 Ok(aes.generate_key(&mut rng, variant, &[])?)
536 }
537 }
538 KeyType::HMAC_SHA256 | KeyType::HMAC_SHA512 => {
539 let key_size_bytes = get_key_size_in_bytes(key_type)?;
540 if let Some(key_bytes) = key_random_bytes {
541 if key_bytes.len() != key_size_bytes {
542 Err(hwcrypto_err!(
543 BAD_PARAMETER,
544 "for hmac key needed {} bytes, received {}",
545 key_bytes.len(),
546 key_size_bytes
547 ))
548 } else {
549 Ok(KeyMaterial::Hmac(crypto::hmac::Key::new(key_bytes).into()))
550 }
551 } else {
552 Ok(hmac.generate_key(
553 &mut rng,
554 kmr_wire::KeySizeInBits((key_size_bytes * 8).try_into().map_err(|_| {
555 hwcrypto_err!(
556 GENERIC_ERROR,
557 "shouldn't happen, key_size_bytes * 8 should fit on an u32"
558 )
559 })?),
560 &[],
561 )?)
562 }
563 }
564 _ => unimplemented!("key material other than AES and HMAC not implemented yet"),
565 }
566 }
567
568 #[cfg(test)]
569 mod tests {
570 use super::*;
571 use test::{expect, expect_eq};
572
573 #[test]
boot_unique_values_match()574 fn boot_unique_values_match() {
575 let boot_value = BootUniqueValue::new().expect("couldn't get boot unique value");
576 let boot_value2 = BootUniqueValue::new().expect("couldn't get boot unique value");
577 expect_eq!(boot_value, boot_value2, "boot unique values should match");
578 }
579
580 #[test]
generate_key_material_test()581 fn generate_key_material_test() {
582 let usage = KeyUse::ENCRYPT;
583 let key_type = KeyType::AES_256_GCM;
584 let policy = KeyPolicy {
585 usage,
586 keyLifetime: KeyLifetime::EPHEMERAL,
587 keyPermissions: Vec::new(),
588 keyType: key_type,
589 keyManagementKey: false,
590 };
591 let key_material = generate_key_material(&policy.keyType, None);
592 expect!(key_material.is_ok(), "couldn't retrieve key material");
593 let key_material = key_material.unwrap();
594 let check_result = check_key_material_with_policy(&key_material, &policy);
595 expect!(check_result.is_ok(), "wrong key type");
596 }
597 }
598