diff options
author | Rajesh Nyamagoud <nyamagoud@google.com> | 2023-05-11 00:31:40 +0000 |
---|---|---|
committer | Rajesh Nyamagoud <nyamagoud@google.com> | 2023-10-09 21:10:00 +0000 |
commit | 75dfa0c2ec8c93cc5b064838401fef32a07147ab (patch) | |
tree | c2ee5c30676ba43f9aa0269e21964623081230d8 /keystore2/test_utils | |
parent | 3363996eafe6f49817a6f7bed409e37c735021bb (diff) | |
download | security-75dfa0c2ec8c93cc5b064838401fef32a07147ab.tar.gz |
Adding tests using tags ACTIVE_DATETIME, ORIGINATION_EXPIRE_DATETIME,
USAGE_EXPIRE_DATETIME.
1. Tests will generate a key with current date and time set to
active-datetime and verify the key characteristics. Test will use
this key to create a sign operation successfully.
2. Test will generate a key with future date set to active-datetime and
verify the key characteristics. Test will fail with error code
`KEY_NOT_YET_VALID` while creating an operation using generated key.
3. Tests will generate a key with future date and time set to
origination-expire-datetime and verify the key characteristics. Test
will use this key to create a sign operation successfully.
4. Test will generate a key with current date and time set to
origination-expire-datetime and verify the key characteristics. Test
will fail with error code `KEY_EXPIRED` while creating an operation
using generated key.
5. Tests will generate a key with future date and time set to
usage-expire-datetime and verify the key characteristics. Test
will use this key to successfully verify the signature created using
this key.
6. Tests will generate a key with current date and time set to
usage-expire-datetime and verify the key characteristics. Test
will fail with error code `KEY_EXPIRED` while verifying the signature
created using this key.
7. Test will generate a AES key with future date and time set to
usage-expire-datetime and verify the key characteristics. Test
will perform encrypt and decrypt operations using this generated key
successfully.
8. Test will generate a AES key with current date and time set to
usage-expire-datetime and verify the key characteristics. Test
will fail with error code `KEY_EXPIRED` while creating Decrypt
operation using generated key.
Bug: 279721870
Test: atest keystore2_client_tests
Change-Id: I8a0865a6256a6da133e95d0ee8250ba67359a2a2
Diffstat (limited to 'keystore2/test_utils')
-rw-r--r-- | keystore2/test_utils/Android.bp | 2 | ||||
-rw-r--r-- | keystore2/test_utils/authorizations.rs | 27 | ||||
-rw-r--r-- | keystore2/test_utils/ffi_test_utils.cpp | 13 | ||||
-rw-r--r-- | keystore2/test_utils/ffi_test_utils.hpp | 3 | ||||
-rw-r--r-- | keystore2/test_utils/ffi_test_utils.rs | 18 | ||||
-rw-r--r-- | keystore2/test_utils/key_generations.rs | 150 |
6 files changed, 196 insertions, 17 deletions
diff --git a/keystore2/test_utils/Android.bp b/keystore2/test_utils/Android.bp index 9f3a4e90..a3c40cb4 100644 --- a/keystore2/test_utils/Android.bp +++ b/keystore2/test_utils/Android.bp @@ -35,6 +35,7 @@ rust_defaults { "liblog_rust", "libnix", "librand", + "librustutils", "libserde", "libserde_cbor", "libthiserror", @@ -82,7 +83,6 @@ cc_library_static { shared_libs: [ "libbase", "libcrypto", - "libcppbor_external", "libkeymaster_portable", "libkeystore-engine", "libkeymint_support", diff --git a/keystore2/test_utils/authorizations.rs b/keystore2/test_utils/authorizations.rs index 514cbd3b..aa75982c 100644 --- a/keystore2/test_utils/authorizations.rs +++ b/keystore2/test_utils/authorizations.rs @@ -242,6 +242,33 @@ impl AuthSetBuilder { }); self } + + /// Set active date-time. + pub fn active_date_time(mut self, date: i64) -> Self { + self.0.push(KeyParameter { + tag: Tag::ACTIVE_DATETIME, + value: KeyParameterValue::DateTime(date), + }); + self + } + + /// Set origination expire date-time. + pub fn origination_expire_date_time(mut self, date: i64) -> Self { + self.0.push(KeyParameter { + tag: Tag::ORIGINATION_EXPIRE_DATETIME, + value: KeyParameterValue::DateTime(date), + }); + self + } + + /// Set usage expire date-time. + pub fn usage_expire_date_time(mut self, date: i64) -> Self { + self.0.push(KeyParameter { + tag: Tag::USAGE_EXPIRE_DATETIME, + value: KeyParameterValue::DateTime(date), + }); + self + } } impl Deref for AuthSetBuilder { diff --git a/keystore2/test_utils/ffi_test_utils.cpp b/keystore2/test_utils/ffi_test_utils.cpp index 1853c079..07408044 100644 --- a/keystore2/test_utils/ffi_test_utils.cpp +++ b/keystore2/test_utils/ffi_test_utils.cpp @@ -8,6 +8,7 @@ #include <keymaster/km_openssl/openssl_err.h> #include <keymaster/km_openssl/openssl_utils.h> #include <keymint_support/attestation_record.h> +#include <keymint_support/keymint_utils.h> #include <openssl/mem.h> using keymaster::ASN1_OBJECT_Ptr; @@ -696,3 +697,15 @@ CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) { std::move(val.begin(), val.end(), std::back_inserter(cxx_result.data)); return cxx_result; } + +uint32_t getOsVersion() { + return aidl::android::hardware::security::keymint::getOsVersion(); +} + +uint32_t getOsPatchlevel() { + return aidl::android::hardware::security::keymint::getOsPatchlevel(); +} + +uint32_t getVendorPatchlevel() { + return aidl::android::hardware::security::keymint::getVendorPatchlevel(); +} diff --git a/keystore2/test_utils/ffi_test_utils.hpp b/keystore2/test_utils/ffi_test_utils.hpp index 3ed7edc1..69f558a0 100644 --- a/keystore2/test_utils/ffi_test_utils.hpp +++ b/keystore2/test_utils/ffi_test_utils.hpp @@ -11,3 +11,6 @@ CxxResult createWrappedKey(rust::Vec<rust::u8> encrypted_secure_key, CxxResult buildAsn1DerEncodedWrappedKeyDescription(); bool performCryptoOpUsingKeystoreEngine(int64_t grant_id); CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag); +uint32_t getOsVersion(); +uint32_t getOsPatchlevel(); +uint32_t getVendorPatchlevel(); diff --git a/keystore2/test_utils/ffi_test_utils.rs b/keystore2/test_utils/ffi_test_utils.rs index 95e3160b..04d82f11 100644 --- a/keystore2/test_utils/ffi_test_utils.rs +++ b/keystore2/test_utils/ffi_test_utils.rs @@ -36,6 +36,9 @@ mod ffi { fn buildAsn1DerEncodedWrappedKeyDescription() -> CxxResult; fn performCryptoOpUsingKeystoreEngine(grant_id: i64) -> bool; fn getValueFromAttestRecord(cert_buf: Vec<u8>, tag: i32) -> CxxResult; + fn getOsVersion() -> u32; + fn getOsPatchlevel() -> u32; + fn getVendorPatchlevel() -> u32; } } @@ -102,3 +105,18 @@ pub fn get_value_from_attest_record(cert_buf: &[u8], tag: Tag) -> Result<Vec<u8> } Err(Error::AttestRecordGetValueFailed) } + +/// Get OS Version +pub fn get_os_version() -> u32 { + ffi::getOsVersion() +} + +/// Get OS Patch Level +pub fn get_os_patchlevel() -> u32 { + ffi::getOsPatchlevel() +} + +/// Get vendor Patch Level +pub fn get_vendor_patchlevel() -> u32 { + ffi::getVendorPatchlevel() +} diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs index 0f9ecbe0..24ce6e19 100644 --- a/keystore2/test_utils/key_generations.rs +++ b/keystore2/test_utils/key_generations.rs @@ -15,11 +15,13 @@ //! This module implements test utils to generate various types of keys. use anyhow::Result; - use core::ops::Range; +use nix::unistd::getuid; use std::collections::HashSet; use std::fmt::Write; +use binder::ThreadState; + use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve, ErrorCode::ErrorCode, HardwareAuthenticatorType::HardwareAuthenticatorType, @@ -27,7 +29,8 @@ use android_hardware_security_keymint::aidl::android::hardware::security::keymin KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, Tag::Tag, }; use android_system_keystore2::aidl::android::system::keystore2::{ - AuthenticatorSpec::AuthenticatorSpec, Authorization::Authorization, Domain::Domain, + AuthenticatorSpec::AuthenticatorSpec, Authorization::Authorization, + CreateOperationResponse::CreateOperationResponse, Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor, KeyMetadata::KeyMetadata, ResponseCode::ResponseCode, }; @@ -35,6 +38,8 @@ use android_system_keystore2::aidl::android::system::keystore2::{ use crate::authorizations::AuthSetBuilder; use android_system_keystore2::binder::{ExceptionCode, Result as BinderResult}; +use crate::ffi_test_utils::{get_os_patchlevel, get_os_version, get_vendor_patchlevel}; + /// Shell namespace. pub const SELINUX_SHELL_NAMESPACE: i64 = 1; /// Vold namespace. @@ -388,7 +393,12 @@ pub fn check_key_param(authorizations: &[Authorization], key_param: &KeyParamete authorizations.iter().any(|auth| &auth.keyParameter == key_param) } -fn check_key_authorizations(authorizations: &[Authorization], expected_params: &[KeyParameter]) { +/// Verify the given key authorizations with the expected authorizations. +pub fn check_key_authorizations( + authorizations: &[Authorization], + expected_params: &[KeyParameter], + expected_key_origin: KeyOrigin, +) { // Make sure key authorizations contains only `ALLOWED_TAGS_IN_KEY_AUTHS` authorizations.iter().all(|auth| { assert!( @@ -410,6 +420,54 @@ fn check_key_authorizations(authorizations: &[Authorization], expected_params: & } true }); + + check_common_auths(authorizations, expected_key_origin); +} + +/// Verify common key authorizations. +fn check_common_auths(authorizations: &[Authorization], expected_key_origin: KeyOrigin) { + assert!(check_key_param( + authorizations, + &KeyParameter { + tag: Tag::OS_VERSION, + value: KeyParameterValue::Integer(get_os_version().try_into().unwrap()) + } + )); + assert!(check_key_param( + authorizations, + &KeyParameter { + tag: Tag::OS_PATCHLEVEL, + value: KeyParameterValue::Integer(get_os_patchlevel().try_into().unwrap()) + } + )); + + // Access denied for finding vendor-patch-level ("ro.vendor.build.security_patch") property + // in a test running with `untrusted_app` context. Keeping this check to verify + // vendor-patch-level in tests running with `su` context. + if getuid().is_root() { + assert!(check_key_param( + authorizations, + &KeyParameter { + tag: Tag::VENDOR_PATCHLEVEL, + value: KeyParameterValue::Integer(get_vendor_patchlevel().try_into().unwrap()) + } + )); + } + assert!(check_key_param( + authorizations, + &KeyParameter { tag: Tag::ORIGIN, value: KeyParameterValue::Origin(expected_key_origin) } + )); + assert!(check_key_param( + authorizations, + &KeyParameter { + tag: Tag::USER_ID, + value: KeyParameterValue::Integer( + rustutils::users::multiuser_get_user_id(ThreadState::get_calling_uid()) + .try_into() + .unwrap() + ) + } + )); } /// Generate EC Key using given security level and domain with below key parameters and @@ -455,7 +513,11 @@ pub fn generate_ec_p256_signing_key( assert!(key_metadata.key.blob.is_some()); } - check_key_authorizations(&key_metadata.authorizations, &gen_params); + check_key_authorizations( + &key_metadata.authorizations, + &gen_params, + KeyOrigin::GENERATED, + ); Ok(key_metadata) } Err(e) => Err(e), @@ -498,7 +560,7 @@ pub fn generate_ec_key( } else { assert!(key_metadata.key.blob.is_none()); } - check_key_authorizations(&key_metadata.authorizations, &gen_params); + check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED); Ok(key_metadata) } @@ -560,7 +622,7 @@ pub fn generate_rsa_key( || key_metadata.key.blob.is_none() ); - check_key_authorizations(&key_metadata.authorizations, &gen_params); + check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED); // If `RSA_OAEP_MGF_DIGEST` tag is not mentioned explicitly while generating/importing a key, // then make sure `RSA_OAEP_MGF_DIGEST` tag with default value (SHA1) must not be included in // key authorization list. @@ -617,7 +679,7 @@ pub fn generate_sym_key( // Should not have an attestation record. assert!(key_metadata.certificateChain.is_none()); - check_key_authorizations(&key_metadata.authorizations, &gen_params); + check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED); Ok(key_metadata) } @@ -657,7 +719,7 @@ pub fn generate_hmac_key( // Should not have an attestation record. assert!(key_metadata.certificateChain.is_none()); - check_key_authorizations(&key_metadata.authorizations, &gen_params); + check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED); Ok(key_metadata) } @@ -742,7 +804,11 @@ pub fn generate_ec_attestation_key( // Should have an attestation record. assert!(attestation_key_metadata.certificateChain.is_some()); - check_key_authorizations(&attestation_key_metadata.authorizations, &gen_params); + check_key_authorizations( + &attestation_key_metadata.authorizations, + &gen_params, + KeyOrigin::GENERATED, + ); Ok(attestation_key_metadata) } @@ -777,7 +843,7 @@ pub fn generate_ec_256_attested_key( // Shouldn't have an attestation record. assert!(ec_key_metadata.certificateChain.is_none()); - check_key_authorizations(&ec_key_metadata.authorizations, &ec_gen_params); + check_key_authorizations(&ec_key_metadata.authorizations, &ec_gen_params, KeyOrigin::GENERATED); Ok(ec_key_metadata) } @@ -802,7 +868,7 @@ pub fn import_rsa_2048_key( assert!(key_metadata.certificate.is_some()); assert!(key_metadata.certificateChain.is_none()); - check_key_authorizations(&key_metadata.authorizations, &import_params); + check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED); // Check below auths explicitly, they might not be addd in import parameters. assert!(check_key_param( @@ -865,7 +931,7 @@ pub fn import_ec_p_256_key( assert!(key_metadata.certificate.is_some()); assert!(key_metadata.certificateChain.is_none()); - check_key_authorizations(&key_metadata.authorizations, &import_params); + check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED); // Check below auths explicitly, they might not be addd in import parameters. assert!(check_key_param( @@ -917,7 +983,7 @@ pub fn import_aes_key( AES_KEY, )?; - check_key_authorizations(&key_metadata.authorizations, &import_params); + check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED); // Check below auths explicitly, they might not be addd in import parameters. assert!(check_key_param( @@ -976,7 +1042,7 @@ pub fn import_3des_key( TRIPLE_DES_KEY, )?; - check_key_authorizations(&key_metadata.authorizations, &import_params); + check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED); // Check below auths explicitly, they might not be addd in import parameters. assert!(check_key_param( @@ -1036,7 +1102,7 @@ pub fn import_hmac_key( HMAC_KEY, )?; - check_key_authorizations(&key_metadata.authorizations, &import_params); + check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED); // Check below auths explicitly, they might not be addd in import parameters. assert!(check_key_param( @@ -1188,7 +1254,11 @@ pub fn generate_ec_agree_key( assert!(key_metadata.key.blob.is_some()); } - check_key_authorizations(&key_metadata.authorizations, &gen_params); + check_key_authorizations( + &key_metadata.authorizations, + &gen_params, + KeyOrigin::GENERATED, + ); Ok(key_metadata) } Err(e) => Err(e), @@ -1288,3 +1358,51 @@ pub fn generate_key_with_attest_id( b"entropy", ) } + +/// Generate Key and validate key characteristics. +pub fn generate_key( + sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, + gen_params: &AuthSetBuilder, + alias: &str, +) -> binder::Result<KeyMetadata> { + let key_metadata = sec_level.generateKey( + &KeyDescriptor { + domain: Domain::APP, + nspace: -1, + alias: Some(alias.to_string()), + blob: None, + }, + None, + gen_params, + 0, + b"entropy", + )?; + + if gen_params.iter().any(|kp| { + matches!( + kp.value, + KeyParameterValue::Algorithm(Algorithm::RSA) + | KeyParameterValue::Algorithm(Algorithm::EC) + ) + }) { + assert!(key_metadata.certificate.is_some()); + if gen_params.iter().any(|kp| kp.tag == Tag::ATTESTATION_CHALLENGE) { + assert!(key_metadata.certificateChain.is_some()); + } + } + check_key_authorizations(&key_metadata.authorizations, gen_params, KeyOrigin::GENERATED); + + Ok(key_metadata) +} + +/// Generate a key using given authorizations and create an operation using the generated key. +pub fn create_key_and_operation( + sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, + gen_params: &AuthSetBuilder, + op_params: &AuthSetBuilder, + alias: &str, +) -> binder::Result<CreateOperationResponse> { + let key_metadata = generate_key(sec_level, gen_params, alias)?; + + sec_level.createOperation(&key_metadata.key, op_params, false) +} |