• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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