From b1c8e833920e45042f7ce1c167757b6e3f9e86c1 Mon Sep 17 00:00:00 2001 From: Rajesh Nyamagoud Date: Tue, 6 Jun 2023 01:39:44 +0000 Subject: Adding tests to verify Device-Unique-Attestation. 1. Test to verify Device-Unique-Attestation is not supported on `TRUSTED_ENVIRONMENT` security level. Test shoould fail to generate a key with device-unique-attestation with `INVALID_ARGUMENT` error code. 2. Generate EC/RSA keys with `DEVICE_UNIQUE_ATTESTATION` using `STRONGBOX` security level. Test should generate akey and verify key characteristics and cert-chain signatures. Test should be able to perform an operation using the generated key successfully. 3. Try to generate a device unique attested key with attestation of invalid device's identifiers. Test should fail to generate a key with error code `CANNOT_ATTEST_IDS`. 4. Generate a device unique attested key with attestation of the device's identifiers. Test should succeed in generating a attested key with attestation of device identifiers. Test might fail on devices which don't support device id attestation with error response code `CANNOT_ATTEST_IDS`. Separate test is added for each attestation id with RSA and EC keys. Bug: 279721870 Test: atest keystore2_client_tests Change-Id: I627a01dc44558a4393d14f9931b1708196ee6ff9 --- keystore2/test_utils/authorizations.rs | 9 + keystore2/test_utils/ffi_test_utils.rs | 14 +- keystore2/test_utils/key_generations.rs | 7 +- .../tests/keystore2_client_attest_key_tests.rs | 12 +- ...tore2_client_device_unique_attestation_tests.rs | 406 +++++++++++++++++++++ keystore2/tests/keystore2_client_test_utils.rs | 32 +- keystore2/tests/keystore2_client_tests.rs | 1 + 7 files changed, 451 insertions(+), 30 deletions(-) create mode 100644 keystore2/tests/keystore2_client_device_unique_attestation_tests.rs (limited to 'keystore2') diff --git a/keystore2/test_utils/authorizations.rs b/keystore2/test_utils/authorizations.rs index 02ceb83e..61260c78 100644 --- a/keystore2/test_utils/authorizations.rs +++ b/keystore2/test_utils/authorizations.rs @@ -335,6 +335,15 @@ impl AuthSetBuilder { self.0.push(KeyParameter { tag: Tag::APPLICATION_ID, value: KeyParameterValue::Blob(b) }); self } + + /// Set device-unique-attestation. + pub fn device_unique_attestation(mut self) -> Self { + self.0.push(KeyParameter { + tag: Tag::DEVICE_UNIQUE_ATTESTATION, + value: KeyParameterValue::BoolValue(true), + }); + self + } } impl Deref for AuthSetBuilder { diff --git a/keystore2/test_utils/ffi_test_utils.rs b/keystore2/test_utils/ffi_test_utils.rs index 5d6bf46e..1ccdcc81 100644 --- a/keystore2/test_utils/ffi_test_utils.rs +++ b/keystore2/test_utils/ffi_test_utils.rs @@ -50,7 +50,19 @@ mod ffi { /// Validate given certificate chain. pub fn validate_certchain(cert_buf: &[u8]) -> Result { - if ffi::validateCertChain(cert_buf.to_vec(), cert_buf.len().try_into().unwrap(), true) { + validate_certchain_with_strict_issuer_check(cert_buf, true) +} + +/// Validate given certificate chain with an option to validate the issuer. +pub fn validate_certchain_with_strict_issuer_check( + cert_buf: &[u8], + strict_issuer_check: bool, +) -> Result { + if ffi::validateCertChain( + cert_buf.to_vec(), + cert_buf.len().try_into().unwrap(), + strict_issuer_check, + ) { return Ok(true); } diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs index badc4806..9ddc87aa 100644 --- a/keystore2/test_utils/key_generations.rs +++ b/keystore2/test_utils/key_generations.rs @@ -40,7 +40,7 @@ use android_system_keystore2::binder::{ExceptionCode, Result as BinderResult}; use crate::ffi_test_utils::{ get_os_patchlevel, get_os_version, get_value_from_attest_record, get_vendor_patchlevel, - validate_certchain, + validate_certchain_with_strict_issuer_check, }; /// Shell namespace. @@ -1426,7 +1426,10 @@ pub fn generate_key( let mut cert_chain: Vec = Vec::new(); cert_chain.extend(key_metadata.certificate.as_ref().unwrap()); cert_chain.extend(key_metadata.certificateChain.as_ref().unwrap()); - validate_certchain(&cert_chain).expect("Error while validating cert chain"); + let strict_issuer_check = + !(gen_params.iter().any(|kp| kp.tag == Tag::DEVICE_UNIQUE_ATTESTATION)); + validate_certchain_with_strict_issuer_check(&cert_chain, strict_issuer_check) + .expect("Error while validating cert chain"); } if let Some(challenge_param) = diff --git a/keystore2/tests/keystore2_client_attest_key_tests.rs b/keystore2/tests/keystore2_client_attest_key_tests.rs index c9ef2988..3532a350 100644 --- a/keystore2/tests/keystore2_client_attest_key_tests.rs +++ b/keystore2/tests/keystore2_client_attest_key_tests.rs @@ -488,12 +488,12 @@ fn keystore2_attest_symmetric_key_fail_sys_error() { fn get_attestation_ids(keystore2: &binder::Strong) -> Vec<(Tag, Vec)> { let attest_ids = vec![ - (Tag::ATTESTATION_ID_BRAND, "ro.product.brand_for_attestation"), - (Tag::ATTESTATION_ID_DEVICE, "ro.product.device"), - (Tag::ATTESTATION_ID_PRODUCT, "ro.product.name_for_attestation"), - (Tag::ATTESTATION_ID_SERIAL, "ro.serialno"), - (Tag::ATTESTATION_ID_MANUFACTURER, "ro.product.manufacturer"), - (Tag::ATTESTATION_ID_MODEL, "ro.product.model_for_attestation"), + (Tag::ATTESTATION_ID_BRAND, "brand"), + (Tag::ATTESTATION_ID_DEVICE, "device"), + (Tag::ATTESTATION_ID_PRODUCT, "name"), + (Tag::ATTESTATION_ID_SERIAL, "serialno"), + (Tag::ATTESTATION_ID_MANUFACTURER, "manufacturer"), + (Tag::ATTESTATION_ID_MODEL, "model"), (Tag::ATTESTATION_ID_IMEI, ""), //Get this value from Telephony service. (Tag::ATTESTATION_ID_SECOND_IMEI, ""), //Get this value from Telephony service. ]; diff --git a/keystore2/tests/keystore2_client_device_unique_attestation_tests.rs b/keystore2/tests/keystore2_client_device_unique_attestation_tests.rs new file mode 100644 index 00000000..cf88fc54 --- /dev/null +++ b/keystore2/tests/keystore2_client_device_unique_attestation_tests.rs @@ -0,0 +1,406 @@ +// Copyright 2023, The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ + Algorithm::Algorithm, Digest::Digest, EcCurve::EcCurve, ErrorCode::ErrorCode, + KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag, +}; + +use keystore2_test_utils::{ + authorizations, get_keystore_service, key_generations, key_generations::Error, +}; + +use keystore2_test_utils::ffi_test_utils::get_value_from_attest_record; + +use crate::keystore2_client_test_utils::{ + delete_app_key, get_attest_id_value, is_second_imei_id_attestation_required, + perform_sample_asym_sign_verify_op, +}; + +/// This macro is used for generating device unique attested EC key with device id attestation. +macro_rules! test_ec_key_device_unique_attestation_id { + ( $test_name:ident, $tag:expr, $prop_name:expr ) => { + #[test] + fn $test_name() { + generate_ec_key_device_unique_attested_with_id_attest($tag, $prop_name); + } + }; +} + +/// This macro is used for generating device unique attested RSA key with device id attestation. +macro_rules! test_rsa_key_device_unique_attestation_id { + ( $test_name:ident, $tag:expr, $prop_name:expr ) => { + #[test] + fn $test_name() { + generate_rsa_key_device_unique_attested_with_id_attest($tag, $prop_name); + } + }; +} + +fn generate_ec_key_device_unique_attested_with_id_attest(attest_id_tag: Tag, prop_name: &str) { + let gen_params = authorizations::AuthSetBuilder::new() + .no_auth_required() + .algorithm(Algorithm::EC) + .purpose(KeyPurpose::SIGN) + .purpose(KeyPurpose::VERIFY) + .digest(Digest::SHA_2_256) + .ec_curve(EcCurve::P_256) + .attestation_challenge(b"foo".to_vec()) + .device_unique_attestation(); + generate_device_unique_attested_key_with_device_attest_ids( + gen_params, + attest_id_tag, + prop_name, + ); +} + +fn generate_rsa_key_device_unique_attested_with_id_attest(attest_id_tag: Tag, prop_name: &str) { + let gen_params = authorizations::AuthSetBuilder::new() + .no_auth_required() + .algorithm(Algorithm::RSA) + .rsa_public_exponent(65537) + .key_size(2048) + .purpose(KeyPurpose::SIGN) + .purpose(KeyPurpose::VERIFY) + .digest(Digest::SHA_2_256) + .padding_mode(PaddingMode::RSA_PKCS1_1_5_SIGN) + .attestation_challenge(b"foo".to_vec()) + .device_unique_attestation(); + generate_device_unique_attested_key_with_device_attest_ids( + gen_params, + attest_id_tag, + prop_name, + ); +} + +fn add_attest_id_auth( + gen_params: authorizations::AuthSetBuilder, + attest_id_tag: Tag, + value: Vec, +) -> authorizations::AuthSetBuilder { + match attest_id_tag { + Tag::ATTESTATION_ID_BRAND => gen_params.attestation_device_brand(value), + Tag::ATTESTATION_ID_DEVICE => gen_params.attestation_device_name(value), + Tag::ATTESTATION_ID_PRODUCT => gen_params.attestation_device_product_name(value), + Tag::ATTESTATION_ID_SERIAL => gen_params.attestation_device_serial(value), + Tag::ATTESTATION_ID_MANUFACTURER => gen_params.attestation_device_manufacturer(value), + Tag::ATTESTATION_ID_MODEL => gen_params.attestation_device_model(value), + Tag::ATTESTATION_ID_IMEI => gen_params.attestation_device_imei(value), + Tag::ATTESTATION_ID_SECOND_IMEI => gen_params.attestation_device_second_imei(value), + _ => { + panic!("Unknown attestation id"); + } + } +} + +/// Generate a device unique attested key with attestation of the device's identifiers. Test should +/// succeed in generating a attested key with attestation of device identifiers. Test might fail on +/// devices which don't support device id attestation with error response code `CANNOT_ATTEST_IDS`. +fn generate_device_unique_attested_key_with_device_attest_ids( + gen_params: authorizations::AuthSetBuilder, + attest_id: Tag, + prop_name: &str, +) { + let keystore2 = get_keystore_service(); + let result = + key_generations::map_ks_error(keystore2.getSecurityLevel(SecurityLevel::STRONGBOX)); + if result.is_err() { + assert_eq!(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE), result.unwrap_err()); + return; + } + let sec_level = result.unwrap(); + + if attest_id == Tag::ATTESTATION_ID_SECOND_IMEI + && !is_second_imei_id_attestation_required(&keystore2) + { + return; + } + + if let Some(value) = get_attest_id_value(attest_id, prop_name) { + if value.is_empty() { + return; + } + let gen_params = add_attest_id_auth(gen_params, attest_id, value.clone()); + let alias = "ks_test_device_unique_attest_id_test"; + match key_generations::map_ks_error(key_generations::generate_key( + &sec_level, + &gen_params, + alias, + )) { + Ok(key_metadata) => { + let attest_id_value = get_value_from_attest_record( + key_metadata.certificate.as_ref().unwrap(), + attest_id, + key_metadata.keySecurityLevel, + ) + .expect("Attest id verification failed."); + assert_eq!(attest_id_value, value); + delete_app_key(&keystore2, alias).unwrap(); + } + Err(e) => { + assert_eq!(e, Error::Km(ErrorCode::CANNOT_ATTEST_IDS)); + } + } + } +} + +/// Try generate a key with `DEVICE_UNIQUE_ATTESTATION` using `TRUSTED_ENVIRONMENT` security level. +/// Test should fail to generate a key with error code `INVALID_ARGUMENT` +#[test] +fn keystore2_gen_key_device_unique_attest_with_default_sec_level_unimplemented() { + let keystore2 = get_keystore_service(); + let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap(); + + let gen_params = authorizations::AuthSetBuilder::new() + .no_auth_required() + .algorithm(Algorithm::EC) + .purpose(KeyPurpose::SIGN) + .purpose(KeyPurpose::VERIFY) + .digest(Digest::SHA_2_256) + .ec_curve(EcCurve::P_256) + .attestation_challenge(b"foo".to_vec()) + .device_unique_attestation(); + + let alias = "ks_test_auth_tags_test"; + let result = key_generations::map_ks_error(key_generations::generate_key( + &sec_level, + &gen_params, + alias, + )); + assert!(result.is_err()); + assert_eq!(Error::Km(ErrorCode::INVALID_ARGUMENT), result.unwrap_err()); +} + +/// Generate a EC key with `DEVICE_UNIQUE_ATTESTATION` using `STRONGBOX` security level. +/// Test should create a key successfully, verify key characteristics, cert-chain signatures and +/// use it for performing an operation. +#[test] +fn keystore2_gen_ec_key_device_unique_attest_with_strongbox_sec_level_test_success() { + let keystore2 = get_keystore_service(); + let result = + key_generations::map_ks_error(keystore2.getSecurityLevel(SecurityLevel::STRONGBOX)); + if result.is_err() { + assert_eq!(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE), result.unwrap_err()); + return; + } + + let sec_level = result.unwrap(); + let gen_params = authorizations::AuthSetBuilder::new() + .no_auth_required() + .algorithm(Algorithm::EC) + .purpose(KeyPurpose::SIGN) + .purpose(KeyPurpose::VERIFY) + .digest(Digest::SHA_2_256) + .ec_curve(EcCurve::P_256) + .attestation_challenge(b"foo".to_vec()) + .device_unique_attestation(); + + let alias = "ks_device_unique_ec_key_attest_test"; + match key_generations::map_ks_error(key_generations::generate_key( + &sec_level, + &gen_params, + alias, + )) { + Ok(key_metadata) => { + perform_sample_asym_sign_verify_op( + &sec_level, + &key_metadata, + None, + Some(Digest::SHA_2_256), + ); + delete_app_key(&keystore2, alias).unwrap(); + } + Err(e) => { + assert_eq!(e, Error::Km(ErrorCode::CANNOT_ATTEST_IDS)); + } + } +} + +/// Generate a RSA key with `DEVICE_UNIQUE_ATTESTATION` using `STRONGBOX` security level. +/// Test should create a key successfully, verify key characteristics, cert-chain signatures and +/// use it for performing an operation. +#[test] +fn keystore2_gen_rsa_key_device_unique_attest_with_strongbox_sec_level_test_success() { + let keystore2 = get_keystore_service(); + let result = + key_generations::map_ks_error(keystore2.getSecurityLevel(SecurityLevel::STRONGBOX)); + if result.is_err() { + assert_eq!(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE), result.unwrap_err()); + return; + } + + let sec_level = result.unwrap(); + let gen_params = authorizations::AuthSetBuilder::new() + .no_auth_required() + .algorithm(Algorithm::RSA) + .rsa_public_exponent(65537) + .key_size(2048) + .purpose(KeyPurpose::SIGN) + .purpose(KeyPurpose::VERIFY) + .digest(Digest::SHA_2_256) + .padding_mode(PaddingMode::RSA_PKCS1_1_5_SIGN) + .attestation_challenge(b"foo".to_vec()) + .device_unique_attestation(); + + let alias = "ks_device_unique_rsa_key_attest_test"; + match key_generations::map_ks_error(key_generations::generate_key( + &sec_level, + &gen_params, + alias, + )) { + Ok(key_metadata) => { + perform_sample_asym_sign_verify_op( + &sec_level, + &key_metadata, + Some(PaddingMode::RSA_PKCS1_1_5_SIGN), + Some(Digest::SHA_2_256), + ); + delete_app_key(&keystore2, alias).unwrap(); + } + Err(e) => { + assert_eq!(e, Error::Km(ErrorCode::CANNOT_ATTEST_IDS)); + } + } +} + +/// Try to generate a device unique attested key with attestation of invalid device's identifiers. +/// Test should fail with error response code `CANNOT_ATTEST_IDS`. +#[test] +fn keystore2_device_unique_attest_key_fails_with_invalid_attestation_id() { + let keystore2 = get_keystore_service(); + let result = + key_generations::map_ks_error(keystore2.getSecurityLevel(SecurityLevel::STRONGBOX)); + if result.is_err() { + assert_eq!(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE), result.unwrap_err()); + return; + } + + let sec_level = result.unwrap(); + let attest_id_params = vec![ + (Tag::ATTESTATION_ID_BRAND, b"invalid-brand".to_vec()), + (Tag::ATTESTATION_ID_DEVICE, b"invalid-device-name".to_vec()), + (Tag::ATTESTATION_ID_PRODUCT, b"invalid-product-name".to_vec()), + (Tag::ATTESTATION_ID_SERIAL, b"invalid-ro-serial".to_vec()), + (Tag::ATTESTATION_ID_MANUFACTURER, b"invalid-ro-product-manufacturer".to_vec()), + (Tag::ATTESTATION_ID_MODEL, b"invalid-ro-product-model".to_vec()), + (Tag::ATTESTATION_ID_IMEI, b"invalid-imei".to_vec()), + ]; + + for (attest_id, value) in attest_id_params { + let gen_params = authorizations::AuthSetBuilder::new() + .no_auth_required() + .algorithm(Algorithm::EC) + .purpose(KeyPurpose::SIGN) + .purpose(KeyPurpose::VERIFY) + .digest(Digest::SHA_2_256) + .ec_curve(EcCurve::P_256) + .attestation_challenge(b"foo".to_vec()) + .device_unique_attestation(); + let alias = "ks_ec_device_unique_attested_test_key_fail"; + let gen_params = add_attest_id_auth(gen_params, attest_id, value.clone()); + + let result = key_generations::map_ks_error(key_generations::generate_key( + &sec_level, + &gen_params, + alias, + )); + assert!(result.is_err()); + assert!(matches!(result.unwrap_err(), Error::Km(ErrorCode::CANNOT_ATTEST_IDS))); + } +} + +// Below macros generate tests for generating device unique attested EC keys with attestation +// of the device's identifiers. +test_ec_key_device_unique_attestation_id!( + keystore2_device_unique_attest_ecdsa_attest_id_brand, + Tag::ATTESTATION_ID_BRAND, + "ro.product.brand_for_attestation" +); +test_ec_key_device_unique_attestation_id!( + keystore2_device_unique_attest_ecdsa_attest_id_device, + Tag::ATTESTATION_ID_DEVICE, + "ro.product.device" +); +test_ec_key_device_unique_attestation_id!( + keystore2_device_unique_attest_ecdsa_attest_id_product, + Tag::ATTESTATION_ID_PRODUCT, + "ro.product.name_for_attestation" +); +test_ec_key_device_unique_attestation_id!( + keystore2_device_unique_attest_ecdsa_attest_id_serial, + Tag::ATTESTATION_ID_SERIAL, + "ro.serialno" +); +test_ec_key_device_unique_attestation_id!( + keystore2_device_unique_attest_ecdsa_attest_id_manufacturer, + Tag::ATTESTATION_ID_MANUFACTURER, + "ro.product.manufacturer" +); +test_ec_key_device_unique_attestation_id!( + keystore2_device_unique_attest_ecdsa_attest_id_model, + Tag::ATTESTATION_ID_MODEL, + "ro.product.model_for_attestation" +); +test_ec_key_device_unique_attestation_id!( + keystore2_device_unique_attest_ecdsa_attest_id_imei, + Tag::ATTESTATION_ID_IMEI, + "" +); +test_ec_key_device_unique_attestation_id!( + keystore2_device_unique_attest_ecdsa_attest_id_second_imei, + Tag::ATTESTATION_ID_SECOND_IMEI, + "" +); + +// Below macros generate tests for generating device unique attested RSA keys with attestation +// of the device's identifiers. +test_rsa_key_device_unique_attestation_id!( + keystore2_device_unique_attest_rsa_attest_id_brand, + Tag::ATTESTATION_ID_BRAND, + "ro.product.brand_for_attestation" +); +test_rsa_key_device_unique_attestation_id!( + keystore2_device_unique_attest_rsa_attest_id_device, + Tag::ATTESTATION_ID_DEVICE, + "ro.product.device" +); +test_rsa_key_device_unique_attestation_id!( + keystore2_device_unique_attest_rsa_attest_id_product, + Tag::ATTESTATION_ID_PRODUCT, + "ro.product.name_for_attestation" +); +test_rsa_key_device_unique_attestation_id!( + keystore2_device_unique_attest_rsa_attest_id_serial, + Tag::ATTESTATION_ID_SERIAL, + "ro.serialno" +); +test_rsa_key_device_unique_attestation_id!( + keystore2_device_unique_attest_rsa_attest_id_manufacturer, + Tag::ATTESTATION_ID_MANUFACTURER, + "ro.product.manufacturer" +); +test_rsa_key_device_unique_attestation_id!( + keystore2_device_unique_attest_rsa_attest_id_model, + Tag::ATTESTATION_ID_MODEL, + "ro.product.model_for_attestation" +); +test_rsa_key_device_unique_attestation_id!( + keystore2_device_unique_attest_rsa_attest_id_imei, + Tag::ATTESTATION_ID_IMEI, + "" +); +test_rsa_key_device_unique_attestation_id!( + keystore2_device_unique_attest_rsa_attest_id_second_imei, + Tag::ATTESTATION_ID_SECOND_IMEI, + "" +); diff --git a/keystore2/tests/keystore2_client_test_utils.rs b/keystore2/tests/keystore2_client_test_utils.rs index e76c64b8..364cec4e 100644 --- a/keystore2/tests/keystore2_client_test_utils.rs +++ b/keystore2/tests/keystore2_client_test_utils.rs @@ -517,30 +517,20 @@ pub fn get_attest_id_value(attest_id: Tag, prop_name: &str) -> Option> { match attest_id { Tag::ATTESTATION_ID_IMEI => get_imei(0), Tag::ATTESTATION_ID_SECOND_IMEI => get_imei(1), - Tag::ATTESTATION_ID_BRAND => { - let prop_val = get_system_prop(prop_name); - if prop_val.is_empty() { - Some(get_system_prop("ro.product.brand")) - } else { - Some(prop_val) - } - } - Tag::ATTESTATION_ID_PRODUCT => { - let prop_val = get_system_prop(prop_name); - if prop_val.is_empty() { - Some(get_system_prop("ro.product.name")) - } else { + Tag::ATTESTATION_ID_SERIAL => Some(get_system_prop(format!("ro.{}", prop_name).as_str())), + _ => { + let prop_val = + get_system_prop(format!("ro.product.{}_for_attestation", prop_name).as_str()); + if !prop_val.is_empty() { Some(prop_val) - } - } - Tag::ATTESTATION_ID_MODEL => { - let prop_val = get_system_prop(prop_name); - if prop_val.is_empty() { - Some(get_system_prop("ro.product.model")) } else { - Some(prop_val) + let prop_val = get_system_prop(format!("ro.product.vendor.{}", prop_name).as_str()); + if !prop_val.is_empty() { + Some(prop_val) + } else { + Some(get_system_prop(format!("ro.product.{}", prop_name).as_str())) + } } } - _ => Some(get_system_prop(prop_name)), } } diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs index ac7f19f8..a0c140a0 100644 --- a/keystore2/tests/keystore2_client_tests.rs +++ b/keystore2/tests/keystore2_client_tests.rs @@ -17,6 +17,7 @@ pub mod keystore2_client_aes_key_tests; pub mod keystore2_client_attest_key_tests; pub mod keystore2_client_authorizations_tests; pub mod keystore2_client_delete_key_tests; +pub mod keystore2_client_device_unique_attestation_tests; pub mod keystore2_client_ec_key_tests; pub mod keystore2_client_grant_key_tests; pub mod keystore2_client_hmac_key_tests; -- cgit v1.2.3