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 //! Super-key tests.
16
17 use super::*;
18 use crate::database::tests::make_bootlevel_key_entry;
19 use crate::database::tests::make_test_key_entry;
20 use crate::database::tests::new_test_db;
21 use rand::prelude::*;
22 const USER_ID: u32 = 0;
23 const TEST_KEY_ALIAS: &str = "TEST_KEY";
24 const TEST_BOOT_KEY_ALIAS: &str = "TEST_BOOT_KEY";
25
generate_password_blob() -> Password<'static>26 pub 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
setup_test(pw: &Password) -> (Arc<RwLock<SuperKeyManager>>, KeystoreDB, LegacyImporter)37 fn 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
assert_unlocked( skm: &Arc<RwLock<SuperKeyManager>>, keystore_db: &mut KeystoreDB, legacy_importer: &LegacyImporter, user_id: u32, err_msg: &str, )50 fn 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
assert_locked( skm: &Arc<RwLock<SuperKeyManager>>, keystore_db: &mut KeystoreDB, legacy_importer: &LegacyImporter, user_id: u32, err_msg: &str, )65 fn 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
assert_uninitialized( skm: &Arc<RwLock<SuperKeyManager>>, keystore_db: &mut KeystoreDB, legacy_importer: &LegacyImporter, user_id: u32, err_msg: &str, )80 fn 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]
test_initialize_user()96 fn 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]
test_unlock_user()109 fn 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]
test_unlock_wrong_password()138 fn 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]
test_unlock_user_idempotent()174 fn 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
test_user_removal(locked: bool)210 fn 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]
test_remove_unlocked_user()280 fn test_remove_unlocked_user() {
281 test_user_removal(false);
282 }
283
284 #[test]
test_remove_locked_user()285 fn test_remove_locked_user() {
286 test_user_removal(true);
287 }
288