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