xref: /aosp_15_r20/system/security/keystore2/src/legacy_blob/tests.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
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 //! Tests for legacy keyblob processing.
16 
17 #![allow(dead_code)]
18 use super::*;
19 use crate::legacy_blob::test_utils::legacy_blob_test_vectors::*;
20 use crate::legacy_blob::test_utils::*;
21 use anyhow::{anyhow, Result};
22 use keystore2_crypto::aes_gcm_decrypt;
23 use keystore2_test_utils::TempDir;
24 use rand::Rng;
25 use std::convert::TryInto;
26 use std::ops::Deref;
27 use std::string::FromUtf8Error;
28 
29 #[test]
decode_encode_alias_test()30 fn decode_encode_alias_test() {
31     static ALIAS: &str = "#({}test[])��";
32     static ENCODED_ALIAS: &str = "+S+X{}test[]+Y.`-O-H-G";
33     // Second multi byte out of range ------v
34     static ENCODED_ALIAS_ERROR1: &str = "+S+{}test[]+Y";
35     // Incomplete multi byte ------------------------v
36     static ENCODED_ALIAS_ERROR2: &str = "+S+X{}test[]+";
37     // Our encoding: ".`-O-H-G"
38     // is UTF-8: 0xF0 0x9F 0x98 0x97
39     // is UNICODE: U+1F617
40     // is ��
41     // But +H below is a valid encoding for 0x18 making this sequence invalid UTF-8.
42     static ENCODED_ALIAS_ERROR_UTF8: &str = ".`-O+H-G";
43 
44     assert_eq!(ENCODED_ALIAS, &LegacyBlobLoader::encode_alias(ALIAS));
45     assert_eq!(ALIAS, &LegacyBlobLoader::decode_alias(ENCODED_ALIAS).unwrap());
46     assert_eq!(
47         Some(&Error::BadEncoding),
48         LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR1)
49             .unwrap_err()
50             .root_cause()
51             .downcast_ref::<Error>()
52     );
53     assert_eq!(
54         Some(&Error::BadEncoding),
55         LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR2)
56             .unwrap_err()
57             .root_cause()
58             .downcast_ref::<Error>()
59     );
60     assert!(LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR_UTF8)
61         .unwrap_err()
62         .root_cause()
63         .downcast_ref::<FromUtf8Error>()
64         .is_some());
65 
66     for _i in 0..100 {
67         // Any valid UTF-8 string should be en- and decoded without loss.
68         let alias_str = rand::thread_rng().gen::<[char; 20]>().iter().collect::<String>();
69         let random_alias = alias_str.as_bytes();
70         let encoded = LegacyBlobLoader::encode_alias(&alias_str);
71         let decoded = match LegacyBlobLoader::decode_alias(&encoded) {
72             Ok(d) => d,
73             Err(_) => panic!("random_alias: {:x?}\nencoded {}", random_alias, encoded),
74         };
75         assert_eq!(random_alias.to_vec(), decoded.bytes().collect::<Vec<u8>>());
76     }
77 }
78 
79 #[test]
read_golden_key_blob_test() -> anyhow::Result<()>80 fn read_golden_key_blob_test() -> anyhow::Result<()> {
81     let blob = LegacyBlobLoader::new_from_stream_decrypt_with(&mut &*BLOB, |_, _, _, _, _| {
82         Err(anyhow!("should not be called"))
83     })
84     .unwrap();
85     assert!(!blob.is_encrypted());
86     assert!(!blob.is_fallback());
87     assert!(!blob.is_strongbox());
88     assert!(!blob.is_critical_to_device_encryption());
89     assert_eq!(blob.value(), &BlobValue::Generic([0xde, 0xed, 0xbe, 0xef].to_vec()));
90 
91     let blob =
92         LegacyBlobLoader::new_from_stream_decrypt_with(&mut &*REAL_LEGACY_BLOB, |_, _, _, _, _| {
93             Err(anyhow!("should not be called"))
94         })
95         .unwrap();
96     assert!(!blob.is_encrypted());
97     assert!(!blob.is_fallback());
98     assert!(!blob.is_strongbox());
99     assert!(!blob.is_critical_to_device_encryption());
100     assert_eq!(blob.value(), &BlobValue::Decrypted(REAL_LEGACY_BLOB_PAYLOAD.try_into().unwrap()));
101     Ok(())
102 }
103 
104 #[test]
read_aes_gcm_encrypted_key_blob_test()105 fn read_aes_gcm_encrypted_key_blob_test() {
106     let blob = LegacyBlobLoader::new_from_stream_decrypt_with(
107         &mut &*AES_GCM_ENCRYPTED_BLOB,
108         |d, iv, tag, salt, key_size| {
109             assert_eq!(salt, None);
110             assert_eq!(key_size, None);
111             assert_eq!(
112                 iv,
113                 &[
114                     0xbd, 0xdb, 0x8d, 0x69, 0x72, 0x56, 0xf0, 0xf5, 0xa4, 0x02, 0x88, 0x7f, 0x00,
115                     0x00, 0x00, 0x00,
116                 ]
117             );
118             assert_eq!(
119                 tag,
120                 &[
121                     0x50, 0xd9, 0x97, 0x95, 0x37, 0x6e, 0x28, 0x6a, 0x28, 0x9d, 0x51, 0xb9, 0xb9,
122                     0xe0, 0x0b, 0xc3
123                 ][..]
124             );
125             aes_gcm_decrypt(d, iv, tag, AES_KEY).context("Trying to decrypt blob.")
126         },
127     )
128     .unwrap();
129     assert!(blob.is_encrypted());
130     assert!(!blob.is_fallback());
131     assert!(!blob.is_strongbox());
132     assert!(!blob.is_critical_to_device_encryption());
133 
134     assert_eq!(blob.value(), &BlobValue::Decrypted(DECRYPTED_PAYLOAD.try_into().unwrap()));
135 }
136 
137 #[test]
read_golden_key_blob_too_short_test()138 fn read_golden_key_blob_too_short_test() {
139     let error =
140         LegacyBlobLoader::new_from_stream_decrypt_with(&mut &BLOB[0..15], |_, _, _, _, _| {
141             Err(anyhow!("should not be called"))
142         })
143         .unwrap_err();
144     assert_eq!(Some(&Error::BadLen), error.root_cause().downcast_ref::<Error>());
145 }
146 
147 #[test]
test_is_empty()148 fn test_is_empty() {
149     let temp_dir = TempDir::new("test_is_empty").expect("Failed to create temp dir.");
150     let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
151 
152     assert!(legacy_blob_loader.is_empty().expect("Should succeed and be empty."));
153 
154     let _db =
155         crate::database::KeystoreDB::new(temp_dir.path(), None).expect("Failed to open database.");
156 
157     assert!(legacy_blob_loader.is_empty().expect("Should succeed and still be empty."));
158 
159     std::fs::create_dir(&*temp_dir.build().push("user_0")).expect("Failed to create user_0.");
160 
161     assert!(!legacy_blob_loader.is_empty().expect("Should succeed but not be empty."));
162 
163     std::fs::create_dir(&*temp_dir.build().push("user_10")).expect("Failed to create user_10.");
164 
165     assert!(!legacy_blob_loader.is_empty().expect("Should succeed but still not be empty."));
166 
167     std::fs::remove_dir_all(&*temp_dir.build().push("user_0")).expect("Failed to remove user_0.");
168 
169     assert!(!legacy_blob_loader.is_empty().expect("Should succeed but still not be empty."));
170 
171     std::fs::remove_dir_all(&*temp_dir.build().push("user_10")).expect("Failed to remove user_10.");
172 
173     assert!(legacy_blob_loader.is_empty().expect("Should succeed and be empty again."));
174 }
175 
176 #[test]
test_legacy_blobs() -> anyhow::Result<()>177 fn test_legacy_blobs() -> anyhow::Result<()> {
178     let temp_dir = TempDir::new("legacy_blob_test").unwrap();
179     std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
180 
181     std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
182 
183     std::fs::write(
184         &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
185         USRPKEY_AUTHBOUND,
186     )
187     .unwrap();
188     std::fs::write(
189         &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
190         USRPKEY_AUTHBOUND_CHR,
191     )
192     .unwrap();
193     std::fs::write(
194         &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
195         USRCERT_AUTHBOUND,
196     )
197     .unwrap();
198     std::fs::write(
199         &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
200         CACERT_AUTHBOUND,
201     )
202     .unwrap();
203 
204     std::fs::write(
205         &*temp_dir.build().push("user_0").push("10223_USRPKEY_non_authbound"),
206         USRPKEY_NON_AUTHBOUND,
207     )
208     .unwrap();
209     std::fs::write(
210         &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_non_authbound"),
211         USRPKEY_NON_AUTHBOUND_CHR,
212     )
213     .unwrap();
214     std::fs::write(
215         &*temp_dir.build().push("user_0").push("10223_USRCERT_non_authbound"),
216         USRCERT_NON_AUTHBOUND,
217     )
218     .unwrap();
219     std::fs::write(
220         &*temp_dir.build().push("user_0").push("10223_CACERT_non_authbound"),
221         CACERT_NON_AUTHBOUND,
222     )
223     .unwrap();
224 
225     let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
226 
227     if let (Some((Blob { flags, value }, _params)), Some(cert), Some(chain)) =
228         legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
229     {
230         assert_eq!(flags, 4);
231         assert_eq!(
232             value,
233             BlobValue::Encrypted {
234                 data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
235                 iv: USRPKEY_AUTHBOUND_IV.to_vec(),
236                 tag: USRPKEY_AUTHBOUND_TAG.to_vec()
237             }
238         );
239         assert_eq!(&cert[..], LOADED_CERT_AUTHBOUND);
240         assert_eq!(&chain[..], LOADED_CACERT_AUTHBOUND);
241     } else {
242         panic!("");
243     }
244 
245     if let (Some((Blob { flags, value: _ }, _params)), Some(cert), Some(chain)) =
246         legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
247     {
248         assert_eq!(flags, 4);
249         //assert_eq!(value, BlobValue::Encrypted(..));
250         assert_eq!(&cert[..], LOADED_CERT_AUTHBOUND);
251         assert_eq!(&chain[..], LOADED_CACERT_AUTHBOUND);
252     } else {
253         panic!("");
254     }
255     if let (Some((Blob { flags, value }, _params)), Some(cert), Some(chain)) =
256         legacy_blob_loader.load_by_uid_alias(10223, "non_authbound", &None)?
257     {
258         assert_eq!(flags, 0);
259         assert_eq!(value, BlobValue::Decrypted(LOADED_USRPKEY_NON_AUTHBOUND.try_into()?));
260         assert_eq!(&cert[..], LOADED_CERT_NON_AUTHBOUND);
261         assert_eq!(&chain[..], LOADED_CACERT_NON_AUTHBOUND);
262     } else {
263         panic!("");
264     }
265 
266     legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
267     legacy_blob_loader.remove_keystore_entry(10223, "non_authbound").expect("This should succeed.");
268 
269     assert_eq!(
270         (None, None, None),
271         legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
272     );
273     assert_eq!(
274         (None, None, None),
275         legacy_blob_loader.load_by_uid_alias(10223, "non_authbound", &None)?
276     );
277 
278     // The database should not be empty due to the super key.
279     assert!(!legacy_blob_loader.is_empty()?);
280     assert!(!legacy_blob_loader.is_empty_user(0)?);
281 
282     // The database should be considered empty for user 1.
283     assert!(legacy_blob_loader.is_empty_user(1)?);
284 
285     legacy_blob_loader.remove_super_key(0);
286 
287     // Now it should be empty.
288     assert!(legacy_blob_loader.is_empty_user(0)?);
289     assert!(legacy_blob_loader.is_empty()?);
290 
291     Ok(())
292 }
293 
294 struct TestKey(ZVec);
295 
296 impl crate::utils::AesGcmKey for TestKey {
key(&self) -> &[u8]297     fn key(&self) -> &[u8] {
298         &self.0
299     }
300 }
301 
302 impl Deref for TestKey {
303     type Target = [u8];
deref(&self) -> &Self::Target304     fn deref(&self) -> &Self::Target {
305         &self.0
306     }
307 }
308 
309 #[test]
test_with_encrypted_characteristics() -> anyhow::Result<()>310 fn test_with_encrypted_characteristics() -> anyhow::Result<()> {
311     let temp_dir = TempDir::new("test_with_encrypted_characteristics").unwrap();
312     std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
313 
314     let pw: Password = PASSWORD.into();
315     let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
316     let super_key =
317         Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
318 
319     std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
320 
321     std::fs::write(
322         &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
323         USRPKEY_AUTHBOUND,
324     )
325     .unwrap();
326     make_encrypted_characteristics_file(
327         &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
328         &super_key,
329         KEY_PARAMETERS,
330     )
331     .unwrap();
332     std::fs::write(
333         &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
334         USRCERT_AUTHBOUND,
335     )
336     .unwrap();
337     std::fs::write(
338         &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
339         CACERT_AUTHBOUND,
340     )
341     .unwrap();
342 
343     let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
344 
345     assert_eq!(
346         legacy_blob_loader
347             .load_by_uid_alias(10223, "authbound", &None)
348             .unwrap_err()
349             .root_cause()
350             .downcast_ref::<Error>(),
351         Some(&Error::LockedComponent)
352     );
353 
354     assert_eq!(
355         legacy_blob_loader.load_by_uid_alias(10223, "authbound", &Some(super_key)).unwrap(),
356         (
357             Some((
358                 Blob {
359                     flags: 4,
360                     value: BlobValue::Encrypted {
361                         data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
362                         iv: USRPKEY_AUTHBOUND_IV.to_vec(),
363                         tag: USRPKEY_AUTHBOUND_TAG.to_vec()
364                     }
365                 },
366                 structured_test_params()
367             )),
368             Some(LOADED_CERT_AUTHBOUND.to_vec()),
369             Some(LOADED_CACERT_AUTHBOUND.to_vec())
370         )
371     );
372 
373     legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
374 
375     assert_eq!(
376         (None, None, None),
377         legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None).unwrap()
378     );
379 
380     // The database should not be empty due to the super key.
381     assert!(!legacy_blob_loader.is_empty().unwrap());
382     assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
383 
384     // The database should be considered empty for user 1.
385     assert!(legacy_blob_loader.is_empty_user(1).unwrap());
386 
387     legacy_blob_loader.remove_super_key(0);
388 
389     // Now it should be empty.
390     assert!(legacy_blob_loader.is_empty_user(0).unwrap());
391     assert!(legacy_blob_loader.is_empty().unwrap());
392 
393     Ok(())
394 }
395 
396 #[test]
test_with_encrypted_certificates() -> anyhow::Result<()>397 fn test_with_encrypted_certificates() -> anyhow::Result<()> {
398     let temp_dir = TempDir::new("test_with_encrypted_certificates").unwrap();
399     std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
400 
401     let pw: Password = PASSWORD.into();
402     let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
403     let super_key =
404         Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
405 
406     std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
407 
408     std::fs::write(
409         &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
410         USRPKEY_AUTHBOUND,
411     )
412     .unwrap();
413     std::fs::write(
414         &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
415         USRPKEY_AUTHBOUND_CHR,
416     )
417     .unwrap();
418     make_encrypted_usr_cert_file(
419         &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
420         &super_key,
421         LOADED_CERT_AUTHBOUND,
422     )
423     .unwrap();
424     make_encrypted_ca_cert_file(
425         &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
426         &super_key,
427         LOADED_CACERT_AUTHBOUND,
428     )
429     .unwrap();
430 
431     let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
432 
433     assert_eq!(
434         legacy_blob_loader
435             .load_by_uid_alias(10223, "authbound", &None)
436             .unwrap_err()
437             .root_cause()
438             .downcast_ref::<Error>(),
439         Some(&Error::LockedComponent)
440     );
441 
442     assert_eq!(
443         legacy_blob_loader.load_by_uid_alias(10223, "authbound", &Some(super_key)).unwrap(),
444         (
445             Some((
446                 Blob {
447                     flags: 4,
448                     value: BlobValue::Encrypted {
449                         data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
450                         iv: USRPKEY_AUTHBOUND_IV.to_vec(),
451                         tag: USRPKEY_AUTHBOUND_TAG.to_vec()
452                     }
453                 },
454                 structured_test_params_cache()
455             )),
456             Some(LOADED_CERT_AUTHBOUND.to_vec()),
457             Some(LOADED_CACERT_AUTHBOUND.to_vec())
458         )
459     );
460 
461     legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
462 
463     assert_eq!(
464         (None, None, None),
465         legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None).unwrap()
466     );
467 
468     // The database should not be empty due to the super key.
469     assert!(!legacy_blob_loader.is_empty().unwrap());
470     assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
471 
472     // The database should be considered empty for user 1.
473     assert!(legacy_blob_loader.is_empty_user(1).unwrap());
474 
475     legacy_blob_loader.remove_super_key(0);
476 
477     // Now it should be empty.
478     assert!(legacy_blob_loader.is_empty_user(0).unwrap());
479     assert!(legacy_blob_loader.is_empty().unwrap());
480 
481     Ok(())
482 }
483 
484 #[test]
test_in_place_key_migration() -> anyhow::Result<()>485 fn test_in_place_key_migration() -> anyhow::Result<()> {
486     let temp_dir = TempDir::new("test_in_place_key_migration").unwrap();
487     std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
488 
489     let pw: Password = PASSWORD.into();
490     let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
491     let super_key =
492         Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
493 
494     std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
495 
496     std::fs::write(
497         &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
498         USRPKEY_AUTHBOUND,
499     )
500     .unwrap();
501     std::fs::write(
502         &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
503         USRPKEY_AUTHBOUND_CHR,
504     )
505     .unwrap();
506     make_encrypted_usr_cert_file(
507         &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
508         &super_key,
509         LOADED_CERT_AUTHBOUND,
510     )
511     .unwrap();
512     make_encrypted_ca_cert_file(
513         &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
514         &super_key,
515         LOADED_CACERT_AUTHBOUND,
516     )
517     .unwrap();
518 
519     let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
520 
521     assert_eq!(
522         legacy_blob_loader
523             .load_by_uid_alias(10223, "authbound", &None)
524             .unwrap_err()
525             .root_cause()
526             .downcast_ref::<Error>(),
527         Some(&Error::LockedComponent)
528     );
529 
530     let super_key: Option<Arc<dyn AesGcm>> = Some(super_key);
531 
532     assert_eq!(
533         legacy_blob_loader.load_by_uid_alias(10223, "authbound", &super_key).unwrap(),
534         (
535             Some((
536                 Blob {
537                     flags: 4,
538                     value: BlobValue::Encrypted {
539                         data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
540                         iv: USRPKEY_AUTHBOUND_IV.to_vec(),
541                         tag: USRPKEY_AUTHBOUND_TAG.to_vec()
542                     }
543                 },
544                 structured_test_params_cache()
545             )),
546             Some(LOADED_CERT_AUTHBOUND.to_vec()),
547             Some(LOADED_CACERT_AUTHBOUND.to_vec())
548         )
549     );
550 
551     legacy_blob_loader.move_keystore_entry(10223, 10224, "authbound", "boundauth").unwrap();
552 
553     assert_eq!(
554         legacy_blob_loader
555             .load_by_uid_alias(10224, "boundauth", &None)
556             .unwrap_err()
557             .root_cause()
558             .downcast_ref::<Error>(),
559         Some(&Error::LockedComponent)
560     );
561 
562     assert_eq!(
563         legacy_blob_loader.load_by_uid_alias(10224, "boundauth", &super_key).unwrap(),
564         (
565             Some((
566                 Blob {
567                     flags: 4,
568                     value: BlobValue::Encrypted {
569                         data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
570                         iv: USRPKEY_AUTHBOUND_IV.to_vec(),
571                         tag: USRPKEY_AUTHBOUND_TAG.to_vec()
572                     }
573                 },
574                 structured_test_params_cache()
575             )),
576             Some(LOADED_CERT_AUTHBOUND.to_vec()),
577             Some(LOADED_CACERT_AUTHBOUND.to_vec())
578         )
579     );
580 
581     legacy_blob_loader.remove_keystore_entry(10224, "boundauth").expect("This should succeed.");
582 
583     assert_eq!(
584         (None, None, None),
585         legacy_blob_loader.load_by_uid_alias(10224, "boundauth", &None).unwrap()
586     );
587 
588     // The database should not be empty due to the super key.
589     assert!(!legacy_blob_loader.is_empty().unwrap());
590     assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
591 
592     // The database should be considered empty for user 1.
593     assert!(legacy_blob_loader.is_empty_user(1).unwrap());
594 
595     legacy_blob_loader.remove_super_key(0);
596 
597     // Now it should be empty.
598     assert!(legacy_blob_loader.is_empty_user(0).unwrap());
599     assert!(legacy_blob_loader.is_empty().unwrap());
600 
601     Ok(())
602 }
603 
604 #[test]
list_non_existing_user() -> Result<()>605 fn list_non_existing_user() -> Result<()> {
606     let temp_dir = TempDir::new("list_non_existing_user").unwrap();
607     let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
608 
609     assert!(legacy_blob_loader.list_user(20)?.is_empty());
610 
611     Ok(())
612 }
613 
614 #[test]
list_legacy_keystore_entries_on_non_existing_user() -> Result<()>615 fn list_legacy_keystore_entries_on_non_existing_user() -> Result<()> {
616     let temp_dir = TempDir::new("list_legacy_keystore_entries_on_non_existing_user").unwrap();
617     let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
618 
619     assert!(legacy_blob_loader.list_legacy_keystore_entries_for_user(20)?.is_empty());
620 
621     Ok(())
622 }
623 
624 #[test]
test_move_keystore_entry()625 fn test_move_keystore_entry() {
626     let temp_dir = TempDir::new("test_move_keystore_entry").unwrap();
627     std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
628 
629     const SOME_CONTENT: &[u8] = b"some content";
630     const ANOTHER_CONTENT: &[u8] = b"another content";
631     const SOME_FILENAME: &str = "some_file";
632     const ANOTHER_FILENAME: &str = "another_file";
633 
634     std::fs::write(&*temp_dir.build().push("user_0").push(SOME_FILENAME), SOME_CONTENT).unwrap();
635 
636     std::fs::write(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME), ANOTHER_CONTENT)
637         .unwrap();
638 
639     // Non existent source id silently ignored.
640     assert!(LegacyBlobLoader::move_keystore_file_if_exists(
641         1,
642         2,
643         "non_existent",
644         ANOTHER_FILENAME,
645         "ignored",
646         |_, alias, _| temp_dir.build().push("user_0").push(alias).to_path_buf()
647     )
648     .is_ok());
649 
650     // Content of another_file has not changed.
651     let another_content =
652         std::fs::read(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME)).unwrap();
653     assert_eq!(&another_content, ANOTHER_CONTENT);
654 
655     // Check that some_file still exists.
656     assert!(temp_dir.build().push("user_0").push(SOME_FILENAME).exists());
657     // Existing target files are silently overwritten.
658 
659     assert!(LegacyBlobLoader::move_keystore_file_if_exists(
660         1,
661         2,
662         SOME_FILENAME,
663         ANOTHER_FILENAME,
664         "ignored",
665         |_, alias, _| temp_dir.build().push("user_0").push(alias).to_path_buf()
666     )
667     .is_ok());
668 
669     // Content of another_file is now "some content".
670     let another_content =
671         std::fs::read(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME)).unwrap();
672     assert_eq!(&another_content, SOME_CONTENT);
673 
674     // Check that some_file no longer exists.
675     assert!(!temp_dir.build().push("user_0").push(SOME_FILENAME).exists());
676 }
677