1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <lib/storage/storage.h>
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <uapi/err.h>
22
23 #define FILE_BUFFER_MAX 1000000
24 #define TEST_FILE_MAX 100
25 #define TEST_HANDLER_MAX 1000
26
27 #define MAX_CHUNK_SIZE 4040
28 #define MAX_PARAMETER_SIZE 10
29
30 /* File info structure representing a file on secure storage. */
31 struct FileInfo {
32 char name[STORAGE_MAX_NAME_LENGTH_BYTES];
33 size_t size;
34 /* For test we just use a static buffer for file content. */
35 uint8_t buf[FILE_BUFFER_MAX];
36 };
37
38 struct FileHandler {
39 char name[STORAGE_MAX_NAME_LENGTH_BYTES];
40 uint64_t file_handler;
41 struct FileInfo* file_info;
42 };
43
44 static struct FileInfo* storage_mock_files[TEST_FILE_MAX];
45 static struct FileHandler* storage_mock_handlers[TEST_HANDLER_MAX];
46 static uint64_t storage_mock_handlers_count;
47 static uint64_t storage_mock_files_count;
48 static uint64_t storage_handler_num = 1;
49 static uint64_t storage_session_num = 1;
50 static bool storage_session_opened;
51
get_file_handler(file_handle_t fh)52 static struct FileHandler* get_file_handler(file_handle_t fh) {
53 for (int i = 0; i < TEST_HANDLER_MAX; i++) {
54 if (storage_mock_handlers[i] == NULL) {
55 continue;
56 }
57 if (storage_mock_handlers[i]->file_handler == fh) {
58 return storage_mock_handlers[i];
59 }
60 }
61 return NULL;
62 }
63
not_implemented_handler(const char * operation)64 static int not_implemented_handler(const char* operation) {
65 fprintf(stderr,
66 "%s is not supported in fake secure storage implementation.\n",
67 operation);
68 return ERR_NOT_IMPLEMENTED;
69 }
70
71 /*
72 * Copied from client_tipc.c.
73 */
is_valid_name(const char * name,size_t name_len)74 static int is_valid_name(const char* name, size_t name_len) {
75 size_t i;
76
77 if (!name_len)
78 return 0;
79
80 for (i = 0; i < name_len; i++) {
81 if ((name[i] >= 'a') && (name[i] <= 'z'))
82 continue;
83 if ((name[i] >= 'A') && (name[i] <= 'Z'))
84 continue;
85 if ((name[i] >= '0') && (name[i] <= '9'))
86 continue;
87 if ((name[i] == '.') || (name[i] == '-') || (name[i] == '_'))
88 continue;
89
90 /* not a legal character so reject this name */
91 return 0;
92 }
93
94 return 1;
95 }
96
storage_open_session(storage_session_t * session_p,const char * type)97 int storage_open_session(storage_session_t* session_p, const char* type) {
98 if (storage_session_opened) {
99 return not_implemented_handler("Using more than one session");
100 }
101 storage_session_opened = true;
102 *session_p = storage_session_num;
103 storage_session_num++;
104 return NO_ERROR;
105 }
106
storage_close_session(storage_session_t session)107 void storage_close_session(storage_session_t session) {
108 storage_session_opened = false;
109 return;
110 }
111
storage_open_file(storage_session_t session,file_handle_t * handle_p,const char * name,uint32_t flags,uint32_t opflags)112 int storage_open_file(storage_session_t session,
113 file_handle_t* handle_p,
114 const char* name,
115 uint32_t flags,
116 uint32_t opflags) {
117 if (strlen(name) >= STORAGE_MAX_NAME_LENGTH_BYTES) {
118 return ERR_NOT_VALID;
119 }
120
121 if (!is_valid_name(name, strlen(name))) {
122 return ERR_NOT_VALID;
123 }
124
125 if (storage_mock_handlers_count >= TEST_HANDLER_MAX) {
126 return ERR_GENERIC;
127 }
128 struct FileInfo* file_info_p = NULL;
129 for (int i = 0; i < TEST_FILE_MAX; i++) {
130 if (storage_mock_files[i] == NULL) {
131 continue;
132 }
133 if (!strcmp(storage_mock_files[i]->name, name)) {
134 file_info_p = storage_mock_files[i];
135 }
136 }
137 if (file_info_p == NULL) {
138 /* File not found. */
139 if (!(flags & STORAGE_FILE_OPEN_CREATE)) {
140 return ERR_NOT_FOUND;
141 } else {
142 /* Create new file. */
143 storage_mock_files[storage_mock_files_count] =
144 malloc(sizeof(struct FileInfo));
145 memset(storage_mock_files[storage_mock_files_count], 0,
146 sizeof(struct FileInfo));
147 strncpy(storage_mock_files[storage_mock_files_count]->name, name,
148 STORAGE_MAX_NAME_LENGTH_BYTES);
149 file_info_p = storage_mock_files[storage_mock_files_count];
150 storage_mock_files_count++;
151 }
152 } else {
153 if ((flags & STORAGE_FILE_OPEN_CREATE) &&
154 (flags & STORAGE_FILE_OPEN_CREATE_EXCLUSIVE)) {
155 /* When CREATE_EXCLUSIVE is specified, opening existing file would
156 * fail. */
157 return ERR_ALREADY_EXISTS;
158 }
159 for (int i = 0; i < TEST_HANDLER_MAX; i++) {
160 if (storage_mock_handlers[i] == NULL) {
161 continue;
162 }
163 if (!strcmp(storage_mock_handlers[i]->name, name)) {
164 /* open a same file second time is not allowed. */
165 return ERR_NOT_ALLOWED;
166 }
167 }
168 if (flags & STORAGE_FILE_OPEN_TRUNCATE) {
169 /* Discard existing contents. */
170 file_info_p->size = 0;
171 memset(file_info_p->buf, 0, FILE_BUFFER_MAX);
172 }
173 }
174 storage_mock_handlers[storage_mock_handlers_count] =
175 malloc(sizeof(struct FileHandler));
176 memset(storage_mock_handlers[storage_mock_handlers_count], 0,
177 sizeof(struct FileHandler));
178 strncpy(storage_mock_handlers[storage_mock_handlers_count]->name, name,
179 STORAGE_MAX_NAME_LENGTH_BYTES);
180 storage_mock_handlers[storage_mock_handlers_count]->file_handler =
181 storage_handler_num;
182 storage_mock_handlers[storage_mock_handlers_count]->file_info = file_info_p;
183 *handle_p = storage_handler_num;
184 storage_handler_num++;
185 storage_mock_handlers_count++;
186 return NO_ERROR;
187 }
188
storage_close_file(file_handle_t fh)189 void storage_close_file(file_handle_t fh) {
190 for (int i = 0; i < TEST_HANDLER_MAX; i++) {
191 if (storage_mock_handlers[i] == NULL) {
192 continue;
193 }
194 if (storage_mock_handlers[i]->file_handler == fh) {
195 free(storage_mock_handlers[i]);
196 for (int j = i; j < TEST_HANDLER_MAX - 1; j++) {
197 storage_mock_handlers[j] = storage_mock_handlers[j + 1];
198 }
199 return;
200 }
201 }
202 }
203
storage_move_file(storage_session_t session,file_handle_t handle,const char * old_name,const char * new_name,uint32_t flags,uint32_t opflags)204 int storage_move_file(storage_session_t session,
205 file_handle_t handle,
206 const char* old_name,
207 const char* new_name,
208 uint32_t flags,
209 uint32_t opflags) {
210 return not_implemented_handler("Moving file");
211 }
212
storage_delete_file(storage_session_t session,const char * name,uint32_t opflags)213 int storage_delete_file(storage_session_t session,
214 const char* name,
215 uint32_t opflags) {
216 for (int i = 0; i < TEST_FILE_MAX; i++) {
217 if (storage_mock_files[i] == NULL) {
218 continue;
219 }
220 if (!strcmp(storage_mock_files[i]->name, name)) {
221 free(storage_mock_files[i]);
222 for (int j = i; j < TEST_FILE_MAX - 1; j++) {
223 storage_mock_files[j] = storage_mock_files[j + 1];
224 }
225 /* Invalid all the handlers pointing to the non existing file. */
226 for (int j = 0; j < TEST_HANDLER_MAX; j++) {
227 if (storage_mock_handlers[j] == NULL) {
228 continue;
229 }
230 if (strcmp(storage_mock_handlers[j]->name, name)) {
231 storage_mock_handlers[j]->file_info = NULL;
232 }
233 }
234 return NO_ERROR;
235 }
236 }
237 return ERR_NOT_FOUND;
238 }
239
240 struct storage_open_dir_state {
241 uint8_t buf[MAX_CHUNK_SIZE];
242 size_t buf_size;
243 size_t buf_last_read;
244 size_t buf_read;
245 };
246
storage_open_dir(storage_session_t session,const char * path,struct storage_open_dir_state ** state)247 int storage_open_dir(storage_session_t session,
248 const char* path,
249 struct storage_open_dir_state** state) {
250 return not_implemented_handler("Opening directory");
251 }
252
storage_close_dir(storage_session_t session,struct storage_open_dir_state * state)253 void storage_close_dir(storage_session_t session,
254 struct storage_open_dir_state* state) {
255 not_implemented_handler("Closing directory");
256 return;
257 }
258
storage_read_dir(storage_session_t session,struct storage_open_dir_state * state,uint8_t * flags,char * name,size_t name_out_size)259 int storage_read_dir(storage_session_t session,
260 struct storage_open_dir_state* state,
261 uint8_t* flags,
262 char* name,
263 size_t name_out_size) {
264 return not_implemented_handler("Reading directory");
265 }
266
storage_read(file_handle_t fh,storage_off_t off,void * buf,size_t size)267 ssize_t storage_read(file_handle_t fh,
268 storage_off_t off,
269 void* buf,
270 size_t size) {
271 struct FileHandler* file_handler_p = get_file_handler(fh);
272 if (file_handler_p == NULL) {
273 return ERR_NOT_VALID;
274 }
275 struct FileInfo* file_info = file_handler_p->file_info;
276 if (file_info == NULL) {
277 return ERR_NOT_VALID;
278 }
279 if (off > file_info->size) {
280 return ERR_NOT_VALID;
281 }
282 size_t copy_size = size;
283 if (off + copy_size > file_info->size) {
284 copy_size = file_info->size - off;
285 }
286 memcpy(buf, file_info->buf + off, copy_size);
287 return copy_size;
288 }
289
storage_write(file_handle_t fh,storage_off_t off,const void * buf,size_t size,uint32_t opflags)290 ssize_t storage_write(file_handle_t fh,
291 storage_off_t off,
292 const void* buf,
293 size_t size,
294 uint32_t opflags) {
295 struct FileHandler* file_handler_p = get_file_handler(fh);
296 if (file_handler_p == NULL) {
297 return ERR_NOT_VALID;
298 }
299 struct FileInfo* file_info = file_handler_p->file_info;
300 if (file_info == NULL) {
301 return ERR_NOT_VALID;
302 }
303 if (off + size > FILE_BUFFER_MAX) {
304 return ERR_GENERIC;
305 }
306 if (off > file_info->size) {
307 // Write beyond EOF, pad with 0 first.
308 size_t padding_size = off - file_info->size;
309 memset(file_info->buf + file_info->size, 0, padding_size);
310 }
311 if (off + size > file_info->size) {
312 file_info->size = off + size;
313 }
314
315 memcpy(file_info->buf + off, buf, size);
316
317 return size;
318 }
319
storage_set_file_size(file_handle_t fh,storage_off_t file_size,uint32_t opflags)320 int storage_set_file_size(file_handle_t fh,
321 storage_off_t file_size,
322 uint32_t opflags) {
323 if (file_size > FILE_BUFFER_MAX) {
324 return ERR_GENERIC;
325 }
326 struct FileHandler* file_handler_p = get_file_handler(fh);
327 if (file_handler_p == NULL) {
328 return ERR_NOT_VALID;
329 }
330 struct FileInfo* file_info = file_handler_p->file_info;
331 if (file_info == NULL) {
332 return ERR_NOT_VALID;
333 }
334 if (file_size > file_info->size) {
335 // Write beyond EOF, pad with 0.
336 size_t padding_size = file_size - file_info->size;
337 memset(file_info->buf + file_info->size, 0, padding_size);
338 }
339 file_info->size = file_size;
340
341 return NO_ERROR;
342 }
343
storage_get_file_size(file_handle_t fh,storage_off_t * size_p)344 int storage_get_file_size(file_handle_t fh, storage_off_t* size_p) {
345 struct FileHandler* file_handler_p = get_file_handler(fh);
346 if (file_handler_p == NULL) {
347 return ERR_NOT_VALID;
348 }
349 struct FileInfo* file_info = file_handler_p->file_info;
350 if (file_info == NULL) {
351 /* File has been deleted, return NO_ERROR. */
352 size_p = 0;
353 return NO_ERROR;
354 }
355 *size_p = file_info->size;
356 return NO_ERROR;
357 }
358
storage_end_transaction(storage_session_t session,bool complete)359 int storage_end_transaction(storage_session_t session, bool complete) {
360 if (!complete) {
361 return not_implemented_handler("Discard transaction");
362 }
363 return NO_ERROR;
364 }
365