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