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