blob: 76a96a71248b90281a73267ebe7b5c82eeef97be [file] [log] [blame]
David Drysdale2566fb32024-07-09 14:46:37 +01001// 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//! Super-key tests.
16
17use super::*;
18use crate::database::tests::make_bootlevel_key_entry;
19use crate::database::tests::make_test_key_entry;
20use crate::database::tests::new_test_db;
21use rand::prelude::*;
22const USER_ID: u32 = 0;
23const TEST_KEY_ALIAS: &str = "TEST_KEY";
24const TEST_BOOT_KEY_ALIAS: &str = "TEST_BOOT_KEY";
25
26pub fn generate_password_blob() -> Password<'static> {
27 let mut rng = rand::thread_rng();
28 let mut password = vec![0u8; 64];
29 rng.fill_bytes(&mut password);
30
31 let mut zvec = ZVec::new(64).expect("Failed to create ZVec");
32 zvec[..].copy_from_slice(&password[..]);
33
34 Password::Owned(zvec)
35}
36
37fn setup_test(pw: &Password) -> (Arc<RwLock<SuperKeyManager>>, KeystoreDB, LegacyImporter) {
38 let mut keystore_db = new_test_db().unwrap();
39 let mut legacy_importer = LegacyImporter::new(Arc::new(Default::default()));
40 legacy_importer.set_empty();
41 let skm: Arc<RwLock<SuperKeyManager>> = Default::default();
42 assert!(skm
43 .write()
44 .unwrap()
45 .initialize_user(&mut keystore_db, &legacy_importer, USER_ID, pw, false)
46 .is_ok());
47 (skm, keystore_db, legacy_importer)
48}
49
50fn assert_unlocked(
51 skm: &Arc<RwLock<SuperKeyManager>>,
52 keystore_db: &mut KeystoreDB,
53 legacy_importer: &LegacyImporter,
54 user_id: u32,
55 err_msg: &str,
56) {
57 let user_state =
58 skm.write().unwrap().get_user_state(keystore_db, legacy_importer, user_id).unwrap();
59 match user_state {
60 UserState::AfterFirstUnlock(_) => {}
61 _ => panic!("{}", err_msg),
62 }
63}
64
65fn assert_locked(
66 skm: &Arc<RwLock<SuperKeyManager>>,
67 keystore_db: &mut KeystoreDB,
68 legacy_importer: &LegacyImporter,
69 user_id: u32,
70 err_msg: &str,
71) {
72 let user_state =
73 skm.write().unwrap().get_user_state(keystore_db, legacy_importer, user_id).unwrap();
74 match user_state {
75 UserState::BeforeFirstUnlock => {}
76 _ => panic!("{}", err_msg),
77 }
78}
79
80fn assert_uninitialized(
81 skm: &Arc<RwLock<SuperKeyManager>>,
82 keystore_db: &mut KeystoreDB,
83 legacy_importer: &LegacyImporter,
84 user_id: u32,
85 err_msg: &str,
86) {
87 let user_state =
88 skm.write().unwrap().get_user_state(keystore_db, legacy_importer, user_id).unwrap();
89 match user_state {
90 UserState::Uninitialized => {}
91 _ => panic!("{}", err_msg),
92 }
93}
94
95#[test]
96fn test_initialize_user() {
97 let pw: Password = generate_password_blob();
98 let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
99 assert_unlocked(
100 &skm,
101 &mut keystore_db,
102 &legacy_importer,
103 USER_ID,
104 "The user was not unlocked after initialization!",
105 );
106}
107
108#[test]
109fn test_unlock_user() {
110 let pw: Password = generate_password_blob();
111 let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
112 assert_unlocked(
113 &skm,
114 &mut keystore_db,
115 &legacy_importer,
116 USER_ID,
117 "The user was not unlocked after initialization!",
118 );
119
120 skm.write().unwrap().data.user_keys.clear();
121 assert_locked(
122 &skm,
123 &mut keystore_db,
124 &legacy_importer,
125 USER_ID,
126 "Clearing the cache did not lock the user!",
127 );
128
129 assert!(skm
130 .write()
131 .unwrap()
132 .unlock_user(&mut keystore_db, &legacy_importer, USER_ID, &pw)
133 .is_ok());
134 assert_unlocked(&skm, &mut keystore_db, &legacy_importer, USER_ID, "The user did not unlock!");
135}
136
137#[test]
138fn test_unlock_wrong_password() {
139 let pw: Password = generate_password_blob();
140 let wrong_pw: Password = generate_password_blob();
141 let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
142 assert_unlocked(
143 &skm,
144 &mut keystore_db,
145 &legacy_importer,
146 USER_ID,
147 "The user was not unlocked after initialization!",
148 );
149
150 skm.write().unwrap().data.user_keys.clear();
151 assert_locked(
152 &skm,
153 &mut keystore_db,
154 &legacy_importer,
155 USER_ID,
156 "Clearing the cache did not lock the user!",
157 );
158
159 assert!(skm
160 .write()
161 .unwrap()
162 .unlock_user(&mut keystore_db, &legacy_importer, USER_ID, &wrong_pw)
163 .is_err());
164 assert_locked(
165 &skm,
166 &mut keystore_db,
167 &legacy_importer,
168 USER_ID,
169 "The user was unlocked with an incorrect password!",
170 );
171}
172
173#[test]
174fn test_unlock_user_idempotent() {
175 let pw: Password = generate_password_blob();
176 let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
177 assert_unlocked(
178 &skm,
179 &mut keystore_db,
180 &legacy_importer,
181 USER_ID,
182 "The user was not unlocked after initialization!",
183 );
184
185 skm.write().unwrap().data.user_keys.clear();
186 assert_locked(
187 &skm,
188 &mut keystore_db,
189 &legacy_importer,
190 USER_ID,
191 "Clearing the cache did not lock the user!",
192 );
193
194 for _ in 0..5 {
195 assert!(skm
196 .write()
197 .unwrap()
198 .unlock_user(&mut keystore_db, &legacy_importer, USER_ID, &pw)
199 .is_ok());
200 assert_unlocked(
201 &skm,
202 &mut keystore_db,
203 &legacy_importer,
204 USER_ID,
205 "The user did not unlock!",
206 );
207 }
208}
209
210fn test_user_removal(locked: bool) {
211 let pw: Password = generate_password_blob();
212 let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
213 assert_unlocked(
214 &skm,
215 &mut keystore_db,
216 &legacy_importer,
217 USER_ID,
218 "The user was not unlocked after initialization!",
219 );
220
221 assert!(make_test_key_entry(
222 &mut keystore_db,
223 Domain::APP,
224 USER_ID.into(),
225 TEST_KEY_ALIAS,
226 None
227 )
228 .is_ok());
229 assert!(make_bootlevel_key_entry(
230 &mut keystore_db,
231 Domain::APP,
232 USER_ID.into(),
233 TEST_BOOT_KEY_ALIAS,
234 false
235 )
236 .is_ok());
237
238 assert!(keystore_db
239 .key_exists(Domain::APP, USER_ID.into(), TEST_KEY_ALIAS, KeyType::Client)
240 .unwrap());
241 assert!(keystore_db
242 .key_exists(Domain::APP, USER_ID.into(), TEST_BOOT_KEY_ALIAS, KeyType::Client)
243 .unwrap());
244
245 if locked {
246 skm.write().unwrap().data.user_keys.clear();
247 assert_locked(
248 &skm,
249 &mut keystore_db,
250 &legacy_importer,
251 USER_ID,
252 "Clearing the cache did not lock the user!",
253 );
254 }
255
256 assert!(skm.write().unwrap().remove_user(&mut keystore_db, &legacy_importer, USER_ID).is_ok());
257 assert_uninitialized(
258 &skm,
259 &mut keystore_db,
260 &legacy_importer,
261 USER_ID,
262 "The user was not removed!",
263 );
264
265 assert!(!skm
266 .write()
267 .unwrap()
268 .super_key_exists_in_db_for_user(&mut keystore_db, &legacy_importer, USER_ID)
269 .unwrap());
270
271 assert!(!keystore_db
272 .key_exists(Domain::APP, USER_ID.into(), TEST_KEY_ALIAS, KeyType::Client)
273 .unwrap());
274 assert!(!keystore_db
275 .key_exists(Domain::APP, USER_ID.into(), TEST_BOOT_KEY_ALIAS, KeyType::Client)
276 .unwrap());
277}
278
279#[test]
280fn test_remove_unlocked_user() {
281 test_user_removal(false);
282}
283
284#[test]
285fn test_remove_locked_user() {
286 test_user_removal(true);
287}