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