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 use crate::metrics_store::*;
16 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
17 HardwareAuthenticatorType::HardwareAuthenticatorType as AuthType, KeyParameter::KeyParameter,
18 KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel, Tag::Tag,
19 };
20 use android_security_metrics::aidl::android::security::metrics::{
21 HardwareAuthenticatorType::HardwareAuthenticatorType as MetricsAuthType,
22 SecurityLevel::SecurityLevel as MetricsSecurityLevel,
23 };
24
25 #[test]
test_enum_show()26 fn test_enum_show() {
27 let algo = MetricsAlgorithm::RSA;
28 assert_eq!("RSA ", algo.show());
29 let algo = MetricsAlgorithm(42);
30 assert_eq!("Unknown(42)", algo.show());
31 }
32
33 #[test]
test_enum_bitmask_show()34 fn test_enum_bitmask_show() {
35 let mut modes = 0i32;
36 compute_block_mode_bitmap(&mut modes, BlockMode::ECB);
37 compute_block_mode_bitmap(&mut modes, BlockMode::CTR);
38
39 assert_eq!(show_blockmode(modes), "-T-E");
40
41 // Add some bits not covered by the enum of valid bit positions.
42 modes |= 0xa0;
43 assert_eq!(show_blockmode(modes), "-T-E(full:0x000000aa)");
44 modes |= 0x300;
45 assert_eq!(show_blockmode(modes), "-T-E(full:0x000003aa)");
46 }
47
create_key_param_with_auth_type(auth_type: AuthType) -> KeyParameter48 fn create_key_param_with_auth_type(auth_type: AuthType) -> KeyParameter {
49 KeyParameter {
50 tag: Tag::USER_AUTH_TYPE,
51 value: KeyParameterValue::HardwareAuthenticatorType(auth_type),
52 }
53 }
54
55 #[test]
test_user_auth_type()56 fn test_user_auth_type() {
57 let test_cases = [
58 (vec![], MetricsAuthType::NO_AUTH_TYPE),
59 (vec![AuthType::NONE], MetricsAuthType::NONE),
60 (vec![AuthType::PASSWORD], MetricsAuthType::PASSWORD),
61 (vec![AuthType::FINGERPRINT], MetricsAuthType::FINGERPRINT),
62 (
63 vec![AuthType(AuthType::PASSWORD.0 | AuthType::FINGERPRINT.0)],
64 MetricsAuthType::PASSWORD_OR_FINGERPRINT,
65 ),
66 (vec![AuthType::ANY], MetricsAuthType::ANY),
67 // 7 is the "next" undefined HardwareAuthenticatorType enum tag number, so
68 // force this test to fail and be updated if someone adds a new enum value.
69 (vec![AuthType(7)], MetricsAuthType::AUTH_TYPE_UNSPECIFIED),
70 (vec![AuthType(123)], MetricsAuthType::AUTH_TYPE_UNSPECIFIED),
71 (
72 // In practice, Tag::USER_AUTH_TYPE isn't a repeatable tag. It's allowed
73 // to appear once for auth-bound keys and contains the binary OR of the
74 // applicable auth types. However, this test case repeats the tag more
75 // than once in order to unit test the logic that constructs the atom.
76 vec![AuthType::ANY, AuthType(123), AuthType::PASSWORD],
77 // The last auth type wins.
78 MetricsAuthType::PASSWORD,
79 ),
80 ];
81 for (auth_types, expected) in test_cases {
82 let key_params: Vec<_> =
83 auth_types.iter().map(|a| create_key_param_with_auth_type(*a)).collect();
84 let (_, atom_with_auth_info, _) = process_key_creation_event_stats(
85 SecurityLevel::TRUSTED_ENVIRONMENT,
86 &key_params,
87 &Ok(()),
88 );
89 assert!(matches!(
90 atom_with_auth_info,
91 KeystoreAtomPayload::KeyCreationWithAuthInfo(a) if a.user_auth_type == expected
92 ));
93 }
94 }
95
create_key_param_with_auth_timeout(timeout: i32) -> KeyParameter96 fn create_key_param_with_auth_timeout(timeout: i32) -> KeyParameter {
97 KeyParameter { tag: Tag::AUTH_TIMEOUT, value: KeyParameterValue::Integer(timeout) }
98 }
99
100 #[test]
test_log_auth_timeout_seconds()101 fn test_log_auth_timeout_seconds() {
102 let test_cases = [
103 (vec![], -1),
104 (vec![-1], 0),
105 // The metrics code computes the value of this field for a timeout `t` with
106 // `f32::log10(t as f32) as i32`. The result of f32::log10(0 as f32) is `-inf`.
107 // Casting this to i32 means it gets "rounded" to i32::MIN, which is -2147483648.
108 (vec![0], -2147483648),
109 (vec![1], 0),
110 (vec![9], 0),
111 (vec![10], 1),
112 (vec![999], 2),
113 (
114 // In practice, Tag::AUTH_TIMEOUT isn't a repeatable tag. It's allowed to
115 // appear once for auth-bound keys. However, this test case repeats the
116 // tag more than once in order to unit test the logic that constructs the
117 // atom.
118 vec![1, 0, 10],
119 // The last timeout wins.
120 1,
121 ),
122 ];
123 for (timeouts, expected) in test_cases {
124 let key_params: Vec<_> =
125 timeouts.iter().map(|t| create_key_param_with_auth_timeout(*t)).collect();
126 let (_, atom_with_auth_info, _) = process_key_creation_event_stats(
127 SecurityLevel::TRUSTED_ENVIRONMENT,
128 &key_params,
129 &Ok(()),
130 );
131 assert!(matches!(
132 atom_with_auth_info,
133 KeystoreAtomPayload::KeyCreationWithAuthInfo(a)
134 if a.log10_auth_key_timeout_seconds == expected
135 ));
136 }
137 }
138
139 #[test]
test_security_level()140 fn test_security_level() {
141 let test_cases = [
142 (SecurityLevel::SOFTWARE, MetricsSecurityLevel::SECURITY_LEVEL_SOFTWARE),
143 (
144 SecurityLevel::TRUSTED_ENVIRONMENT,
145 MetricsSecurityLevel::SECURITY_LEVEL_TRUSTED_ENVIRONMENT,
146 ),
147 (SecurityLevel::STRONGBOX, MetricsSecurityLevel::SECURITY_LEVEL_STRONGBOX),
148 (SecurityLevel::KEYSTORE, MetricsSecurityLevel::SECURITY_LEVEL_KEYSTORE),
149 (SecurityLevel(123), MetricsSecurityLevel::SECURITY_LEVEL_UNSPECIFIED),
150 ];
151 for (security_level, expected) in test_cases {
152 let (_, atom_with_auth_info, _) =
153 process_key_creation_event_stats(security_level, &[], &Ok(()));
154 assert!(matches!(
155 atom_with_auth_info,
156 KeystoreAtomPayload::KeyCreationWithAuthInfo(a)
157 if a.security_level == expected
158 ));
159 }
160 }
161