1 //! Helper functionality for working with tags.
2
3 use crate::{
4 crypto,
5 crypto::{rsa::DecryptionMode, *},
6 km_err, try_to_vec, vec_try_with_capacity, Error, FallibleAllocExt,
7 };
8 use alloc::vec::Vec;
9 use kmr_wire::{
10 keymint::{
11 Algorithm, BlockMode, Digest, EcCurve, ErrorCode, KeyCharacteristics, KeyFormat, KeyParam,
12 KeyPurpose, PaddingMode, SecurityLevel, Tag, DEFAULT_CERT_SERIAL, DEFAULT_CERT_SUBJECT,
13 },
14 KeySizeInBits,
15 };
16 use log::{info, warn};
17
18 mod info;
19 pub use info::*;
20 pub mod legacy;
21 #[cfg(test)]
22 mod tests;
23
24 /// The set of tags that are directly copied from key generation/import parameters to
25 /// key characteristics without being checked.
26 pub const UNPOLICED_COPYABLE_TAGS: &[Tag] = &[
27 Tag::RollbackResistance,
28 Tag::EarlyBootOnly,
29 Tag::MaxUsesPerBoot,
30 Tag::UserSecureId, // repeatable
31 Tag::NoAuthRequired,
32 Tag::UserAuthType,
33 Tag::AuthTimeout,
34 Tag::TrustedUserPresenceRequired,
35 Tag::TrustedConfirmationRequired,
36 Tag::UnlockedDeviceRequired,
37 Tag::StorageKey,
38 ];
39
40 /// Indication of whether secure storage is available.
41 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
42 pub enum SecureStorage {
43 Available,
44 Unavailable,
45 }
46
47 /// Macro to retrieve a copy of the (single) value of a tag in a collection of `KeyParam`s. There
48 /// can be only one. Only works for variants whose data type implements `Copy`.
49 #[macro_export]
50 macro_rules! get_tag_value {
51 { $params:expr, $variant:ident, $err:expr } => {
52 {
53 let mut result = None;
54 let mut count = 0;
55 for param in $params {
56 if let kmr_wire::keymint::KeyParam::$variant(v) = param {
57 count += 1;
58 result = Some(*v);
59 }
60 }
61 match count {
62 0 => Err($crate::km_verr!($err, "missing tag {}", stringify!($variant))),
63 1 => Ok(result.unwrap()), /* safe: count=1 => exists */
64 _ => Err($crate::km_verr!($err, "duplicate tag {}", stringify!($variant))),
65 }
66 }
67 }
68 }
69
70 /// Macro to retrieve the value of an optional single-valued tag in a collection of `KeyParam`s. It
71 /// may or may not be present, but multiple instances of the tag are assumed to be invalid.
72 #[macro_export]
73 macro_rules! get_opt_tag_value {
74 { $params:expr, $variant:ident } => {
75 get_opt_tag_value!($params, $variant, InvalidTag)
76 };
77 { $params:expr, $variant:ident, $dup_error:ident } => {
78 {
79 let mut result = None;
80 let mut count = 0;
81 for param in $params {
82 if let kmr_wire::keymint::KeyParam::$variant(v) = param {
83 count += 1;
84 result = Some(v);
85 }
86 }
87 match count {
88 0 => Ok(None),
89 1 => Ok(Some(result.unwrap())), /* safe: count=1 => exists */
90 _ => Err($crate::km_err!($dup_error, "duplicate tag {}", stringify!($variant))),
91 }
92 }
93 }
94 }
95
96 /// Macro to retrieve a `bool` tag value, returning `false` if the tag is absent
97 #[macro_export]
98 macro_rules! get_bool_tag_value {
99 { $params:expr, $variant:ident } => {
100 {
101 let mut count = 0;
102 for param in $params {
103 if let kmr_wire::keymint::KeyParam::$variant = param {
104 count += 1;
105 }
106 }
107 match count {
108 0 => Ok(false),
109 1 => Ok(true),
110 _ => Err($crate::km_err!(InvalidTag, "duplicate tag {}", stringify!($variant))),
111 }
112 }
113 }
114 }
115
116 /// Macro to check a collection of `KeyParam`s holds a value matching the given value.
117 #[macro_export]
118 macro_rules! contains_tag_value {
119 { $params:expr, $variant:ident, $value:expr } => {
120 {
121 let mut found = false;
122 for param in $params {
123 if let kmr_wire::keymint::KeyParam::$variant(v) = param {
124 if *v == $value {
125 found = true;
126 }
127 }
128 }
129 found
130 }
131 }
132 }
133
134 /// Check that a set of [`KeyParam`]s is valid when considered as key characteristics.
characteristics_valid(characteristics: &[KeyParam]) -> Result<(), Error>135 pub fn characteristics_valid(characteristics: &[KeyParam]) -> Result<(), Error> {
136 let mut dup_checker = DuplicateTagChecker::default();
137 for param in characteristics {
138 let tag = param.tag();
139 dup_checker.add(tag)?;
140 if info(tag)?.characteristic == Characteristic::NotKeyCharacteristic {
141 return Err(
142 km_err!(InvalidKeyBlob, "tag {:?} is not a valid key characteristic", tag,),
143 );
144 }
145 }
146 Ok(())
147 }
148
149 /// Copy anything in `src` that matches `tags` into `dest`. Fails if any non-repeatable
150 /// tags occur more than once with a different value.
transcribe_tags( dest: &mut Vec<KeyParam>, src: &[KeyParam], tags: &[Tag], ) -> Result<(), Error>151 pub fn transcribe_tags(
152 dest: &mut Vec<KeyParam>,
153 src: &[KeyParam],
154 tags: &[Tag],
155 ) -> Result<(), Error> {
156 let mut dup_checker = DuplicateTagChecker::default();
157 for param in src {
158 let tag = param.tag();
159 dup_checker.add(tag)?;
160 if tags.iter().any(|t| *t == tag) {
161 dest.try_push(param.clone())?;
162 }
163 }
164 Ok(())
165 }
166
167 /// Get the configured algorithm from a set of parameters.
get_algorithm(params: &[KeyParam]) -> Result<Algorithm, Error>168 pub fn get_algorithm(params: &[KeyParam]) -> Result<Algorithm, Error> {
169 get_tag_value!(params, Algorithm, ErrorCode::UnsupportedAlgorithm)
170 }
171
172 /// Get the configured block mode from a set of parameters.
get_block_mode(params: &[KeyParam]) -> Result<BlockMode, Error>173 pub fn get_block_mode(params: &[KeyParam]) -> Result<BlockMode, Error> {
174 get_tag_value!(params, BlockMode, ErrorCode::UnsupportedBlockMode)
175 }
176
177 /// Get the configured padding mode from a set of parameters.
get_padding_mode(params: &[KeyParam]) -> Result<PaddingMode, Error>178 pub fn get_padding_mode(params: &[KeyParam]) -> Result<PaddingMode, Error> {
179 get_tag_value!(params, Padding, ErrorCode::UnsupportedPaddingMode)
180 }
181
182 /// Get the configured digest from a set of parameters.
get_digest(params: &[KeyParam]) -> Result<Digest, Error>183 pub fn get_digest(params: &[KeyParam]) -> Result<Digest, Error> {
184 get_tag_value!(params, Digest, ErrorCode::UnsupportedDigest)
185 }
186
187 /// Get the configured elliptic curve from a set of parameters.
get_ec_curve(params: &[KeyParam]) -> Result<EcCurve, Error>188 pub fn get_ec_curve(params: &[KeyParam]) -> Result<EcCurve, Error> {
189 get_tag_value!(params, EcCurve, ErrorCode::UnsupportedKeySize)
190 }
191
192 /// Get the configured MGF digest from a set of parameters. If no MGF digest is specified,
193 /// a default value of SHA1 is returned.
get_mgf_digest(params: &[KeyParam]) -> Result<Digest, Error>194 pub fn get_mgf_digest(params: &[KeyParam]) -> Result<Digest, Error> {
195 Ok(*get_opt_tag_value!(params, RsaOaepMgfDigest)?.unwrap_or(&Digest::Sha1))
196 }
197
198 /// Get the certificate serial number from a set of parameters, falling back to default value of 1
199 /// if not specified
get_cert_serial(params: &[KeyParam]) -> Result<&[u8], Error>200 pub fn get_cert_serial(params: &[KeyParam]) -> Result<&[u8], Error> {
201 Ok(get_opt_tag_value!(params, CertificateSerial)?
202 .map(Vec::as_ref)
203 .unwrap_or(DEFAULT_CERT_SERIAL))
204 }
205
206 /// Return the set of key parameters at the provided security level.
characteristics_at( chars: &[KeyCharacteristics], sec_level: SecurityLevel, ) -> Result<&[KeyParam], Error>207 pub fn characteristics_at(
208 chars: &[KeyCharacteristics],
209 sec_level: SecurityLevel,
210 ) -> Result<&[KeyParam], Error> {
211 let mut result: Option<&[KeyParam]> = None;
212 for chars in chars {
213 if chars.security_level != sec_level {
214 continue;
215 }
216 if result.is_none() {
217 result = Some(&chars.authorizations);
218 } else {
219 return Err(km_err!(InvalidKeyBlob, "multiple key characteristics at {:?}", sec_level));
220 }
221 }
222 result.ok_or_else(|| {
223 km_err!(InvalidKeyBlob, "no parameters at security level {:?} found", sec_level)
224 })
225 }
226
227 /// Get the certificate subject from a set of parameters, falling back to a default if not
228 /// specified.
get_cert_subject(params: &[KeyParam]) -> Result<&[u8], Error>229 pub fn get_cert_subject(params: &[KeyParam]) -> Result<&[u8], Error> {
230 Ok(get_opt_tag_value!(params, CertificateSubject)?
231 .map(Vec::as_ref)
232 .unwrap_or(DEFAULT_CERT_SUBJECT))
233 }
234
235 /// Build the parameters that are used as the hidden input to KEK derivation calculations:
236 /// - `ApplicationId(data)` if present
237 /// - `ApplicationData(data)` if present
238 /// - `RootOfTrust(rot)` where `rot` is a hardcoded root of trust
hidden(params: &[KeyParam], rot: &[u8]) -> Result<Vec<KeyParam>, Error>239 pub fn hidden(params: &[KeyParam], rot: &[u8]) -> Result<Vec<KeyParam>, Error> {
240 let mut results = vec_try_with_capacity!(3)?;
241 if let Ok(Some(app_id)) = get_opt_tag_value!(params, ApplicationId) {
242 results.push(KeyParam::ApplicationId(try_to_vec(app_id)?));
243 }
244 if let Ok(Some(app_data)) = get_opt_tag_value!(params, ApplicationData) {
245 results.push(KeyParam::ApplicationData(try_to_vec(app_data)?));
246 }
247 results.push(KeyParam::RootOfTrust(try_to_vec(rot)?));
248 Ok(results)
249 }
250
251 /// Build the set of key characteristics for a key that is about to be generated,
252 /// checking parameter validity along the way. Also return the information needed for key
253 /// generation.
extract_key_gen_characteristics( secure_storage: SecureStorage, params: &[KeyParam], sec_level: SecurityLevel, ) -> Result<(Vec<KeyCharacteristics>, KeyGenInfo), Error>254 pub fn extract_key_gen_characteristics(
255 secure_storage: SecureStorage,
256 params: &[KeyParam],
257 sec_level: SecurityLevel,
258 ) -> Result<(Vec<KeyCharacteristics>, KeyGenInfo), Error> {
259 let keygen_info = match get_algorithm(params)? {
260 Algorithm::Rsa => check_rsa_gen_params(params, sec_level),
261 Algorithm::Ec => check_ec_gen_params(params, sec_level),
262 Algorithm::Aes => check_aes_gen_params(params, sec_level),
263 Algorithm::TripleDes => check_3des_gen_params(params),
264 Algorithm::Hmac => check_hmac_gen_params(params, sec_level),
265 }?;
266 Ok((extract_key_characteristics(secure_storage, params, &[], sec_level)?, keygen_info))
267 }
268
269 /// Build the set of key characteristics for a key that is about to be imported,
270 /// checking parameter validity along the way.
extract_key_import_characteristics( imp: &crypto::Implementation, secure_storage: SecureStorage, params: &[KeyParam], sec_level: SecurityLevel, key_format: KeyFormat, key_data: &[u8], ) -> Result<(Vec<KeyCharacteristics>, KeyMaterial), Error>271 pub fn extract_key_import_characteristics(
272 imp: &crypto::Implementation,
273 secure_storage: SecureStorage,
274 params: &[KeyParam],
275 sec_level: SecurityLevel,
276 key_format: KeyFormat,
277 key_data: &[u8],
278 ) -> Result<(Vec<KeyCharacteristics>, KeyMaterial), Error> {
279 let (deduced_params, key_material) = match get_algorithm(params)? {
280 Algorithm::Rsa => check_rsa_import_params(imp.rsa, params, sec_level, key_format, key_data),
281 Algorithm::Ec => check_ec_import_params(imp.ec, params, sec_level, key_format, key_data),
282 Algorithm::Aes => check_aes_import_params(imp.aes, params, sec_level, key_format, key_data),
283 Algorithm::TripleDes => check_3des_import_params(imp.des, params, key_format, key_data),
284 Algorithm::Hmac => {
285 check_hmac_import_params(imp.hmac, params, sec_level, key_format, key_data)
286 }
287 }?;
288 Ok((
289 extract_key_characteristics(secure_storage, params, &deduced_params, sec_level)?,
290 key_material,
291 ))
292 }
293
294 /// Build the set of key characteristics for a key that is about to be generated or imported,
295 /// checking parameter validity along the way. The `extra_params` argument provides additional
296 /// parameters on top of `params`, such as those deduced from imported key material.
extract_key_characteristics( secure_storage: SecureStorage, params: &[KeyParam], extra_params: &[KeyParam], sec_level: SecurityLevel, ) -> Result<Vec<KeyCharacteristics>, Error>297 fn extract_key_characteristics(
298 secure_storage: SecureStorage,
299 params: &[KeyParam],
300 extra_params: &[KeyParam],
301 sec_level: SecurityLevel,
302 ) -> Result<Vec<KeyCharacteristics>, Error> {
303 // Separately accumulate any characteristics that are policed by Keystore.
304 let mut chars = Vec::new();
305 let mut keystore_chars = Vec::new();
306 for param in params.iter().chain(extra_params) {
307 let tag = param.tag();
308
309 // Input params should not contain anything that KeyMint adds itself.
310 if AUTO_ADDED_CHARACTERISTICS.contains(&tag) {
311 return Err(km_err!(InvalidTag, "KeyMint-added tag included on key generation/import"));
312 }
313
314 if sec_level == SecurityLevel::Strongbox
315 && [Tag::MaxUsesPerBoot, Tag::RollbackResistance].contains(&tag)
316 {
317 // StrongBox does not support tags that require per-key storage.
318 return Err(km_err!(InvalidTag, "tag {:?} not allowed in StrongBox", param.tag()));
319 }
320
321 // UsageCountLimit is peculiar. If its value is > 1, it should be Keystore-enforced.
322 // If its value is = 1, then it is KeyMint-enforced if secure storage is available,
323 // and Keystore-enforced otherwise.
324 if let KeyParam::UsageCountLimit(use_limit) = param {
325 match (use_limit, secure_storage) {
326 (1, SecureStorage::Available) => {
327 chars.try_push(KeyParam::UsageCountLimit(*use_limit))?
328 }
329 (1, SecureStorage::Unavailable) | (_, _) => {
330 keystore_chars.try_push(KeyParam::UsageCountLimit(*use_limit))?
331 }
332 }
333 }
334
335 if KEYMINT_ENFORCED_CHARACTERISTICS.contains(&tag) {
336 chars.try_push(param.clone())?;
337 } else if KEYSTORE_ENFORCED_CHARACTERISTICS.contains(&tag) {
338 keystore_chars.try_push(param.clone())?;
339 } else if tag == Tag::UnlockedDeviceRequired {
340 // `UnlockedDeviceRequired` is policed by both KeyMint and Keystore, so put it in the
341 // KeyMint security level.
342 chars.try_push(param.clone())?;
343 }
344 }
345
346 reject_incompatible_auth(&chars)?;
347
348 // Use the same sort order for tags as was previously used.
349 chars.sort_by(legacy::param_compare);
350 keystore_chars.sort_by(legacy::param_compare);
351
352 let mut result = Vec::new();
353 result.try_push(KeyCharacteristics { security_level: sec_level, authorizations: chars })?;
354 if !keystore_chars.is_empty() {
355 result.try_push(KeyCharacteristics {
356 security_level: SecurityLevel::Keystore,
357 authorizations: keystore_chars,
358 })?;
359 }
360 Ok(result)
361 }
362
363 /// Check that an RSA key size is valid.
check_rsa_key_size(key_size: KeySizeInBits, sec_level: SecurityLevel) -> Result<(), Error>364 fn check_rsa_key_size(key_size: KeySizeInBits, sec_level: SecurityLevel) -> Result<(), Error> {
365 // StrongBox only supports 2048-bit keys.
366 match key_size {
367 KeySizeInBits(512) if sec_level != SecurityLevel::Strongbox => Ok(()),
368 KeySizeInBits(768) if sec_level != SecurityLevel::Strongbox => Ok(()),
369 KeySizeInBits(1024) if sec_level != SecurityLevel::Strongbox => Ok(()),
370 KeySizeInBits(2048) => Ok(()),
371 KeySizeInBits(3072) if sec_level != SecurityLevel::Strongbox => Ok(()),
372 KeySizeInBits(4096) if sec_level != SecurityLevel::Strongbox => Ok(()),
373 _ => Err(km_err!(UnsupportedKeySize, "unsupported KEY_SIZE {:?} bits for RSA", key_size)),
374 }
375 }
376
377 /// Check RSA key generation parameter validity.
check_rsa_gen_params( params: &[KeyParam], sec_level: SecurityLevel, ) -> Result<KeyGenInfo, Error>378 fn check_rsa_gen_params(
379 params: &[KeyParam],
380 sec_level: SecurityLevel,
381 ) -> Result<KeyGenInfo, Error> {
382 // For key generation, size and public exponent must be explicitly specified.
383 let key_size = get_tag_value!(params, KeySize, ErrorCode::UnsupportedKeySize)?;
384 check_rsa_key_size(key_size, sec_level)?;
385 let public_exponent = get_tag_value!(params, RsaPublicExponent, ErrorCode::InvalidArgument)?;
386
387 check_rsa_params(params)?;
388 Ok(KeyGenInfo::Rsa(key_size, public_exponent))
389 }
390
391 /// Check RSA key import parameter validity. Return the key material along with any key generation
392 /// parameters that have been deduced from the key material (but which are not present in the input
393 /// key parameters).
check_rsa_import_params( rsa: &dyn Rsa, params: &[KeyParam], sec_level: SecurityLevel, key_format: KeyFormat, key_data: &[u8], ) -> Result<(Vec<KeyParam>, KeyMaterial), Error>394 fn check_rsa_import_params(
395 rsa: &dyn Rsa,
396 params: &[KeyParam],
397 sec_level: SecurityLevel,
398 key_format: KeyFormat,
399 key_data: &[u8],
400 ) -> Result<(Vec<KeyParam>, KeyMaterial), Error> {
401 // Deduce key size and exponent from import data.
402 if key_format != KeyFormat::Pkcs8 {
403 return Err(km_err!(
404 UnsupportedKeyFormat,
405 "unsupported import format {:?}, expect PKCS8",
406 key_format
407 ));
408 }
409 let (key, key_size, public_exponent) = rsa.import_pkcs8_key(key_data, params)?;
410
411 // If key size or exponent are explicitly specified, they must match. If they were not
412 // specified, we emit them.
413 let mut deduced_chars = Vec::new();
414 match get_opt_tag_value!(params, KeySize)? {
415 Some(param_key_size) => {
416 if *param_key_size != key_size {
417 return Err(km_err!(
418 ImportParameterMismatch,
419 "specified KEY_SIZE {:?} bits != actual key size {:?} for PKCS8 import",
420 param_key_size,
421 key_size
422 ));
423 }
424 }
425 None => deduced_chars.try_push(KeyParam::KeySize(key_size))?,
426 }
427 match get_opt_tag_value!(params, RsaPublicExponent)? {
428 Some(param_public_exponent) => {
429 if *param_public_exponent != public_exponent {
430 return Err(km_err!(
431 ImportParameterMismatch,
432 "specified RSA_PUBLIC_EXPONENT {:?} != actual exponent {:?} for PKCS8 import",
433 param_public_exponent,
434 public_exponent,
435 ));
436 }
437 }
438 None => deduced_chars.try_push(KeyParam::RsaPublicExponent(public_exponent))?,
439 }
440 check_rsa_key_size(key_size, sec_level)?;
441
442 check_rsa_params(params)?;
443 Ok((deduced_chars, key))
444 }
445
446 /// Check the parameter validity for an RSA key that is about to be generated or imported.
check_rsa_params(params: &[KeyParam]) -> Result<(), Error>447 fn check_rsa_params(params: &[KeyParam]) -> Result<(), Error> {
448 let mut seen_attest = false;
449 let mut seen_non_attest = false;
450 for param in params {
451 if let KeyParam::Purpose(purpose) = param {
452 match purpose {
453 KeyPurpose::Sign | KeyPurpose::Decrypt | KeyPurpose::WrapKey => {
454 seen_non_attest = true
455 }
456 KeyPurpose::AttestKey => seen_attest = true,
457 KeyPurpose::Verify | KeyPurpose::Encrypt => {} // public key operations
458 KeyPurpose::AgreeKey => {
459 warn!("Generating RSA key with invalid purpose {:?}", purpose)
460 }
461 }
462 }
463 }
464 if seen_attest && seen_non_attest {
465 return Err(km_err!(
466 IncompatiblePurpose,
467 "keys with ATTEST_KEY must have no other purpose"
468 ));
469 }
470 Ok(())
471 }
472
473 /// Check EC key generation parameter validity.
check_ec_gen_params(params: &[KeyParam], sec_level: SecurityLevel) -> Result<KeyGenInfo, Error>474 fn check_ec_gen_params(params: &[KeyParam], sec_level: SecurityLevel) -> Result<KeyGenInfo, Error> {
475 // For key generation, the curve must be explicitly specified.
476 let ec_curve = get_ec_curve(params)?;
477
478 let purpose = check_ec_params(ec_curve, params, sec_level)?;
479 let keygen_info = match (ec_curve, purpose) {
480 (EcCurve::Curve25519, Some(KeyPurpose::Sign)) => KeyGenInfo::Ed25519,
481 (EcCurve::Curve25519, Some(KeyPurpose::AttestKey)) => KeyGenInfo::Ed25519,
482 (EcCurve::Curve25519, Some(KeyPurpose::AgreeKey)) => KeyGenInfo::X25519,
483 (EcCurve::Curve25519, _) => {
484 return Err(km_err!(
485 IncompatiblePurpose,
486 "curve25519 keys with invalid purpose {:?}",
487 purpose
488 ))
489 }
490 (EcCurve::P224, _) => KeyGenInfo::NistEc(ec::NistCurve::P224),
491 (EcCurve::P256, _) => KeyGenInfo::NistEc(ec::NistCurve::P256),
492 (EcCurve::P384, _) => KeyGenInfo::NistEc(ec::NistCurve::P384),
493 (EcCurve::P521, _) => KeyGenInfo::NistEc(ec::NistCurve::P521),
494 };
495 Ok(keygen_info)
496 }
497
498 /// Find the first purpose value in the parameters.
primary_purpose(params: &[KeyParam]) -> Result<KeyPurpose, Error>499 pub fn primary_purpose(params: &[KeyParam]) -> Result<KeyPurpose, Error> {
500 params
501 .iter()
502 .find_map(
503 |param| if let KeyParam::Purpose(purpose) = param { Some(*purpose) } else { None },
504 )
505 .ok_or_else(|| km_err!(IncompatiblePurpose, "no purpose found for key!"))
506 }
507
508 /// Check EC key import parameter validity. Return the key material along with any key generation
509 /// parameters that have been deduced from the key material (but which are not present in the input
510 /// key parameters).
check_ec_import_params( ec: &dyn Ec, params: &[KeyParam], sec_level: SecurityLevel, key_format: KeyFormat, key_data: &[u8], ) -> Result<(Vec<KeyParam>, KeyMaterial), Error>511 fn check_ec_import_params(
512 ec: &dyn Ec,
513 params: &[KeyParam],
514 sec_level: SecurityLevel,
515 key_format: KeyFormat,
516 key_data: &[u8],
517 ) -> Result<(Vec<KeyParam>, KeyMaterial), Error> {
518 // Curve25519 can be imported as PKCS8 or raw; all other curves must be PKCS8.
519 // If we need to disinguish between Ed25519 and X25519, we need to examine the purpose for the
520 // key -- look for `AgreeKey` as it cannot be combined with other purposes.
521 let (key, curve) = match key_format {
522 KeyFormat::Raw if get_ec_curve(params)? == EcCurve::Curve25519 => {
523 // Raw key import must specify the curve (and the only valid option is Curve25519
524 // currently).
525 if primary_purpose(params)? == KeyPurpose::AgreeKey {
526 (ec.import_raw_x25519_key(key_data, params)?, EcCurve::Curve25519)
527 } else {
528 (ec.import_raw_ed25519_key(key_data, params)?, EcCurve::Curve25519)
529 }
530 }
531 KeyFormat::Pkcs8 => {
532 let key = ec.import_pkcs8_key(key_data, params)?;
533 let curve = match &key {
534 KeyMaterial::Ec(curve, CurveType::Nist, _) => *curve,
535 KeyMaterial::Ec(EcCurve::Curve25519, CurveType::EdDsa, _) => {
536 if primary_purpose(params)? == KeyPurpose::AgreeKey {
537 return Err(km_err!(
538 IncompatiblePurpose,
539 "can't use EdDSA key for key agreement"
540 ));
541 }
542 EcCurve::Curve25519
543 }
544 KeyMaterial::Ec(EcCurve::Curve25519, CurveType::Xdh, _) => {
545 if primary_purpose(params)? != KeyPurpose::AgreeKey {
546 return Err(km_err!(IncompatiblePurpose, "can't use XDH key for signing"));
547 }
548 EcCurve::Curve25519
549 }
550 _ => {
551 return Err(km_err!(
552 ImportParameterMismatch,
553 "unexpected key type from EC import"
554 ))
555 }
556 };
557 (key, curve)
558 }
559 _ => {
560 return Err(km_err!(
561 UnsupportedKeyFormat,
562 "invalid import format ({:?}) for EC key",
563 key_format,
564 ));
565 }
566 };
567
568 // If curve was explicitly specified, it must match. If not specified, populate it in the
569 // deduced characteristics.
570 let mut deduced_chars = Vec::new();
571 match get_opt_tag_value!(params, EcCurve)? {
572 Some(specified_curve) => {
573 if *specified_curve != curve {
574 return Err(km_err!(
575 ImportParameterMismatch,
576 "imported EC key claimed curve {:?} but is {:?}",
577 specified_curve,
578 curve
579 ));
580 }
581 }
582 None => deduced_chars.try_push(KeyParam::EcCurve(curve))?,
583 }
584
585 // If key size was explicitly specified, it must match. If not specified, populate it in the
586 // deduced characteristics.
587 let key_size = ec::curve_to_key_size(curve);
588 match get_opt_tag_value!(params, KeySize)? {
589 Some(param_key_size) => {
590 if *param_key_size != key_size {
591 return Err(km_err!(
592 ImportParameterMismatch,
593 "specified KEY_SIZE {:?} bits != actual key size {:?} for PKCS8 import",
594 param_key_size,
595 key_size
596 ));
597 }
598 }
599 None => deduced_chars.try_push(KeyParam::KeySize(key_size))?,
600 }
601
602 check_ec_params(curve, params, sec_level)?;
603 Ok((deduced_chars, key))
604 }
605
606 /// Check the parameter validity for an EC key that is about to be generated or imported.
check_ec_params( curve: EcCurve, params: &[KeyParam], sec_level: SecurityLevel, ) -> Result<Option<KeyPurpose>, Error>607 fn check_ec_params(
608 curve: EcCurve,
609 params: &[KeyParam],
610 sec_level: SecurityLevel,
611 ) -> Result<Option<KeyPurpose>, Error> {
612 if sec_level == SecurityLevel::Strongbox && curve != EcCurve::P256 {
613 return Err(km_err!(UnsupportedEcCurve, "invalid curve ({:?}) for StrongBox", curve));
614 }
615
616 // Key size is not needed, but if present should match the curve.
617 if let Some(key_size) = get_opt_tag_value!(params, KeySize)? {
618 match curve {
619 EcCurve::P224 if *key_size == KeySizeInBits(224) => {}
620 EcCurve::P256 if *key_size == KeySizeInBits(256) => {}
621 EcCurve::P384 if *key_size == KeySizeInBits(384) => {}
622 EcCurve::P521 if *key_size == KeySizeInBits(521) => {}
623 EcCurve::Curve25519 if *key_size == KeySizeInBits(256) => {}
624 _ => {
625 return Err(km_err!(
626 InvalidArgument,
627 "invalid curve ({:?}) / key size ({:?}) combination",
628 curve,
629 key_size
630 ))
631 }
632 }
633 }
634
635 let mut seen_attest = false;
636 let mut seen_sign = false;
637 let mut seen_agree = false;
638 let mut primary_purpose = None;
639 for param in params {
640 if let KeyParam::Purpose(purpose) = param {
641 match purpose {
642 KeyPurpose::Sign => seen_sign = true,
643 KeyPurpose::AgreeKey => seen_agree = true,
644 KeyPurpose::AttestKey => seen_attest = true,
645 KeyPurpose::Verify => {}
646 _ => warn!("Generating EC key with invalid purpose {:?}", purpose),
647 }
648 if primary_purpose.is_none() {
649 primary_purpose = Some(*purpose);
650 }
651 }
652 }
653 // Keys with Purpose::ATTEST_KEY must have no other purpose.
654 if seen_attest && (seen_sign || seen_agree) {
655 return Err(km_err!(
656 IncompatiblePurpose,
657 "keys with ATTEST_KEY must have no other purpose"
658 ));
659 }
660 // Curve25519 keys must be either signing/attesting keys (Ed25519), or key agreement
661 // keys (X25519), not both.
662 if curve == EcCurve::Curve25519 && seen_agree && (seen_sign || seen_attest) {
663 return Err(km_err!(
664 IncompatiblePurpose,
665 "curve25519 keys must be either SIGN/ATTEST_KEY or AGREE_KEY, not both"
666 ));
667 }
668
669 Ok(primary_purpose)
670 }
671
672 /// Check AES key generation parameter validity.
check_aes_gen_params( params: &[KeyParam], sec_level: SecurityLevel, ) -> Result<KeyGenInfo, Error>673 fn check_aes_gen_params(
674 params: &[KeyParam],
675 sec_level: SecurityLevel,
676 ) -> Result<KeyGenInfo, Error> {
677 // For key generation, the size must be explicitly specified.
678 let key_size = get_tag_value!(params, KeySize, ErrorCode::UnsupportedKeySize)?;
679
680 let keygen_info = match key_size {
681 KeySizeInBits(128) => KeyGenInfo::Aes(aes::Variant::Aes128),
682 KeySizeInBits(256) => KeyGenInfo::Aes(aes::Variant::Aes256),
683 KeySizeInBits(192) if sec_level != SecurityLevel::Strongbox => {
684 KeyGenInfo::Aes(aes::Variant::Aes192)
685 }
686 _ => {
687 return Err(km_err!(
688 UnsupportedKeySize,
689 "unsupported KEY_SIZE {:?} bits for AES",
690 key_size
691 ))
692 }
693 };
694
695 check_aes_params(params)?;
696 Ok(keygen_info)
697 }
698
699 /// Check AES key import parameter validity. Return the key material along with any key generation
700 /// parameters that have been deduced from the key material (but which are not present in the input
701 /// key parameters).
check_aes_import_params( aes: &dyn Aes, params: &[KeyParam], sec_level: SecurityLevel, key_format: KeyFormat, key_data: &[u8], ) -> Result<(Vec<KeyParam>, KeyMaterial), Error>702 fn check_aes_import_params(
703 aes: &dyn Aes,
704 params: &[KeyParam],
705 sec_level: SecurityLevel,
706 key_format: KeyFormat,
707 key_data: &[u8],
708 ) -> Result<(Vec<KeyParam>, KeyMaterial), Error> {
709 require_raw(key_format)?;
710 let (key, key_size) = aes.import_key(key_data, params)?;
711 if key_size == KeySizeInBits(192) && sec_level == SecurityLevel::Strongbox {
712 return Err(km_err!(
713 UnsupportedKeySize,
714 "unsupported KEY_SIZE=192 bits for AES on StrongBox",
715 ));
716 }
717 let deduced_chars = require_matching_key_size(params, key_size)?;
718
719 check_aes_params(params)?;
720 Ok((deduced_chars, key))
721 }
722
723 /// Check the parameter validity for an AES key that is about to be generated or imported.
check_aes_params(params: &[KeyParam]) -> Result<(), Error>724 fn check_aes_params(params: &[KeyParam]) -> Result<(), Error> {
725 let gcm_support = params.iter().any(|p| *p == KeyParam::BlockMode(BlockMode::Gcm));
726 if gcm_support {
727 let min_mac_len = get_tag_value!(params, MinMacLength, ErrorCode::MissingMinMacLength)?;
728 if (min_mac_len % 8 != 0) || !(96..=128).contains(&min_mac_len) {
729 return Err(km_err!(
730 UnsupportedMinMacLength,
731 "unsupported MIN_MAC_LENGTH {} bits",
732 min_mac_len
733 ));
734 }
735 }
736 Ok(())
737 }
738
739 /// Check triple DES key generation parameter validity.
check_3des_gen_params(params: &[KeyParam]) -> Result<KeyGenInfo, Error>740 fn check_3des_gen_params(params: &[KeyParam]) -> Result<KeyGenInfo, Error> {
741 // For key generation, the size (168) must be explicitly specified.
742 let key_size = get_tag_value!(params, KeySize, ErrorCode::UnsupportedKeySize)?;
743 if key_size != KeySizeInBits(168) {
744 return Err(km_err!(
745 UnsupportedKeySize,
746 "unsupported KEY_SIZE {:?} bits for TRIPLE_DES",
747 key_size
748 ));
749 }
750 Ok(KeyGenInfo::TripleDes)
751 }
752
753 /// Check triple DES key import parameter validity. Return the key material along with any key
754 /// generation parameters that have been deduced from the key material (but which are not present in
755 /// the input key parameters).
check_3des_import_params( des: &dyn Des, params: &[KeyParam], key_format: KeyFormat, key_data: &[u8], ) -> Result<(Vec<KeyParam>, KeyMaterial), Error>756 fn check_3des_import_params(
757 des: &dyn Des,
758 params: &[KeyParam],
759 key_format: KeyFormat,
760 key_data: &[u8],
761 ) -> Result<(Vec<KeyParam>, KeyMaterial), Error> {
762 require_raw(key_format)?;
763 let key = des.import_key(key_data, params)?;
764 // If the key size is specified as a parameter, it must be 168. Note that this
765 // is not equal to 8 x 24 (the data size).
766 let deduced_chars = require_matching_key_size(params, des::KEY_SIZE_BITS)?;
767
768 Ok((deduced_chars, key))
769 }
770
771 /// Check HMAC key generation parameter validity.
check_hmac_gen_params( params: &[KeyParam], sec_level: SecurityLevel, ) -> Result<KeyGenInfo, Error>772 fn check_hmac_gen_params(
773 params: &[KeyParam],
774 sec_level: SecurityLevel,
775 ) -> Result<KeyGenInfo, Error> {
776 // For key generation the size must be explicitly specified.
777 let key_size = get_tag_value!(params, KeySize, ErrorCode::UnsupportedKeySize)?;
778 check_hmac_params(params, sec_level, key_size)?;
779 Ok(KeyGenInfo::Hmac(key_size))
780 }
781
782 /// Build the set of key characteristics for an HMAC key that is about to be imported,
783 /// checking parameter validity along the way.
check_hmac_import_params( hmac: &dyn Hmac, params: &[KeyParam], sec_level: SecurityLevel, key_format: KeyFormat, key_data: &[u8], ) -> Result<(Vec<KeyParam>, KeyMaterial), Error>784 fn check_hmac_import_params(
785 hmac: &dyn Hmac,
786 params: &[KeyParam],
787 sec_level: SecurityLevel,
788 key_format: KeyFormat,
789 key_data: &[u8],
790 ) -> Result<(Vec<KeyParam>, KeyMaterial), Error> {
791 require_raw(key_format)?;
792 let (key, key_size) = hmac.import_key(key_data, params)?;
793 let deduced_chars = require_matching_key_size(params, key_size)?;
794
795 check_hmac_params(params, sec_level, key_size)?;
796 Ok((deduced_chars, key))
797 }
798
799 /// Check the parameter validity for an HMAC key that is about to be generated or imported.
check_hmac_params( params: &[KeyParam], sec_level: SecurityLevel, key_size: KeySizeInBits, ) -> Result<(), Error>800 fn check_hmac_params(
801 params: &[KeyParam],
802 sec_level: SecurityLevel,
803 key_size: KeySizeInBits,
804 ) -> Result<(), Error> {
805 if sec_level == SecurityLevel::Strongbox {
806 hmac::valid_strongbox_hal_size(key_size)?;
807 } else {
808 hmac::valid_hal_size(key_size)?;
809 }
810 let digest = get_tag_value!(params, Digest, ErrorCode::UnsupportedDigest)?;
811 if digest == Digest::None {
812 return Err(km_err!(UnsupportedDigest, "unsupported digest {:?}", digest));
813 }
814
815 let min_mac_len = get_tag_value!(params, MinMacLength, ErrorCode::MissingMinMacLength)?;
816 if (min_mac_len % 8 != 0) || !(64..=512).contains(&min_mac_len) {
817 return Err(km_err!(
818 UnsupportedMinMacLength,
819 "unsupported MIN_MAC_LENGTH {:?} bits",
820 min_mac_len
821 ));
822 }
823 Ok(())
824 }
825
826 /// Check for `KeyFormat::RAW`.
require_raw(key_format: KeyFormat) -> Result<(), Error>827 fn require_raw(key_format: KeyFormat) -> Result<(), Error> {
828 if key_format != KeyFormat::Raw {
829 return Err(km_err!(
830 UnsupportedKeyFormat,
831 "unsupported import format {:?}, expect RAW",
832 key_format
833 ));
834 }
835 Ok(())
836 }
837
838 /// Check or populate a `Tag::KEY_SIZE` value.
require_matching_key_size( params: &[KeyParam], key_size: KeySizeInBits, ) -> Result<Vec<KeyParam>, Error>839 fn require_matching_key_size(
840 params: &[KeyParam],
841 key_size: KeySizeInBits,
842 ) -> Result<Vec<KeyParam>, Error> {
843 let mut deduced_chars = Vec::new();
844 match get_opt_tag_value!(params, KeySize)? {
845 Some(param_key_size) => {
846 if *param_key_size != key_size {
847 return Err(km_err!(
848 ImportParameterMismatch,
849 "specified KEY_SIZE {:?} bits != actual key size {:?}",
850 param_key_size,
851 key_size
852 ));
853 }
854 }
855 None => deduced_chars.try_push(KeyParam::KeySize(key_size))?,
856 }
857 Ok(deduced_chars)
858 }
859
860 /// Return an error if any of the `exclude` tags are found in `params`.
reject_tags(params: &[KeyParam], exclude: &[Tag]) -> Result<(), Error>861 fn reject_tags(params: &[KeyParam], exclude: &[Tag]) -> Result<(), Error> {
862 for param in params {
863 if exclude.contains(¶m.tag()) {
864 return Err(km_err!(InvalidTag, "tag {:?} not allowed", param.tag()));
865 }
866 }
867 Ok(())
868 }
869
870 /// Return an error if non-None padding found.
reject_some_padding(params: &[KeyParam]) -> Result<(), Error>871 fn reject_some_padding(params: &[KeyParam]) -> Result<(), Error> {
872 if let Some(padding) = get_opt_tag_value!(params, Padding)? {
873 if *padding != PaddingMode::None {
874 return Err(km_err!(InvalidTag, "padding {:?} not allowed", padding));
875 }
876 }
877 Ok(())
878 }
879
880 /// Return an error if non-None digest found.
reject_some_digest(params: &[KeyParam]) -> Result<(), Error>881 fn reject_some_digest(params: &[KeyParam]) -> Result<(), Error> {
882 if let Some(digest) = get_opt_tag_value!(params, Digest)? {
883 if *digest != Digest::None {
884 return Err(km_err!(InvalidTag, "digest {:?} not allowed", digest));
885 }
886 }
887 Ok(())
888 }
889
890 /// Reject incompatible combinations of authentication tags.
reject_incompatible_auth(params: &[KeyParam]) -> Result<(), Error>891 fn reject_incompatible_auth(params: &[KeyParam]) -> Result<(), Error> {
892 let mut seen_user_secure_id = false;
893 let mut seen_auth_type = false;
894 let mut seen_no_auth = false;
895
896 for param in params {
897 match param {
898 KeyParam::UserSecureId(_sid) => seen_user_secure_id = true,
899 KeyParam::UserAuthType(_atype) => seen_auth_type = true,
900 KeyParam::NoAuthRequired => seen_no_auth = true,
901 _ => {}
902 }
903 }
904
905 if seen_no_auth {
906 if seen_user_secure_id {
907 return Err(km_err!(InvalidTag, "found both NO_AUTH_REQUIRED and USER_SECURE_ID"));
908 }
909 if seen_auth_type {
910 return Err(km_err!(InvalidTag, "found both NO_AUTH_REQUIRED and USER_AUTH_TYPE"));
911 }
912 }
913 if seen_user_secure_id && !seen_auth_type {
914 return Err(km_err!(InvalidTag, "found USER_SECURE_ID but no USER_AUTH_TYPE"));
915 }
916 Ok(())
917 }
918
919 /// Indication of which parameters on a `begin` need to be checked against key authorizations.
920 struct BeginParamsToCheck {
921 block_mode: bool,
922 padding: bool,
923 digest: bool,
924 mgf_digest: bool,
925 }
926
927 /// Check that an operation with the given `purpose` and `params` can validly be started
928 /// using a key with characteristics `chars`.
check_begin_params( chars: &[KeyParam], purpose: KeyPurpose, params: &[KeyParam], ) -> Result<(), Error>929 pub fn check_begin_params(
930 chars: &[KeyParam],
931 purpose: KeyPurpose,
932 params: &[KeyParam],
933 ) -> Result<(), Error> {
934 // General checks for all algorithms.
935 let algo = get_algorithm(chars)?;
936 let valid_purpose = matches!(
937 (algo, purpose),
938 (Algorithm::Aes, KeyPurpose::Encrypt)
939 | (Algorithm::Aes, KeyPurpose::Decrypt)
940 | (Algorithm::TripleDes, KeyPurpose::Encrypt)
941 | (Algorithm::TripleDes, KeyPurpose::Decrypt)
942 | (Algorithm::Hmac, KeyPurpose::Sign)
943 | (Algorithm::Hmac, KeyPurpose::Verify)
944 | (Algorithm::Ec, KeyPurpose::Sign)
945 | (Algorithm::Ec, KeyPurpose::AttestKey)
946 | (Algorithm::Ec, KeyPurpose::AgreeKey)
947 | (Algorithm::Rsa, KeyPurpose::Sign)
948 | (Algorithm::Rsa, KeyPurpose::Decrypt)
949 | (Algorithm::Rsa, KeyPurpose::AttestKey)
950 );
951 if !valid_purpose {
952 return Err(km_err!(
953 UnsupportedPurpose,
954 "invalid purpose {:?} for {:?} key",
955 purpose,
956 algo
957 ));
958 }
959 if !contains_tag_value!(chars, Purpose, purpose) {
960 return Err(km_err!(
961 IncompatiblePurpose,
962 "purpose {:?} not in key characteristics",
963 purpose
964 ));
965 }
966 if get_bool_tag_value!(chars, StorageKey)? {
967 return Err(km_err!(StorageKeyUnsupported, "attempt to use storage key",));
968 }
969 let nonce = get_opt_tag_value!(params, Nonce)?;
970 if get_bool_tag_value!(chars, CallerNonce)? {
971 // Caller-provided nonces are allowed.
972 } else if nonce.is_some() && purpose == KeyPurpose::Encrypt {
973 return Err(km_err!(CallerNonceProhibited, "caller nonce not allowed for encryption"));
974 }
975
976 // Further algorithm-specific checks.
977 let check = match algo {
978 Algorithm::Rsa => check_begin_rsa_params(chars, purpose, params),
979 Algorithm::Ec => check_begin_ec_params(chars, purpose, params),
980 Algorithm::Aes => check_begin_aes_params(chars, params, nonce.map(|v| v.as_ref())),
981 Algorithm::TripleDes => check_begin_3des_params(params, nonce.map(|v| v.as_ref())),
982 Algorithm::Hmac => check_begin_hmac_params(chars, purpose, params),
983 }?;
984
985 // For various parameters, if they are specified in the begin parameters and they
986 // are relevant for the algorithm, then the same value must also exist in the key
987 // characteristics. Also, there can be only one distinct value in the parameters.
988 if check.block_mode {
989 if let Some(bmode) = get_opt_tag_value!(params, BlockMode, UnsupportedBlockMode)? {
990 if !contains_tag_value!(chars, BlockMode, *bmode) {
991 return Err(km_err!(
992 IncompatibleBlockMode,
993 "block mode {:?} not in key characteristics {:?}",
994 bmode,
995 chars,
996 ));
997 }
998 }
999 }
1000 if check.padding {
1001 if let Some(pmode) = get_opt_tag_value!(params, Padding, UnsupportedPaddingMode)? {
1002 if !contains_tag_value!(chars, Padding, *pmode) {
1003 return Err(km_err!(
1004 IncompatiblePaddingMode,
1005 "padding mode {:?} not in key characteristics {:?}",
1006 pmode,
1007 chars,
1008 ));
1009 }
1010 }
1011 }
1012 if check.digest {
1013 if let Some(digest) = get_opt_tag_value!(params, Digest, UnsupportedDigest)? {
1014 if !contains_tag_value!(chars, Digest, *digest) {
1015 return Err(km_err!(
1016 IncompatibleDigest,
1017 "digest {:?} not in key characteristics",
1018 digest,
1019 ));
1020 }
1021 }
1022 }
1023 if check.mgf_digest {
1024 let mut mgf_digest_to_find =
1025 get_opt_tag_value!(params, RsaOaepMgfDigest, UnsupportedMgfDigest)?;
1026
1027 let chars_have_mgf_digest =
1028 chars.iter().any(|param| matches!(param, KeyParam::RsaOaepMgfDigest(_)));
1029 if chars_have_mgf_digest && mgf_digest_to_find.is_none() {
1030 // The key characteristics include an explicit set of MGF digests, but the begin()
1031 // operation is using the default SHA1. Check that this default is in the
1032 // characteristics.
1033 mgf_digest_to_find = Some(&Digest::Sha1);
1034 }
1035
1036 if let Some(mgf_digest) = mgf_digest_to_find {
1037 if !contains_tag_value!(chars, RsaOaepMgfDigest, *mgf_digest) {
1038 return Err(km_err!(
1039 IncompatibleMgfDigest,
1040 "MGF digest {:?} not in key characteristics",
1041 mgf_digest,
1042 ));
1043 }
1044 }
1045 }
1046 Ok(())
1047 }
1048
1049 /// Indicate whether a [`KeyPurpose`] is for encryption/decryption.
for_encryption(purpose: KeyPurpose) -> bool1050 fn for_encryption(purpose: KeyPurpose) -> bool {
1051 purpose == KeyPurpose::Encrypt
1052 || purpose == KeyPurpose::Decrypt
1053 || purpose == KeyPurpose::WrapKey
1054 }
1055
1056 /// Indicate whether a [`KeyPurpose`] is for signing.
for_signing(purpose: KeyPurpose) -> bool1057 fn for_signing(purpose: KeyPurpose) -> bool {
1058 purpose == KeyPurpose::Sign
1059 }
1060
1061 /// Check that an RSA operation with the given `purpose` and `params` can validly be started
1062 /// using a key with characteristics `chars`.
check_begin_rsa_params( chars: &[KeyParam], purpose: KeyPurpose, params: &[KeyParam], ) -> Result<BeginParamsToCheck, Error>1063 fn check_begin_rsa_params(
1064 chars: &[KeyParam],
1065 purpose: KeyPurpose,
1066 params: &[KeyParam],
1067 ) -> Result<BeginParamsToCheck, Error> {
1068 let padding = get_padding_mode(params)?;
1069 let mut digest = None;
1070 if for_signing(purpose) || (for_encryption(purpose) && padding == PaddingMode::RsaOaep) {
1071 digest = Some(get_digest(params)?);
1072 }
1073 if for_signing(purpose) && padding == PaddingMode::None && digest != Some(Digest::None) {
1074 return Err(km_err!(
1075 IncompatibleDigest,
1076 "unpadded RSA sign requires Digest::None not {:?}",
1077 digest
1078 ));
1079 }
1080 match padding {
1081 PaddingMode::None => {}
1082 PaddingMode::RsaOaep if for_encryption(purpose) => {
1083 if digest.is_none() || digest == Some(Digest::None) {
1084 return Err(km_err!(IncompatibleDigest, "digest required for RSA-OAEP"));
1085 }
1086 let mgf_digest = get_mgf_digest(params)?;
1087 if mgf_digest == Digest::None {
1088 return Err(km_err!(
1089 UnsupportedMgfDigest,
1090 "MGF digest cannot be NONE for RSA-OAEP"
1091 ));
1092 }
1093 }
1094 PaddingMode::RsaPss if for_signing(purpose) => {
1095 if let Some(digest) = digest {
1096 let key_size_bits = get_tag_value!(chars, KeySize, ErrorCode::InvalidArgument)?;
1097 let d = digest_len(digest)?;
1098 if key_size_bits < KeySizeInBits(2 * d + 9) {
1099 return Err(km_err!(
1100 IncompatibleDigest,
1101 "key size {:?} < 2*8*D={} + 9",
1102 key_size_bits,
1103 d
1104 ));
1105 }
1106 } else {
1107 return Err(km_err!(IncompatibleDigest, "digest required for RSA-PSS"));
1108 }
1109 }
1110 PaddingMode::RsaPkcs115Encrypt if for_encryption(purpose) => {
1111 if digest.is_some() && digest != Some(Digest::None) {
1112 warn!(
1113 "ignoring digest {:?} provided for PKCS#1 v1.5 encryption/decryption",
1114 digest
1115 );
1116 }
1117 }
1118 PaddingMode::RsaPkcs115Sign if for_signing(purpose) => {
1119 if digest.is_none() {
1120 return Err(km_err!(IncompatibleDigest, "digest required for RSA-PKCS_1_5_SIGN"));
1121 }
1122 }
1123 _ => {
1124 return Err(km_err!(
1125 UnsupportedPaddingMode,
1126 "purpose {:?} incompatible with padding {:?}",
1127 purpose,
1128 padding
1129 ))
1130 }
1131 }
1132
1133 Ok(BeginParamsToCheck { block_mode: false, padding: true, digest: true, mgf_digest: true })
1134 }
1135
1136 /// Check that an EC operation with the given `purpose` and `params` can validly be started
1137 /// using a key with characteristics `chars`.
check_begin_ec_params( chars: &[KeyParam], purpose: KeyPurpose, params: &[KeyParam], ) -> Result<BeginParamsToCheck, Error>1138 fn check_begin_ec_params(
1139 chars: &[KeyParam],
1140 purpose: KeyPurpose,
1141 params: &[KeyParam],
1142 ) -> Result<BeginParamsToCheck, Error> {
1143 let curve = get_ec_curve(chars)?;
1144 if purpose == KeyPurpose::Sign {
1145 let digest = get_digest(params)?;
1146 if digest == Digest::Md5 {
1147 return Err(km_err!(UnsupportedDigest, "Digest::MD5 unsupported for EC signing"));
1148 }
1149 if curve == EcCurve::Curve25519 && digest != Digest::None {
1150 return Err(km_err!(
1151 UnsupportedDigest,
1152 "Ed25519 only supports Digest::None not {:?}",
1153 digest
1154 ));
1155 }
1156 }
1157 Ok(BeginParamsToCheck { block_mode: false, padding: false, digest: true, mgf_digest: false })
1158 }
1159
1160 /// Check that an AES operation with the given `purpose` and `params` can validly be started
1161 /// using a key with characteristics `chars`.
check_begin_aes_params( chars: &[KeyParam], params: &[KeyParam], caller_nonce: Option<&[u8]>, ) -> Result<BeginParamsToCheck, Error>1162 fn check_begin_aes_params(
1163 chars: &[KeyParam],
1164 params: &[KeyParam],
1165 caller_nonce: Option<&[u8]>,
1166 ) -> Result<BeginParamsToCheck, Error> {
1167 reject_tags(params, &[Tag::RsaOaepMgfDigest])?;
1168 reject_some_digest(params)?;
1169 let bmode = get_block_mode(params)?;
1170 let padding = get_padding_mode(params)?;
1171
1172 if bmode == BlockMode::Gcm {
1173 let mac_len = get_tag_value!(params, MacLength, ErrorCode::MissingMacLength)?;
1174 if mac_len % 8 != 0 || mac_len > 128 {
1175 return Err(km_err!(UnsupportedMacLength, "invalid mac len {}", mac_len));
1176 }
1177 let min_mac_len = get_tag_value!(chars, MinMacLength, ErrorCode::MissingMinMacLength)?;
1178 if mac_len < min_mac_len {
1179 return Err(km_err!(
1180 InvalidMacLength,
1181 "mac len {} less than min {}",
1182 mac_len,
1183 min_mac_len
1184 ));
1185 }
1186 }
1187 match bmode {
1188 BlockMode::Gcm | BlockMode::Ctr => match padding {
1189 PaddingMode::None => {}
1190 _ => {
1191 return Err(km_err!(
1192 IncompatiblePaddingMode,
1193 "padding {:?} not valid for AES GCM/CTR",
1194 padding
1195 ))
1196 }
1197 },
1198 BlockMode::Ecb | BlockMode::Cbc => match padding {
1199 PaddingMode::None | PaddingMode::Pkcs7 => {}
1200 _ => {
1201 return Err(km_err!(
1202 IncompatiblePaddingMode,
1203 "padding {:?} not valid for AES GCM/CTR",
1204 padding
1205 ))
1206 }
1207 },
1208 }
1209
1210 if let Some(nonce) = caller_nonce {
1211 match bmode {
1212 BlockMode::Cbc if nonce.len() == 16 => {}
1213 BlockMode::Ctr if nonce.len() == 16 => {}
1214 BlockMode::Gcm if nonce.len() == 12 => {}
1215 _ => {
1216 return Err(km_err!(
1217 InvalidNonce,
1218 "invalid caller nonce len {} for {:?}",
1219 nonce.len(),
1220 bmode
1221 ))
1222 }
1223 }
1224 }
1225 Ok(BeginParamsToCheck { block_mode: true, padding: true, digest: false, mgf_digest: false })
1226 }
1227
1228 /// Check that a 3-DES operation with the given `purpose` and `params` can validly be started
1229 /// using a key with characteristics `chars`.
check_begin_3des_params( params: &[KeyParam], caller_nonce: Option<&[u8]>, ) -> Result<BeginParamsToCheck, Error>1230 fn check_begin_3des_params(
1231 params: &[KeyParam],
1232 caller_nonce: Option<&[u8]>,
1233 ) -> Result<BeginParamsToCheck, Error> {
1234 reject_tags(params, &[Tag::RsaOaepMgfDigest])?;
1235 reject_some_digest(params)?;
1236 let bmode = get_block_mode(params)?;
1237 let _padding = get_padding_mode(params)?;
1238
1239 match bmode {
1240 BlockMode::Cbc | BlockMode::Ecb => {}
1241 _ => {
1242 return Err(km_err!(UnsupportedBlockMode, "block mode {:?} not valid for 3-DES", bmode))
1243 }
1244 }
1245
1246 if let Some(nonce) = caller_nonce {
1247 match bmode {
1248 BlockMode::Cbc if nonce.len() == 8 => {}
1249 _ => {
1250 return Err(km_err!(
1251 InvalidNonce,
1252 "invalid caller nonce len {} for {:?}",
1253 nonce.len(),
1254 bmode
1255 ))
1256 }
1257 }
1258 }
1259 Ok(BeginParamsToCheck { block_mode: true, padding: true, digest: false, mgf_digest: false })
1260 }
1261
1262 /// Check that an HMAC operation with the given `purpose` and `params` can validly be started
1263 /// using a key with characteristics `chars`.
check_begin_hmac_params( chars: &[KeyParam], purpose: KeyPurpose, params: &[KeyParam], ) -> Result<BeginParamsToCheck, Error>1264 fn check_begin_hmac_params(
1265 chars: &[KeyParam],
1266 purpose: KeyPurpose,
1267 params: &[KeyParam],
1268 ) -> Result<BeginParamsToCheck, Error> {
1269 reject_tags(params, &[Tag::BlockMode, Tag::RsaOaepMgfDigest])?;
1270 reject_some_padding(params)?;
1271 let digest = get_digest(params)?;
1272 if purpose == KeyPurpose::Sign {
1273 let mac_len = get_tag_value!(params, MacLength, ErrorCode::MissingMacLength)?;
1274 if mac_len % 8 != 0 || mac_len > digest_len(digest)? {
1275 return Err(km_err!(UnsupportedMacLength, "invalid mac len {}", mac_len));
1276 }
1277 let min_mac_len = get_tag_value!(chars, MinMacLength, ErrorCode::MissingMinMacLength)?;
1278 if mac_len < min_mac_len {
1279 return Err(km_err!(
1280 InvalidMacLength,
1281 "mac len {} less than min {}",
1282 mac_len,
1283 min_mac_len
1284 ));
1285 }
1286 }
1287
1288 Ok(BeginParamsToCheck { block_mode: false, padding: false, digest: true, mgf_digest: false })
1289 }
1290
1291 /// Return the length in bits of a [`Digest`] function.
digest_len(digest: Digest) -> Result<u32, Error>1292 pub fn digest_len(digest: Digest) -> Result<u32, Error> {
1293 match digest {
1294 Digest::Md5 => Ok(128),
1295 Digest::Sha1 => Ok(160),
1296 Digest::Sha224 => Ok(224),
1297 Digest::Sha256 => Ok(256),
1298 Digest::Sha384 => Ok(384),
1299 Digest::Sha512 => Ok(512),
1300 _ => Err(km_err!(IncompatibleDigest, "invalid digest {:?}", digest)),
1301 }
1302 }
1303
1304 /// Check the required key params for an RSA wrapping key used in secure import and return the
1305 /// [`DecryptionMode`] constructed from the processed key characteristics.
check_rsa_wrapping_key_params( chars: &[KeyParam], params: &[KeyParam], ) -> Result<DecryptionMode, Error>1306 pub fn check_rsa_wrapping_key_params(
1307 chars: &[KeyParam],
1308 params: &[KeyParam],
1309 ) -> Result<DecryptionMode, Error> {
1310 // Check the purpose of the wrapping key
1311 if !contains_tag_value!(chars, Purpose, KeyPurpose::WrapKey) {
1312 return Err(km_err!(IncompatiblePurpose, "no wrap key purpose for the wrapping key"));
1313 }
1314 let padding_mode = get_tag_value!(params, Padding, ErrorCode::IncompatiblePaddingMode)?;
1315 if padding_mode != PaddingMode::RsaOaep {
1316 return Err(km_err!(
1317 IncompatiblePaddingMode,
1318 "invalid padding mode {:?} for RSA wrapping key",
1319 padding_mode
1320 ));
1321 }
1322 let msg_digest = get_tag_value!(params, Digest, ErrorCode::IncompatibleDigest)?;
1323 if msg_digest != Digest::Sha256 {
1324 return Err(km_err!(
1325 IncompatibleDigest,
1326 "invalid digest {:?} for RSA wrapping key",
1327 padding_mode
1328 ));
1329 }
1330 let opt_mgf_digest = get_opt_tag_value!(params, RsaOaepMgfDigest)?;
1331 if opt_mgf_digest == Some(&Digest::None) {
1332 return Err(km_err!(UnsupportedMgfDigest, "MGF digest cannot be NONE for RSA-OAEP"));
1333 }
1334
1335 if !contains_tag_value!(chars, Padding, padding_mode) {
1336 return Err(km_err!(
1337 IncompatiblePaddingMode,
1338 "padding mode {:?} not in key characteristics {:?}",
1339 padding_mode,
1340 chars,
1341 ));
1342 }
1343 if !contains_tag_value!(chars, Digest, msg_digest) {
1344 return Err(km_err!(
1345 IncompatibleDigest,
1346 "digest {:?} not in key characteristics {:?}",
1347 msg_digest,
1348 chars,
1349 ));
1350 }
1351
1352 if let Some(mgf_digest) = opt_mgf_digest {
1353 // MGF digest explicitly specified, check it is in key characteristics.
1354 if !contains_tag_value!(chars, RsaOaepMgfDigest, *mgf_digest) {
1355 return Err(km_err!(
1356 IncompatibleDigest,
1357 "MGF digest {:?} not in key characteristics {:?}",
1358 mgf_digest,
1359 chars,
1360 ));
1361 }
1362 }
1363 let mgf_digest = opt_mgf_digest.unwrap_or(&Digest::Sha1);
1364
1365 let rsa_oaep_decrypt_mode = DecryptionMode::OaepPadding { msg_digest, mgf_digest: *mgf_digest };
1366 Ok(rsa_oaep_decrypt_mode)
1367 }
1368
1369 /// Calculate the [Luhn checksum](https://en.wikipedia.org/wiki/Luhn_algorithm) of the given number.
luhn_checksum(mut val: u64) -> u641370 fn luhn_checksum(mut val: u64) -> u64 {
1371 let mut ii = 0;
1372 let mut sum_digits = 0;
1373 while val != 0 {
1374 let curr_digit = val % 10;
1375 let multiplier = if ii % 2 == 0 { 2 } else { 1 };
1376 let digit_multiplied = curr_digit * multiplier;
1377 sum_digits += (digit_multiplied % 10) + (digit_multiplied / 10);
1378 val /= 10;
1379 ii += 1;
1380 }
1381 (10 - (sum_digits % 10)) % 10
1382 }
1383
1384 /// Derive an IMEI value from a first IMEI value, by incrementing by one and re-calculating
1385 /// the Luhn checksum. Return an empty vector on any failure.
increment_imei(imei: &[u8]) -> Vec<u8>1386 pub fn increment_imei(imei: &[u8]) -> Vec<u8> {
1387 if imei.is_empty() {
1388 info!("empty IMEI");
1389 return Vec::new();
1390 }
1391
1392 // Expect ASCII digits.
1393 let imei: &str = match core::str::from_utf8(imei) {
1394 Ok(v) => v,
1395 Err(_) => {
1396 warn!("IMEI is not UTF-8");
1397 return Vec::new();
1398 }
1399 };
1400 let imei: u64 = match imei.parse() {
1401 Ok(v) => v,
1402 Err(_) => {
1403 warn!("IMEI is not numeric");
1404 return Vec::new();
1405 }
1406 };
1407
1408 // Drop trailing checksum digit, increment, and restore checksum.
1409 let imei2 = (imei / 10) + 1;
1410 let imei2 = (imei2 * 10) + luhn_checksum(imei2);
1411
1412 // Convert back to bytes.
1413 alloc::format!("{}", imei2).into_bytes()
1414 }
1415