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