1 use android_hardware_security_see_storage::aidl::android::hardware::security::see::storage::{
2     CreationMode::CreationMode, FileMode::FileMode, ISecureStorage as SecureStorage,
3     IStorageSession::IStorageSession, OpenOptions::OpenOptions, ReadIntegrity::ReadIntegrity,
4 };
5 use binder::ExceptionCode;
6 use test::{assert_ok, expect, fail};
7 
8 mod helpers;
9 use helpers::{ensure_deleted, Exists};
10 
11 const CREATE_EXCLUSIVE: &'static OpenOptions = &OpenOptions {
12     createMode: CreationMode::CREATE_EXCLUSIVE,
13     accessMode: FileMode::READ_WRITE,
14     readIntegrity: ReadIntegrity::NO_TAMPER,
15     truncateOnOpen: true,
16     allowWritesDuringAbUpdate: false,
17 };
18 
19 const NO_CREATE: &'static OpenOptions = &OpenOptions {
20     createMode: CreationMode::NO_CREATE,
21     accessMode: FileMode::READ_WRITE,
22     readIntegrity: ReadIntegrity::NO_TAMPER,
23     truncateOnOpen: false,
24     allowWritesDuringAbUpdate: false,
25 };
26 
create_delete(ss: &(impl IStorageSession + ?Sized))27 pub(crate) fn create_delete(ss: &(impl IStorageSession + ?Sized)) {
28     let fname = "test_create_delete_file";
29     assert_ok!(ensure_deleted(ss, fname, Exists::Unknown));
30 
31     {
32         // Create file
33         let _file = assert_ok!(ss.openFile(fname, CREATE_EXCLUSIVE));
34         assert_ok!(ss.commitChanges());
35 
36         // Try to create file again
37         match ss.openFile(fname, CREATE_EXCLUSIVE) {
38             Ok(_) => fail!("openFile (on existing file) unexpectedly succeeded"),
39             Err(e)
40                 if e.exception_code() == ExceptionCode::SERVICE_SPECIFIC
41                     && e.service_specific_error() == SecureStorage::ERR_ALREADY_EXISTS =>
42             {
43                 ()
44             }
45             Err(e) => fail!("openFile (on existing file) failed with: {}", e),
46         };
47         assert_ok!(ss.commitChanges());
48 
49         // File closes
50     }
51 
52     assert_ok!(ensure_deleted(ss, fname, Exists::Must));
53 }
54 
create_move_delete(ss: &(impl IStorageSession + ?Sized))55 pub(crate) fn create_move_delete(ss: &(impl IStorageSession + ?Sized)) {
56     let fname1 = "test_create_move_delete_1_file";
57     let fname2 = "test_create_move_delete_2_file";
58 
59     assert_ok!(ensure_deleted(ss, fname1, Exists::Unknown));
60     assert_ok!(ensure_deleted(ss, fname2, Exists::Unknown));
61 
62     {
63         // Create file
64         let file = assert_ok!(ss.openFile(fname1, CREATE_EXCLUSIVE));
65         assert_ok!(ss.commitChanges());
66 
67         // Move fname1 -> fname2
68         assert_ok!(file.rename(fname2, CreationMode::CREATE_EXCLUSIVE));
69         assert_ok!(ss.commitChanges());
70 
71         // Try to create fname2, with file still alive
72         match ss.openFile(fname2, CREATE_EXCLUSIVE) {
73             Ok(_) => fail!("openFile unexpectedly succeeded"),
74             Err(e)
75                 if e.exception_code() == ExceptionCode::SERVICE_SPECIFIC
76                     && e.service_specific_error() == SecureStorage::ERR_ALREADY_EXISTS =>
77             {
78                 ()
79             }
80             Err(e) => fail!("openFile failed with unexpected error: {}", e),
81         };
82         assert_ok!(ss.commitChanges());
83 
84         // file closes
85     }
86 
87     // Try to create fname2, now that file is closed
88     match ss.openFile(fname2, CREATE_EXCLUSIVE) {
89         Ok(_) => fail!("openFile unexpectedly succeeded"),
90         Err(e)
91             if e.exception_code() == ExceptionCode::SERVICE_SPECIFIC
92                 && e.service_specific_error() == SecureStorage::ERR_ALREADY_EXISTS =>
93         {
94             ()
95         }
96         Err(e) => fail!("openFile failed with unexpected error: {}", e),
97     };
98     assert_ok!(ss.commitChanges());
99 
100     {
101         // Recreate fname1
102         let file = assert_ok!(ss.openFile(fname1, CREATE_EXCLUSIVE));
103         assert_ok!(ss.commitChanges());
104 
105         // Move doesn't work now that fname2 exists
106         match file.rename(fname2, CreationMode::CREATE_EXCLUSIVE) {
107             Ok(_) => panic!("rename unexpectedly succeeded"),
108             Err(e)
109                 if e.exception_code() == ExceptionCode::SERVICE_SPECIFIC
110                     && e.service_specific_error() == SecureStorage::ERR_ALREADY_EXISTS =>
111             {
112                 ()
113             }
114             Err(e) => panic!("rename failed with unexpected error: {}", e),
115         };
116 
117         // file closes
118     }
119 
120     assert_ok!(ensure_deleted(ss, fname1, Exists::Must));
121     assert_ok!(ensure_deleted(ss, fname2, Exists::Must));
122 }
123 
file_list(ss: &(impl IStorageSession + ?Sized))124 pub(crate) fn file_list(ss: &(impl IStorageSession + ?Sized)) {
125     use core::array::from_fn;
126     use std::collections::HashSet;
127 
128     let fnames: [String; 100] = from_fn(|i| format!("test_file_list_{:02}_file", i));
129     for fname in &fnames {
130         assert_ok!(ensure_deleted(ss, fname, Exists::Unknown), "file: {}", fname);
131     }
132 
133     {
134         let dir = assert_ok!(ss.openDir("", ReadIntegrity::NO_TAMPER));
135         let filenames = assert_ok!(dir.readNextFilenames(0));
136         expect!(filenames.is_empty(), "Found unexpected files: {:?}", filenames);
137     }
138 
139     // Create, commit, and close file #0
140     {
141         let _file = assert_ok!(ss.openFile(&fnames[0], CREATE_EXCLUSIVE));
142         assert_ok!(ss.commitChanges());
143     }
144     // Create and close (don't commit) other files
145     for fname in &fnames[1..] {
146         let _file = assert_ok!(ss.openFile(fname, CREATE_EXCLUSIVE), "for fname {}", fname);
147     }
148 
149     let mut read_file_names = HashSet::new();
150     {
151         let dir = assert_ok!(ss.openDir("", ReadIntegrity::NO_TAMPER));
152         let mut filenames = assert_ok!(dir.readNextFilenames(0));
153         while !filenames.is_empty() {
154             for filename in filenames {
155                 let existed = read_file_names.replace(filename);
156                 if let Some(previous) = existed {
157                     fail!("NextFilenameResult returned file more than once: {}", previous);
158                 }
159             }
160             filenames = assert_ok!(dir.readNextFilenames(0));
161         }
162     }
163     assert_ok!(ss.commitChanges());
164 
165     // Clean up
166     for fname in &fnames {
167         assert_ok!(ensure_deleted(ss, fname, Exists::Must), "file: {}", fname);
168     }
169 
170     let expected = fnames.into_iter().collect::<HashSet<_>>();
171     let missing = expected.difference(&read_file_names).collect::<Vec<_>>();
172     let extra = read_file_names.difference(&expected).collect::<Vec<_>>();
173 
174     expect!(missing.is_empty(), "Did not find the following expected files: {:?}", missing);
175     expect!(extra.is_empty(), "Found the following unexpected files: {:?}", extra);
176 }
177 
write_read_sequential(ss: &(impl IStorageSession + ?Sized))178 pub(crate) fn write_read_sequential(ss: &(impl IStorageSession + ?Sized)) {
179     use helpers::{read_pattern, write_pattern};
180 
181     let fname = "test_write_read_sequential";
182     let chunks = 32;
183     let chunk_len = 2048;
184 
185     assert_ok!(ensure_deleted(ss, fname, Exists::Unknown));
186 
187     {
188         let file = assert_ok!(ss.openFile(fname, CREATE_EXCLUSIVE));
189         assert_ok!(ss.commitChanges());
190 
191         assert_ok!(write_pattern(&*file, 0, chunks, chunk_len));
192         assert_ok!(ss.commitChanges());
193 
194         assert_ok!(read_pattern(&*file, 0, chunks, chunk_len));
195     } // file closes
196 
197     {
198         let file = assert_ok!(ss.openFile(fname, NO_CREATE));
199         assert_ok!(read_pattern(&*file, 0, chunks, chunk_len));
200     } // file closes
201 
202     assert_ok!(ensure_deleted(ss, fname, Exists::Must));
203 }
204