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