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(¶ms, &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(¶ms, &KeyImportData::None);
601 assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want);
602 }
603 }
604 }
605