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(¶ms, &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(¶ms, &KeyImportData::None);
595 assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want);
596 }
597 }
598 }
599