1 // Copyright 2020, 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 //! Provide a wrapper around a KeyMint device that allows up-level features to
16 //! be emulated on back-level devices.
17 
18 use crate::ks_err;
19 use crate::error::{map_binder_status, map_binder_status_code, into_logged_binder, Error, ErrorCode};
20 use android_hardware_security_keymint::binder::{BinderFeatures, StatusCode, Strong};
21 use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::TimeStampToken::TimeStampToken;
22 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
23     AttestationKey::AttestationKey, BeginResult::BeginResult, EcCurve::EcCurve,
24     HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::BnKeyMintDevice,
25     IKeyMintDevice::IKeyMintDevice, KeyCharacteristics::KeyCharacteristics,
26     KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat,
27     KeyMintHardwareInfo::KeyMintHardwareInfo, KeyParameter::KeyParameter,
28     KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
29     Tag::Tag,
30 };
31 use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
32 use anyhow::Context;
33 use keystore2_crypto::{hmac_sha256, HMAC_SHA256_LEN};
34 
35 /// Magic prefix used by the km_compat C++ code to mark a key that is owned by an
36 /// underlying Keymaster hardware device that has been wrapped by km_compat. (The
37 /// final zero byte indicates that the blob is not software emulated.)
38 pub const KEYMASTER_BLOB_HW_PREFIX: &[u8] = b"pKMblob\x00";
39 
40 /// Magic prefix used by the km_compat C++ code to mark a key that is owned by an
41 /// software emulation device that has been wrapped by km_compat. (The final one
42 /// byte indicates that the blob is software emulated.)
43 pub const KEYMASTER_BLOB_SW_PREFIX: &[u8] = b"pKMblob\x01";
44 
45 /// Key data associated with key generation/import.
46 #[derive(Debug, PartialEq, Eq)]
47 pub enum KeyImportData<'a> {
48     None,
49     Pkcs8(&'a [u8]),
50     Raw(&'a [u8]),
51 }
52 
53 impl<'a> KeyImportData<'a> {
54     /// Translate import parameters into a `KeyImportData` instance.
new(key_format: KeyFormat, key_data: &'a [u8]) -> binder::Result<Self>55     fn new(key_format: KeyFormat, key_data: &'a [u8]) -> binder::Result<Self> {
56         match key_format {
57             KeyFormat::PKCS8 => Ok(KeyImportData::Pkcs8(key_data)),
58             KeyFormat::RAW => Ok(KeyImportData::Raw(key_data)),
59             _ => Err(binder::Status::new_service_specific_error(
60                 ErrorCode::UNSUPPORTED_KEY_FORMAT.0,
61                 None,
62             )),
63         }
64     }
65 }
66 
67 /// A key blob that may be software-emulated or may be directly produced by an
68 /// underlying device.  In either variant the inner data is the keyblob itself,
69 /// as seen by the relevant device.
70 #[derive(Debug, PartialEq, Eq)]
71 pub enum KeyBlob<'a> {
72     Raw(&'a [u8]),
73     Wrapped(&'a [u8]),
74 }
75 
76 /// Trait for detecting that software emulation of a current-version KeyMint
77 /// feature is required for a back-level KeyMint implementation.
78 pub trait EmulationDetector: Send + Sync {
79     /// Indicate whether software emulation is required for key
80     /// generation/import using the provided parameters.
emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool81     fn emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool;
82 }
83 
84 const KEYBLOB_PREFIX: &[u8] = b"SoftKeyMintForV1Blob";
85 const KEYBLOB_HMAC_KEY: &[u8] = b"SoftKeyMintForV1HMACKey";
86 
87 /// Wrap the provided keyblob:
88 /// - prefix it with an identifier specific to this wrapper
89 /// - suffix it with an HMAC tag, using the [`KEYBLOB_HMAC_KEY`] and `keyblob`.
wrap_keyblob(keyblob: &[u8]) -> anyhow::Result<Vec<u8>>90 fn wrap_keyblob(keyblob: &[u8]) -> anyhow::Result<Vec<u8>> {
91     let mut result = Vec::with_capacity(KEYBLOB_PREFIX.len() + keyblob.len() + HMAC_SHA256_LEN);
92     result.extend_from_slice(KEYBLOB_PREFIX);
93     result.extend_from_slice(keyblob);
94     let tag = hmac_sha256(KEYBLOB_HMAC_KEY, keyblob)
95         .context(ks_err!("failed to calculate HMAC-SHA256"))?;
96     result.extend_from_slice(&tag);
97     Ok(result)
98 }
99 
100 /// Return an unwrapped version of the provided `keyblob`, which may or may
101 /// not be associated with the software emulation.
unwrap_keyblob(keyblob: &[u8]) -> KeyBlob102 pub fn unwrap_keyblob(keyblob: &[u8]) -> KeyBlob {
103     if !keyblob.starts_with(KEYBLOB_PREFIX) {
104         return KeyBlob::Raw(keyblob);
105     }
106     let without_prefix = &keyblob[KEYBLOB_PREFIX.len()..];
107     if without_prefix.len() < HMAC_SHA256_LEN {
108         return KeyBlob::Raw(keyblob);
109     }
110     let (inner_keyblob, want_tag) = without_prefix.split_at(without_prefix.len() - HMAC_SHA256_LEN);
111     let got_tag = match hmac_sha256(KEYBLOB_HMAC_KEY, inner_keyblob) {
112         Ok(tag) => tag,
113         Err(e) => {
114             log::error!("Error calculating HMAC-SHA256 for keyblob unwrap: {:?}", e);
115             return KeyBlob::Raw(keyblob);
116         }
117     };
118     // Comparison does not need to be constant-time here.
119     if want_tag == got_tag {
120         KeyBlob::Wrapped(inner_keyblob)
121     } else {
122         KeyBlob::Raw(keyblob)
123     }
124 }
125 
126 /// Wrapper around a real device that implements a back-level version of
127 /// `IKeyMintDevice`
128 pub struct BacklevelKeyMintWrapper<T: EmulationDetector> {
129     /// The `real` device implements some earlier version of `IKeyMintDevice`
130     real: Strong<dyn IKeyMintDevice>,
131     /// The `soft`ware device implements the current version of `IKeyMintDevice`
132     soft: Strong<dyn IKeyMintDevice>,
133     /// Detector for operations that are not supported by the earlier version of
134     /// `IKeyMintDevice`. Or possibly a large flightless bird, who can tell.
135     emu: T,
136 }
137 
138 impl<T> BacklevelKeyMintWrapper<T>
139 where
140     T: EmulationDetector + 'static,
141 {
142     /// Create a wrapper around the provided back-level KeyMint device, so that
143     /// software emulation can be performed for any current-version features not
144     /// provided by the real device.
wrap( emu: T, real: Strong<dyn IKeyMintDevice>, ) -> anyhow::Result<Strong<dyn IKeyMintDevice>>145     pub fn wrap(
146         emu: T,
147         real: Strong<dyn IKeyMintDevice>,
148     ) -> anyhow::Result<Strong<dyn IKeyMintDevice>> {
149         // This is a no-op if it was called before.
150         keystore2_km_compat::add_keymint_device_service();
151 
152         let keystore_compat_service: Strong<dyn IKeystoreCompatService> =
153             map_binder_status_code(binder::get_interface("android.security.compat"))
154                 .context(ks_err!("Trying to connect to compat service."))?;
155         let soft =
156             map_binder_status(keystore_compat_service.getKeyMintDevice(SecurityLevel::SOFTWARE))
157                 .map_err(|e| match e {
158                     Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
159                         Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
160                     }
161                     e => e,
162                 })
163                 .context(ks_err!("Trying to get software device."))?;
164 
165         Ok(BnKeyMintDevice::new_binder(
166             Self { real, soft, emu },
167             BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
168         ))
169     }
170 }
171 
172 impl<T> binder::Interface for BacklevelKeyMintWrapper<T> where T: EmulationDetector + 'static {}
173 
174 impl<T> IKeyMintDevice for BacklevelKeyMintWrapper<T>
175 where
176     T: EmulationDetector + 'static,
177 {
178     // For methods that don't involve keyblobs, forward to either the real
179     // device, or to both real & emulated devices.
getHardwareInfo(&self) -> binder::Result<KeyMintHardwareInfo>180     fn getHardwareInfo(&self) -> binder::Result<KeyMintHardwareInfo> {
181         self.real.getHardwareInfo()
182     }
addRngEntropy(&self, data: &[u8]) -> binder::Result<()>183     fn addRngEntropy(&self, data: &[u8]) -> binder::Result<()> {
184         self.real.addRngEntropy(data)
185     }
deleteAllKeys(&self) -> binder::Result<()>186     fn deleteAllKeys(&self) -> binder::Result<()> {
187         self.real.deleteAllKeys()
188     }
destroyAttestationIds(&self) -> binder::Result<()>189     fn destroyAttestationIds(&self) -> binder::Result<()> {
190         self.real.destroyAttestationIds()
191     }
deviceLocked( &self, password_only: bool, timestamp_token: Option<&TimeStampToken>, ) -> binder::Result<()>192     fn deviceLocked(
193         &self,
194         password_only: bool,
195         timestamp_token: Option<&TimeStampToken>,
196     ) -> binder::Result<()> {
197         // Propagate to both real and software devices, but only pay attention
198         // to the result from the real device.
199         let _ = self.soft.deviceLocked(password_only, timestamp_token);
200         self.real.deviceLocked(password_only, timestamp_token)
201     }
earlyBootEnded(&self) -> binder::Result<()>202     fn earlyBootEnded(&self) -> binder::Result<()> {
203         // Propagate to both real and software devices, but only pay attention
204         // to the result from the real device.
205         let _ = self.soft.earlyBootEnded();
206         self.real.earlyBootEnded()
207     }
getRootOfTrustChallenge(&self) -> binder::Result<[u8; 16]>208     fn getRootOfTrustChallenge(&self) -> binder::Result<[u8; 16]> {
209         self.real.getRootOfTrustChallenge()
210     }
getRootOfTrust(&self, challenge: &[u8; 16]) -> binder::Result<Vec<u8>>211     fn getRootOfTrust(&self, challenge: &[u8; 16]) -> binder::Result<Vec<u8>> {
212         self.real.getRootOfTrust(challenge)
213     }
sendRootOfTrust(&self, root_of_trust: &[u8]) -> binder::Result<()>214     fn sendRootOfTrust(&self, root_of_trust: &[u8]) -> binder::Result<()> {
215         self.real.sendRootOfTrust(root_of_trust)
216     }
217 
218     // For methods that emit keyblobs, check whether the underlying real device
219     // supports the relevant parameters, and forward to the appropriate device.
220     // If the emulated device is used, ensure that the created keyblob gets
221     // prefixed so we can recognize it in future.
generateKey( &self, key_params: &[KeyParameter], attestation_key: Option<&AttestationKey>, ) -> binder::Result<KeyCreationResult>222     fn generateKey(
223         &self,
224         key_params: &[KeyParameter],
225         attestation_key: Option<&AttestationKey>,
226     ) -> binder::Result<KeyCreationResult> {
227         if self.emu.emulation_required(key_params, &KeyImportData::None) {
228             let mut result = self.soft.generateKey(key_params, attestation_key)?;
229             result.keyBlob = wrap_keyblob(&result.keyBlob).map_err(into_logged_binder)?;
230             Ok(result)
231         } else {
232             self.real.generateKey(key_params, attestation_key)
233         }
234     }
importKey( &self, key_params: &[KeyParameter], key_format: KeyFormat, key_data: &[u8], attestation_key: Option<&AttestationKey>, ) -> binder::Result<KeyCreationResult>235     fn importKey(
236         &self,
237         key_params: &[KeyParameter],
238         key_format: KeyFormat,
239         key_data: &[u8],
240         attestation_key: Option<&AttestationKey>,
241     ) -> binder::Result<KeyCreationResult> {
242         if self.emu.emulation_required(key_params, &KeyImportData::new(key_format, key_data)?) {
243             let mut result =
244                 self.soft.importKey(key_params, key_format, key_data, attestation_key)?;
245             result.keyBlob = wrap_keyblob(&result.keyBlob).map_err(into_logged_binder)?;
246             Ok(result)
247         } else {
248             self.real.importKey(key_params, key_format, key_data, attestation_key)
249         }
250     }
importWrappedKey( &self, wrapped_key_data: &[u8], wrapping_key_blob: &[u8], masking_key: &[u8], unwrapping_params: &[KeyParameter], password_sid: i64, biometric_sid: i64, ) -> binder::Result<KeyCreationResult>251     fn importWrappedKey(
252         &self,
253         wrapped_key_data: &[u8],
254         wrapping_key_blob: &[u8],
255         masking_key: &[u8],
256         unwrapping_params: &[KeyParameter],
257         password_sid: i64,
258         biometric_sid: i64,
259     ) -> binder::Result<KeyCreationResult> {
260         // A wrapped key cannot be software-emulated, as the wrapping key is
261         // likely hardware-bound.
262         self.real.importWrappedKey(
263             wrapped_key_data,
264             wrapping_key_blob,
265             masking_key,
266             unwrapping_params,
267             password_sid,
268             biometric_sid,
269         )
270     }
271 
272     // For methods that use keyblobs, determine which device to forward the
273     // operation to based on whether the keyblob is appropriately prefixed.
upgradeKey( &self, keyblob_to_upgrade: &[u8], upgrade_params: &[KeyParameter], ) -> binder::Result<Vec<u8>>274     fn upgradeKey(
275         &self,
276         keyblob_to_upgrade: &[u8],
277         upgrade_params: &[KeyParameter],
278     ) -> binder::Result<Vec<u8>> {
279         match unwrap_keyblob(keyblob_to_upgrade) {
280             KeyBlob::Raw(keyblob) => self.real.upgradeKey(keyblob, upgrade_params),
281             KeyBlob::Wrapped(keyblob) => {
282                 // Re-wrap the upgraded keyblob.
283                 let upgraded_keyblob = self.soft.upgradeKey(keyblob, upgrade_params)?;
284                 wrap_keyblob(&upgraded_keyblob).map_err(into_logged_binder)
285             }
286         }
287     }
deleteKey(&self, keyblob: &[u8]) -> binder::Result<()>288     fn deleteKey(&self, keyblob: &[u8]) -> binder::Result<()> {
289         match unwrap_keyblob(keyblob) {
290             KeyBlob::Raw(keyblob) => self.real.deleteKey(keyblob),
291             KeyBlob::Wrapped(keyblob) => {
292                 // Forward to the software implementation for completeness, but
293                 // this should always be a no-op.
294                 self.soft.deleteKey(keyblob)
295             }
296         }
297     }
begin( &self, purpose: KeyPurpose, keyblob: &[u8], params: &[KeyParameter], auth_token: Option<&HardwareAuthToken>, ) -> binder::Result<BeginResult>298     fn begin(
299         &self,
300         purpose: KeyPurpose,
301         keyblob: &[u8],
302         params: &[KeyParameter],
303         auth_token: Option<&HardwareAuthToken>,
304     ) -> binder::Result<BeginResult> {
305         match unwrap_keyblob(keyblob) {
306             KeyBlob::Raw(keyblob) => self.real.begin(purpose, keyblob, params, auth_token),
307             KeyBlob::Wrapped(keyblob) => self.soft.begin(purpose, keyblob, params, auth_token),
308         }
309     }
getKeyCharacteristics( &self, keyblob: &[u8], app_id: &[u8], app_data: &[u8], ) -> binder::Result<Vec<KeyCharacteristics>>310     fn getKeyCharacteristics(
311         &self,
312         keyblob: &[u8],
313         app_id: &[u8],
314         app_data: &[u8],
315     ) -> binder::Result<Vec<KeyCharacteristics>> {
316         match unwrap_keyblob(keyblob) {
317             KeyBlob::Raw(keyblob) => self.real.getKeyCharacteristics(keyblob, app_id, app_data),
318             KeyBlob::Wrapped(keyblob) => self.soft.getKeyCharacteristics(keyblob, app_id, app_data),
319         }
320     }
convertStorageKeyToEphemeral(&self, storage_keyblob: &[u8]) -> binder::Result<Vec<u8>>321     fn convertStorageKeyToEphemeral(&self, storage_keyblob: &[u8]) -> binder::Result<Vec<u8>> {
322         // Storage keys should never be associated with a software emulated device.
323         self.real.convertStorageKeyToEphemeral(storage_keyblob)
324     }
325 }
326 
327 /// Detector for current features that are not implemented by KeyMint V1.
328 #[derive(Debug)]
329 pub struct KeyMintV1 {
330     sec_level: SecurityLevel,
331 }
332 
333 impl KeyMintV1 {
new(sec_level: SecurityLevel) -> Self334     pub fn new(sec_level: SecurityLevel) -> Self {
335         Self { sec_level }
336     }
337 }
338 
339 impl EmulationDetector for KeyMintV1 {
emulation_required(&self, params: &[KeyParameter], _import_data: &KeyImportData) -> bool340     fn emulation_required(&self, params: &[KeyParameter], _import_data: &KeyImportData) -> bool {
341         // No current difference from KeyMint v1 for STRONGBOX (it doesn't
342         // support curve 25519).
343         if self.sec_level == SecurityLevel::STRONGBOX {
344             return false;
345         }
346 
347         // KeyMint V1 does not support the use of curve 25519, so hunt for that
348         // in the parameters.
349         if params.iter().any(|p| {
350             p.tag == Tag::EC_CURVE && p.value == KeyParameterValue::EcCurve(EcCurve::CURVE_25519)
351         }) {
352             return true;
353         }
354         // In theory, if the `import_data` is `KeyImportData::Pkcs8` we could
355         // check the imported keymaterial for the Ed25519 / X25519 OIDs in the
356         // PKCS8 keydata, and use that to decide to route to software. However,
357         // the KeyMint spec doesn't require that so don't attempt to parse the
358         // key material here.
359         false
360     }
361 }
362 
363 /// Detector for current features that are not implemented by KeyMaster, via the
364 /// km_compat wrapper.
365 #[derive(Debug)]
366 pub struct Keymaster {
367     v1: KeyMintV1,
368 }
369 
370 /// TODO(b/216434270): This could be used this to replace the emulation routing
371 /// in the km_compat C++ code, and allow support for imported ECDH keys along
372 /// the way. Would need to figure out what would happen to existing emulated
373 /// keys though.
374 #[allow(dead_code)]
375 impl Keymaster {
new(sec_level: SecurityLevel) -> Self376     pub fn new(sec_level: SecurityLevel) -> Self {
377         Self { v1: KeyMintV1::new(sec_level) }
378     }
379 }
380 
381 impl EmulationDetector for Keymaster {
emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool382     fn emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool {
383         // The km_compat wrapper on top of Keymaster emulates the KeyMint V1
384         // interface, so any feature from > v1 needs to be emulated.
385         if self.v1.emulation_required(params, import_data) {
386             return true;
387         }
388 
389         // Keymaster does not support ECDH (KeyPurpose::AGREE_KEY), so hunt for
390         // that in the parameters.
391         if params.iter().any(|p| {
392             p.tag == Tag::PURPOSE && p.value == KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY)
393         }) {
394             return true;
395         }
396         false
397     }
398 }
399 
400 #[cfg(test)]
401 mod tests {
402     use super::*;
403 
404     #[test]
test_key_import_data()405     fn test_key_import_data() {
406         let data = vec![1, 2, 3];
407         assert_eq!(KeyImportData::new(KeyFormat::PKCS8, &data), Ok(KeyImportData::Pkcs8(&data)));
408         assert_eq!(KeyImportData::new(KeyFormat::RAW, &data), Ok(KeyImportData::Raw(&data)));
409         assert!(KeyImportData::new(KeyFormat::X509, &data).is_err());
410     }
411 
412     #[test]
test_wrap_keyblob()413     fn test_wrap_keyblob() {
414         let keyblob = vec![1, 2, 3];
415         let wrapped = wrap_keyblob(&keyblob).unwrap();
416         assert_eq!(&wrapped[..KEYBLOB_PREFIX.len()], KEYBLOB_PREFIX);
417         assert_eq!(&wrapped[KEYBLOB_PREFIX.len()..KEYBLOB_PREFIX.len() + keyblob.len()], &keyblob);
418         assert_eq!(unwrap_keyblob(&keyblob), KeyBlob::Raw(&keyblob));
419         assert_eq!(unwrap_keyblob(&wrapped), KeyBlob::Wrapped(&keyblob));
420 
421         let mut corrupt_prefix = wrapped.clone();
422         corrupt_prefix[0] ^= 0x01;
423         assert_eq!(unwrap_keyblob(&corrupt_prefix), KeyBlob::Raw(&corrupt_prefix));
424 
425         let mut corrupt_suffix = wrapped.clone();
426         corrupt_suffix[wrapped.len() - 1] ^= 0x01;
427         assert_eq!(unwrap_keyblob(&corrupt_suffix), KeyBlob::Raw(&corrupt_suffix));
428 
429         let too_short = &wrapped[..wrapped.len() - 4];
430         assert_eq!(unwrap_keyblob(too_short), KeyBlob::Raw(too_short));
431     }
432 
433     #[test]
test_keymintv1_emulation_required()434     fn test_keymintv1_emulation_required() {
435         let tests = vec![
436             (SecurityLevel::TRUSTED_ENVIRONMENT, vec![], false),
437             (
438                 SecurityLevel::TRUSTED_ENVIRONMENT,
439                 vec![
440                     KeyParameter {
441                         tag: Tag::PURPOSE,
442                         value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
443                     },
444                     KeyParameter {
445                         tag: Tag::PURPOSE,
446                         value: KeyParameterValue::KeyPurpose(KeyPurpose::VERIFY),
447                     },
448                 ],
449                 false,
450             ),
451             (
452                 SecurityLevel::TRUSTED_ENVIRONMENT,
453                 vec![KeyParameter {
454                     tag: Tag::PURPOSE,
455                     value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
456                 }],
457                 false,
458             ),
459             (
460                 SecurityLevel::TRUSTED_ENVIRONMENT,
461                 vec![
462                     KeyParameter {
463                         tag: Tag::PURPOSE,
464                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
465                     },
466                     KeyParameter {
467                         tag: Tag::EC_CURVE,
468                         value: KeyParameterValue::EcCurve(EcCurve::P_256),
469                     },
470                 ],
471                 false,
472             ),
473             (
474                 SecurityLevel::TRUSTED_ENVIRONMENT,
475                 vec![
476                     KeyParameter {
477                         tag: Tag::PURPOSE,
478                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
479                     },
480                     KeyParameter {
481                         tag: Tag::EC_CURVE,
482                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
483                     },
484                 ],
485                 true,
486             ),
487             (
488                 SecurityLevel::STRONGBOX,
489                 vec![
490                     KeyParameter {
491                         tag: Tag::PURPOSE,
492                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
493                     },
494                     KeyParameter {
495                         tag: Tag::EC_CURVE,
496                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
497                     },
498                 ],
499                 false,
500             ),
501         ];
502         for (sec_level, params, want) in tests {
503             let v1 = KeyMintV1::new(sec_level);
504             let got = v1.emulation_required(&params, &KeyImportData::None);
505             assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want);
506         }
507     }
508 
509     #[test]
test_keymaster_emulation_required()510     fn test_keymaster_emulation_required() {
511         let tests = vec![
512             (SecurityLevel::TRUSTED_ENVIRONMENT, vec![], false),
513             (
514                 SecurityLevel::TRUSTED_ENVIRONMENT,
515                 vec![
516                     KeyParameter {
517                         tag: Tag::PURPOSE,
518                         value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
519                     },
520                     KeyParameter {
521                         tag: Tag::PURPOSE,
522                         value: KeyParameterValue::KeyPurpose(KeyPurpose::VERIFY),
523                     },
524                 ],
525                 false,
526             ),
527             (
528                 SecurityLevel::TRUSTED_ENVIRONMENT,
529                 vec![KeyParameter {
530                     tag: Tag::PURPOSE,
531                     value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
532                 }],
533                 true,
534             ),
535             (
536                 SecurityLevel::TRUSTED_ENVIRONMENT,
537                 vec![
538                     KeyParameter {
539                         tag: Tag::PURPOSE,
540                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
541                     },
542                     KeyParameter {
543                         tag: Tag::EC_CURVE,
544                         value: KeyParameterValue::EcCurve(EcCurve::P_256),
545                     },
546                 ],
547                 true,
548             ),
549             (
550                 SecurityLevel::TRUSTED_ENVIRONMENT,
551                 vec![
552                     KeyParameter {
553                         tag: Tag::PURPOSE,
554                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
555                     },
556                     KeyParameter {
557                         tag: Tag::EC_CURVE,
558                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
559                     },
560                 ],
561                 true,
562             ),
563             (
564                 SecurityLevel::STRONGBOX,
565                 vec![
566                     KeyParameter {
567                         tag: Tag::PURPOSE,
568                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
569                     },
570                     KeyParameter {
571                         tag: Tag::EC_CURVE,
572                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
573                     },
574                 ],
575                 true,
576             ),
577             (
578                 SecurityLevel::STRONGBOX,
579                 vec![
580                     KeyParameter {
581                         tag: Tag::PURPOSE,
582                         value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
583                     },
584                     KeyParameter {
585                         tag: Tag::EC_CURVE,
586                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
587                     },
588                 ],
589                 false,
590             ),
591         ];
592         for (sec_level, params, want) in tests {
593             let v0 = Keymaster::new(sec_level);
594             let got = v0.emulation_required(&params, &KeyImportData::None);
595             assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want);
596         }
597     }
598 }
599