xref: /aosp_15_r20/system/security/keystore2/src/km_compat.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
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     }
setAdditionalAttestationInfo( &self, additional_attestation_info: &[KeyParameter], ) -> binder::Result<()>217     fn setAdditionalAttestationInfo(
218         &self,
219         additional_attestation_info: &[KeyParameter],
220     ) -> binder::Result<()> {
221         self.real.setAdditionalAttestationInfo(additional_attestation_info)
222     }
223 
224     // For methods that emit keyblobs, check whether the underlying real device
225     // supports the relevant parameters, and forward to the appropriate device.
226     // If the emulated device is used, ensure that the created keyblob gets
227     // prefixed so we can recognize it in future.
generateKey( &self, key_params: &[KeyParameter], attestation_key: Option<&AttestationKey>, ) -> binder::Result<KeyCreationResult>228     fn generateKey(
229         &self,
230         key_params: &[KeyParameter],
231         attestation_key: Option<&AttestationKey>,
232     ) -> binder::Result<KeyCreationResult> {
233         if self.emu.emulation_required(key_params, &KeyImportData::None) {
234             let mut result = self.soft.generateKey(key_params, attestation_key)?;
235             result.keyBlob = wrap_keyblob(&result.keyBlob).map_err(into_logged_binder)?;
236             Ok(result)
237         } else {
238             self.real.generateKey(key_params, attestation_key)
239         }
240     }
importKey( &self, key_params: &[KeyParameter], key_format: KeyFormat, key_data: &[u8], attestation_key: Option<&AttestationKey>, ) -> binder::Result<KeyCreationResult>241     fn importKey(
242         &self,
243         key_params: &[KeyParameter],
244         key_format: KeyFormat,
245         key_data: &[u8],
246         attestation_key: Option<&AttestationKey>,
247     ) -> binder::Result<KeyCreationResult> {
248         if self.emu.emulation_required(key_params, &KeyImportData::new(key_format, key_data)?) {
249             let mut result =
250                 self.soft.importKey(key_params, key_format, key_data, attestation_key)?;
251             result.keyBlob = wrap_keyblob(&result.keyBlob).map_err(into_logged_binder)?;
252             Ok(result)
253         } else {
254             self.real.importKey(key_params, key_format, key_data, attestation_key)
255         }
256     }
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>257     fn importWrappedKey(
258         &self,
259         wrapped_key_data: &[u8],
260         wrapping_key_blob: &[u8],
261         masking_key: &[u8],
262         unwrapping_params: &[KeyParameter],
263         password_sid: i64,
264         biometric_sid: i64,
265     ) -> binder::Result<KeyCreationResult> {
266         // A wrapped key cannot be software-emulated, as the wrapping key is
267         // likely hardware-bound.
268         self.real.importWrappedKey(
269             wrapped_key_data,
270             wrapping_key_blob,
271             masking_key,
272             unwrapping_params,
273             password_sid,
274             biometric_sid,
275         )
276     }
277 
278     // For methods that use keyblobs, determine which device to forward the
279     // operation to based on whether the keyblob is appropriately prefixed.
upgradeKey( &self, keyblob_to_upgrade: &[u8], upgrade_params: &[KeyParameter], ) -> binder::Result<Vec<u8>>280     fn upgradeKey(
281         &self,
282         keyblob_to_upgrade: &[u8],
283         upgrade_params: &[KeyParameter],
284     ) -> binder::Result<Vec<u8>> {
285         match unwrap_keyblob(keyblob_to_upgrade) {
286             KeyBlob::Raw(keyblob) => self.real.upgradeKey(keyblob, upgrade_params),
287             KeyBlob::Wrapped(keyblob) => {
288                 // Re-wrap the upgraded keyblob.
289                 let upgraded_keyblob = self.soft.upgradeKey(keyblob, upgrade_params)?;
290                 wrap_keyblob(&upgraded_keyblob).map_err(into_logged_binder)
291             }
292         }
293     }
deleteKey(&self, keyblob: &[u8]) -> binder::Result<()>294     fn deleteKey(&self, keyblob: &[u8]) -> binder::Result<()> {
295         match unwrap_keyblob(keyblob) {
296             KeyBlob::Raw(keyblob) => self.real.deleteKey(keyblob),
297             KeyBlob::Wrapped(keyblob) => {
298                 // Forward to the software implementation for completeness, but
299                 // this should always be a no-op.
300                 self.soft.deleteKey(keyblob)
301             }
302         }
303     }
begin( &self, purpose: KeyPurpose, keyblob: &[u8], params: &[KeyParameter], auth_token: Option<&HardwareAuthToken>, ) -> binder::Result<BeginResult>304     fn begin(
305         &self,
306         purpose: KeyPurpose,
307         keyblob: &[u8],
308         params: &[KeyParameter],
309         auth_token: Option<&HardwareAuthToken>,
310     ) -> binder::Result<BeginResult> {
311         match unwrap_keyblob(keyblob) {
312             KeyBlob::Raw(keyblob) => self.real.begin(purpose, keyblob, params, auth_token),
313             KeyBlob::Wrapped(keyblob) => self.soft.begin(purpose, keyblob, params, auth_token),
314         }
315     }
getKeyCharacteristics( &self, keyblob: &[u8], app_id: &[u8], app_data: &[u8], ) -> binder::Result<Vec<KeyCharacteristics>>316     fn getKeyCharacteristics(
317         &self,
318         keyblob: &[u8],
319         app_id: &[u8],
320         app_data: &[u8],
321     ) -> binder::Result<Vec<KeyCharacteristics>> {
322         match unwrap_keyblob(keyblob) {
323             KeyBlob::Raw(keyblob) => self.real.getKeyCharacteristics(keyblob, app_id, app_data),
324             KeyBlob::Wrapped(keyblob) => self.soft.getKeyCharacteristics(keyblob, app_id, app_data),
325         }
326     }
convertStorageKeyToEphemeral(&self, storage_keyblob: &[u8]) -> binder::Result<Vec<u8>>327     fn convertStorageKeyToEphemeral(&self, storage_keyblob: &[u8]) -> binder::Result<Vec<u8>> {
328         // Storage keys should never be associated with a software emulated device.
329         self.real.convertStorageKeyToEphemeral(storage_keyblob)
330     }
331 }
332 
333 /// Detector for current features that are not implemented by KeyMint V1.
334 #[derive(Debug)]
335 pub struct KeyMintV1 {
336     sec_level: SecurityLevel,
337 }
338 
339 impl KeyMintV1 {
new(sec_level: SecurityLevel) -> Self340     pub fn new(sec_level: SecurityLevel) -> Self {
341         Self { sec_level }
342     }
343 }
344 
345 impl EmulationDetector for KeyMintV1 {
emulation_required(&self, params: &[KeyParameter], _import_data: &KeyImportData) -> bool346     fn emulation_required(&self, params: &[KeyParameter], _import_data: &KeyImportData) -> bool {
347         // No current difference from KeyMint v1 for STRONGBOX (it doesn't
348         // support curve 25519).
349         if self.sec_level == SecurityLevel::STRONGBOX {
350             return false;
351         }
352 
353         // KeyMint V1 does not support the use of curve 25519, so hunt for that
354         // in the parameters.
355         if params.iter().any(|p| {
356             p.tag == Tag::EC_CURVE && p.value == KeyParameterValue::EcCurve(EcCurve::CURVE_25519)
357         }) {
358             return true;
359         }
360         // In theory, if the `import_data` is `KeyImportData::Pkcs8` we could
361         // check the imported keymaterial for the Ed25519 / X25519 OIDs in the
362         // PKCS8 keydata, and use that to decide to route to software. However,
363         // the KeyMint spec doesn't require that so don't attempt to parse the
364         // key material here.
365         false
366     }
367 }
368 
369 /// Detector for current features that are not implemented by KeyMaster, via the
370 /// km_compat wrapper.
371 #[derive(Debug)]
372 pub struct Keymaster {
373     v1: KeyMintV1,
374 }
375 
376 /// TODO(b/216434270): This could be used this to replace the emulation routing
377 /// in the km_compat C++ code, and allow support for imported ECDH keys along
378 /// the way. Would need to figure out what would happen to existing emulated
379 /// keys though.
380 #[allow(dead_code)]
381 impl Keymaster {
new(sec_level: SecurityLevel) -> Self382     pub fn new(sec_level: SecurityLevel) -> Self {
383         Self { v1: KeyMintV1::new(sec_level) }
384     }
385 }
386 
387 impl EmulationDetector for Keymaster {
emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool388     fn emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool {
389         // The km_compat wrapper on top of Keymaster emulates the KeyMint V1
390         // interface, so any feature from > v1 needs to be emulated.
391         if self.v1.emulation_required(params, import_data) {
392             return true;
393         }
394 
395         // Keymaster does not support ECDH (KeyPurpose::AGREE_KEY), so hunt for
396         // that in the parameters.
397         if params.iter().any(|p| {
398             p.tag == Tag::PURPOSE && p.value == KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY)
399         }) {
400             return true;
401         }
402         false
403     }
404 }
405 
406 #[cfg(test)]
407 mod tests {
408     use super::*;
409 
410     #[test]
test_key_import_data()411     fn test_key_import_data() {
412         let data = vec![1, 2, 3];
413         assert_eq!(KeyImportData::new(KeyFormat::PKCS8, &data), Ok(KeyImportData::Pkcs8(&data)));
414         assert_eq!(KeyImportData::new(KeyFormat::RAW, &data), Ok(KeyImportData::Raw(&data)));
415         assert!(KeyImportData::new(KeyFormat::X509, &data).is_err());
416     }
417 
418     #[test]
test_wrap_keyblob()419     fn test_wrap_keyblob() {
420         let keyblob = vec![1, 2, 3];
421         let wrapped = wrap_keyblob(&keyblob).unwrap();
422         assert_eq!(&wrapped[..KEYBLOB_PREFIX.len()], KEYBLOB_PREFIX);
423         assert_eq!(&wrapped[KEYBLOB_PREFIX.len()..KEYBLOB_PREFIX.len() + keyblob.len()], &keyblob);
424         assert_eq!(unwrap_keyblob(&keyblob), KeyBlob::Raw(&keyblob));
425         assert_eq!(unwrap_keyblob(&wrapped), KeyBlob::Wrapped(&keyblob));
426 
427         let mut corrupt_prefix = wrapped.clone();
428         corrupt_prefix[0] ^= 0x01;
429         assert_eq!(unwrap_keyblob(&corrupt_prefix), KeyBlob::Raw(&corrupt_prefix));
430 
431         let mut corrupt_suffix = wrapped.clone();
432         corrupt_suffix[wrapped.len() - 1] ^= 0x01;
433         assert_eq!(unwrap_keyblob(&corrupt_suffix), KeyBlob::Raw(&corrupt_suffix));
434 
435         let too_short = &wrapped[..wrapped.len() - 4];
436         assert_eq!(unwrap_keyblob(too_short), KeyBlob::Raw(too_short));
437     }
438 
439     #[test]
test_keymintv1_emulation_required()440     fn test_keymintv1_emulation_required() {
441         let tests = vec![
442             (SecurityLevel::TRUSTED_ENVIRONMENT, vec![], false),
443             (
444                 SecurityLevel::TRUSTED_ENVIRONMENT,
445                 vec![
446                     KeyParameter {
447                         tag: Tag::PURPOSE,
448                         value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
449                     },
450                     KeyParameter {
451                         tag: Tag::PURPOSE,
452                         value: KeyParameterValue::KeyPurpose(KeyPurpose::VERIFY),
453                     },
454                 ],
455                 false,
456             ),
457             (
458                 SecurityLevel::TRUSTED_ENVIRONMENT,
459                 vec![KeyParameter {
460                     tag: Tag::PURPOSE,
461                     value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
462                 }],
463                 false,
464             ),
465             (
466                 SecurityLevel::TRUSTED_ENVIRONMENT,
467                 vec![
468                     KeyParameter {
469                         tag: Tag::PURPOSE,
470                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
471                     },
472                     KeyParameter {
473                         tag: Tag::EC_CURVE,
474                         value: KeyParameterValue::EcCurve(EcCurve::P_256),
475                     },
476                 ],
477                 false,
478             ),
479             (
480                 SecurityLevel::TRUSTED_ENVIRONMENT,
481                 vec![
482                     KeyParameter {
483                         tag: Tag::PURPOSE,
484                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
485                     },
486                     KeyParameter {
487                         tag: Tag::EC_CURVE,
488                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
489                     },
490                 ],
491                 true,
492             ),
493             (
494                 SecurityLevel::STRONGBOX,
495                 vec![
496                     KeyParameter {
497                         tag: Tag::PURPOSE,
498                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
499                     },
500                     KeyParameter {
501                         tag: Tag::EC_CURVE,
502                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
503                     },
504                 ],
505                 false,
506             ),
507         ];
508         for (sec_level, params, want) in tests {
509             let v1 = KeyMintV1::new(sec_level);
510             let got = v1.emulation_required(&params, &KeyImportData::None);
511             assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want);
512         }
513     }
514 
515     #[test]
test_keymaster_emulation_required()516     fn test_keymaster_emulation_required() {
517         let tests = vec![
518             (SecurityLevel::TRUSTED_ENVIRONMENT, vec![], false),
519             (
520                 SecurityLevel::TRUSTED_ENVIRONMENT,
521                 vec![
522                     KeyParameter {
523                         tag: Tag::PURPOSE,
524                         value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
525                     },
526                     KeyParameter {
527                         tag: Tag::PURPOSE,
528                         value: KeyParameterValue::KeyPurpose(KeyPurpose::VERIFY),
529                     },
530                 ],
531                 false,
532             ),
533             (
534                 SecurityLevel::TRUSTED_ENVIRONMENT,
535                 vec![KeyParameter {
536                     tag: Tag::PURPOSE,
537                     value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
538                 }],
539                 true,
540             ),
541             (
542                 SecurityLevel::TRUSTED_ENVIRONMENT,
543                 vec![
544                     KeyParameter {
545                         tag: Tag::PURPOSE,
546                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
547                     },
548                     KeyParameter {
549                         tag: Tag::EC_CURVE,
550                         value: KeyParameterValue::EcCurve(EcCurve::P_256),
551                     },
552                 ],
553                 true,
554             ),
555             (
556                 SecurityLevel::TRUSTED_ENVIRONMENT,
557                 vec![
558                     KeyParameter {
559                         tag: Tag::PURPOSE,
560                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
561                     },
562                     KeyParameter {
563                         tag: Tag::EC_CURVE,
564                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
565                     },
566                 ],
567                 true,
568             ),
569             (
570                 SecurityLevel::STRONGBOX,
571                 vec![
572                     KeyParameter {
573                         tag: Tag::PURPOSE,
574                         value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
575                     },
576                     KeyParameter {
577                         tag: Tag::EC_CURVE,
578                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
579                     },
580                 ],
581                 true,
582             ),
583             (
584                 SecurityLevel::STRONGBOX,
585                 vec![
586                     KeyParameter {
587                         tag: Tag::PURPOSE,
588                         value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
589                     },
590                     KeyParameter {
591                         tag: Tag::EC_CURVE,
592                         value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
593                     },
594                 ],
595                 false,
596             ),
597         ];
598         for (sec_level, params, want) in tests {
599             let v0 = Keymaster::new(sec_level);
600             let got = v0.emulation_required(&params, &KeyImportData::None);
601             assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want);
602         }
603     }
604 }
605