1 /*
2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3 * All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * - Neither the name of the copyright owner, nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "oapv_def.h"
33 #include "oapv_metadata.h"
34
meta_id_to_ctx(oapvm_t id)35 static oapvm_ctx_t *meta_id_to_ctx(oapvm_t id)
36 {
37 oapvm_ctx_t *ctx;
38 oapv_assert_rv(id, NULL);
39 ctx = (oapvm_ctx_t *)id;
40 oapv_assert_rv(ctx->magic == OAPVM_MAGIC_CODE, NULL);
41 return ctx;
42 }
43
meta_mdp_find_last_with_check(oapv_md_t * md,int type,unsigned char * uuid)44 static oapv_mdp_t **meta_mdp_find_last_with_check(oapv_md_t *md, int type, unsigned char *uuid)
45 {
46 oapv_mdp_t **last_mdp = &md->md_payload;
47
48 while((*last_mdp) != NULL) {
49 if((*last_mdp) == NULL)
50 break;
51 if((*last_mdp)->pld_type == type) {
52 if(type == OAPV_METADATA_USER_DEFINED) {
53 if(oapv_mcmp(uuid, (*last_mdp)->pld_data, 16) == 0) {
54 return NULL;
55 }
56 }
57 else {
58 return NULL;
59 }
60 }
61 last_mdp = &((*last_mdp)->next);
62 }
63 return last_mdp;
64 }
65
meta_md_find_mdp(oapv_md_t * md,int mdt)66 static oapv_mdp_t *meta_md_find_mdp(oapv_md_t *md, int mdt)
67 {
68 oapv_mdp_t *mdp = md->md_payload;
69
70 while(mdp != NULL) {
71 if(mdp->pld_type == mdt) {
72 break;
73 }
74 mdp = mdp->next;
75 }
76
77 return mdp;
78 }
79
meta_md_free_mdp(oapv_mdp_t * mdp)80 static int meta_md_free_mdp(oapv_mdp_t *mdp)
81 {
82 oapv_mfree(mdp->pld_data);
83 return OAPV_OK;
84 }
85
meta_md_rm_mdp(oapv_md_t * md,int mdt)86 static int meta_md_rm_mdp(oapv_md_t *md, int mdt)
87 {
88 oapv_mdp_t *mdp = md->md_payload;
89 oapv_mdp_t *mdp_prev = NULL;
90
91 while(mdp->pld_type != mdt && mdp->next != NULL) {
92 mdp_prev = mdp;
93 mdp = mdp->next;
94 }
95
96 if(mdp->pld_type == mdt) {
97 if(mdp_prev == NULL) {
98 md->md_payload = NULL;
99 }
100 else {
101 mdp_prev->next = mdp->next;
102 }
103 meta_md_free_mdp(mdp);
104 md->md_num--;
105 return OAPV_OK;
106 }
107
108 return OAPV_ERR_NOT_FOUND;
109 }
110
meta_md_rm_usd(oapv_md_t * md,unsigned char * uuid)111 static int meta_md_rm_usd(oapv_md_t *md, unsigned char *uuid)
112 {
113 oapv_mdp_t *mdp = md->md_payload;
114 oapv_mdp_t *mdp_prev = NULL;
115 while(mdp != NULL) {
116 if(mdp->pld_type == OAPV_METADATA_USER_DEFINED) {
117 if(oapv_mcmp(uuid, mdp->pld_data, 16) == 0) {
118 if(mdp_prev == NULL) {
119 md->md_payload = NULL;
120 }
121 else {
122 mdp_prev->next = mdp->next;
123 }
124 oapv_assert_rv(md->md_size >= mdp->pld_size, OAPV_ERR_UNEXPECTED);
125 md->md_size -= mdp->pld_size;
126 meta_md_free_mdp(mdp);
127 md->md_num--;
128 return OAPV_OK;
129 }
130 }
131 mdp_prev = mdp;
132 mdp = mdp->next;
133 }
134
135 return OAPV_ERR_NOT_FOUND;
136 }
137
meta_md_find_usd(oapv_md_t * md,unsigned char * uuid)138 static oapv_mdp_t *meta_md_find_usd(oapv_md_t *md, unsigned char *uuid)
139 {
140 oapv_mdp_t *mdp = md->md_payload;
141 while(mdp != NULL) {
142 if(mdp->pld_type == OAPV_METADATA_USER_DEFINED) {
143 oapv_md_usd_t *usd = (oapv_md_usd_t *)mdp->pld_data;
144 if(oapv_mcmp(uuid, usd->uuid, 16) == 0) {
145 return mdp;
146 }
147 }
148 mdp = mdp->next;
149 }
150
151 return NULL;
152 }
153
meta_verify_mdp_data(int type,int size,u8 * data)154 static int meta_verify_mdp_data(int type, int size, u8 *data)
155 {
156 if(type == OAPV_METADATA_ITU_T_T35) {
157 if(size == 0) {
158 return OAPV_ERR_INVALID_ARGUMENT;
159 }
160 if(*data == 0xFF) {
161 if(size == 1) {
162 return OAPV_ERR_INVALID_ARGUMENT;
163 }
164 }
165 }
166 else if(type == OAPV_METADATA_MDCV) {
167 if(size != 24) {
168 return OAPV_ERR_INVALID_ARGUMENT;
169 }
170 }
171 else if(type == OAPV_METADATA_CLL) {
172 if(size != 4) {
173 return OAPV_ERR_INVALID_ARGUMENT;
174 }
175 }
176 else if(type == OAPV_METADATA_USER_DEFINED) {
177 if(size < 16) {
178 return OAPV_ERR_INVALID_ARGUMENT;
179 }
180 }
181 else {
182 return OAPV_OK;
183 }
184 return OAPV_OK;
185 }
186
meta_free_md(oapv_md_t * md)187 static void meta_free_md(oapv_md_t *md)
188 {
189 oapv_mdp_t *mdp = md->md_payload;
190 while(mdp != NULL) {
191 oapv_mdp_t *tmp_mdp = mdp;
192 mdp = mdp->next;
193 if(tmp_mdp->pld_data != NULL) {
194 oapv_mfree(tmp_mdp->pld_data);
195 }
196 oapv_mfree(tmp_mdp);
197 }
198 }
199
oapvm_set(oapvm_t mid,int group_id,int type,void * data,int size,unsigned char * uuid)200 int oapvm_set(oapvm_t mid, int group_id, int type, void *data, int size, unsigned char *uuid)
201 {
202 oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
203
204 int ret = meta_verify_mdp_data(type, size, (u8 *)data);
205 oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
206
207 int md_list_idx = 0;
208 while(md_list_idx < md_list->num) {
209 if(md_list->group_ids[md_list_idx] == group_id) {
210 break;
211 }
212 md_list_idx++;
213 }
214 if(md_list_idx == md_list->num) {
215 md_list->num++;
216 }
217 md_list->group_ids[md_list_idx] = group_id;
218 oapv_mdp_t **last_ptr = meta_mdp_find_last_with_check(&md_list->md_arr[md_list_idx], type,
219 (type == OAPV_METADATA_USER_DEFINED) ? uuid : NULL);
220 while(last_ptr == NULL) {
221 oapvm_rem(mid, group_id, type, uuid);
222 last_ptr = meta_mdp_find_last_with_check(&md_list->md_arr[md_list_idx], type,
223 (type == OAPV_METADATA_USER_DEFINED) ? uuid : NULL);
224 }
225 oapv_mdp_t *tmp_mdp = oapv_malloc(sizeof(oapv_mdp_t));
226 oapv_assert_rv(tmp_mdp != NULL, OAPV_ERR_OUT_OF_MEMORY);
227
228 oapv_mset(tmp_mdp, 0, sizeof(oapv_mdp_t));
229 tmp_mdp->pld_size = size;
230 tmp_mdp->pld_type = type;
231 tmp_mdp->pld_data = data;
232 *last_ptr = tmp_mdp;
233
234 /* calculate length of payload type */
235 int tmp_mpt = type;
236 while(tmp_mpt >= 255) {
237 tmp_mpt -= 255;
238 md_list->md_arr[md_list_idx].md_size += 1;
239 }
240 md_list->md_arr[md_list_idx].md_size += 1;
241
242 /* calculate length of payload data size */
243 int tmp_mps = size;
244 while(tmp_mps >= 255) {
245 tmp_mps -= 255;
246 md_list->md_arr[md_list_idx].md_size += 1;
247 }
248 md_list->md_arr[md_list_idx].md_size += 1;
249
250 md_list->md_arr[md_list_idx].md_size += tmp_mdp->pld_size;
251 md_list->md_arr[md_list_idx].md_num++;
252 return OAPV_OK;
253 }
254
oapvm_get(oapvm_t mid,int group_id,int type,void ** data,int * size,unsigned char * uuid)255 int oapvm_get(oapvm_t mid, int group_id, int type, void **data, int *size, unsigned char *uuid)
256 {
257 oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
258 for(int i = 0; i < md_list->num; i++) {
259 if(group_id != md_list->group_ids[i]) {
260 continue;
261 }
262 oapv_mdp_t *mdp = (type == OAPV_METADATA_USER_DEFINED) ? meta_md_find_usd(&md_list->md_arr[i], uuid) : meta_md_find_mdp(&md_list->md_arr[i], type);
263 if(mdp != NULL) {
264 *data = mdp->pld_data;
265 *size = mdp->pld_size;
266 return OAPV_OK;
267 }
268 }
269
270 return OAPV_ERR_NOT_FOUND;
271 }
oapvm_rem(oapvm_t mid,int group_id,int type,unsigned char * uuid)272 int oapvm_rem(oapvm_t mid, int group_id, int type, unsigned char *uuid)
273 {
274 oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
275 int md_list_idx = 0;
276 while(md_list_idx < md_list->num) {
277 if(md_list->group_ids[md_list_idx] == group_id) {
278 break;
279 }
280 md_list_idx++;
281 }
282 oapv_assert_rv(md_list_idx < md_list->num, OAPV_ERR_NOT_FOUND);
283 if(type == OAPV_METADATA_USER_DEFINED) {
284 return meta_md_rm_usd(&md_list->md_arr[md_list_idx], uuid);
285 }
286 return meta_md_rm_mdp(&md_list->md_arr[md_list_idx], type);
287 }
288
oapvm_set_all(oapvm_t mid,oapvm_payload_t * pld,int num_plds)289 int oapvm_set_all(oapvm_t mid, oapvm_payload_t *pld, int num_plds)
290 {
291 int ret;
292 oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
293 for(int i = 0; i < num_plds; i++) {
294 ret = meta_verify_mdp_data(pld[i].type, pld[i].data_size, (u8 *)pld[i].data);
295 oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
296
297 int md_list_idx = 0;
298 while(md_list_idx < md_list->num) {
299 if(md_list->group_ids[md_list_idx] == pld[i].group_id) {
300 break;
301 }
302 md_list_idx++;
303 }
304 if(md_list_idx == md_list->num) {
305 md_list->num++;
306 }
307
308 md_list->group_ids[md_list_idx] = pld[i].group_id;
309 md_list->md_arr[md_list_idx].md_num++;
310 oapv_mdp_t **last_ptr = meta_mdp_find_last_with_check(&md_list->md_arr[md_list_idx], pld[i].type,
311 (pld[i].type == OAPV_METADATA_USER_DEFINED) ? pld[i].uuid : NULL);
312 while(last_ptr == NULL) {
313 oapvm_rem(mid, pld[i].group_id, pld[i].type, pld[i].uuid);
314 last_ptr = meta_mdp_find_last_with_check(&md_list->md_arr[md_list_idx], pld[i].type,
315 (pld[i].type == OAPV_METADATA_USER_DEFINED) ? pld[i].uuid : NULL);
316 }
317 oapv_mdp_t *tmp_mdp = oapv_malloc(sizeof(oapv_mdp_t));
318 oapv_assert_rv(tmp_mdp != NULL, OAPV_ERR_OUT_OF_MEMORY);
319 oapv_mset(tmp_mdp, 0, sizeof(oapv_mdp_t));
320 tmp_mdp->pld_size = pld[i].data_size;
321 tmp_mdp->pld_type = pld[i].type;
322 tmp_mdp->pld_data = pld[i].data;
323 md_list->md_arr[md_list_idx].md_size += tmp_mdp->pld_size;
324
325 *last_ptr = tmp_mdp;
326 }
327 return OAPV_OK;
328
329 ERR:
330 return ret;
331 }
332
oapvm_get_all(oapvm_t mid,oapvm_payload_t * pld,int * num_plds)333 int oapvm_get_all(oapvm_t mid, oapvm_payload_t *pld, int *num_plds)
334 {
335 oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
336 if(pld == NULL) {
337 int num_payload = 0;
338 for(int i = 0; i < md_list->num; i++) {
339 num_payload += md_list->md_arr[i].md_num;
340 }
341 *num_plds = num_payload;
342 return OAPV_OK;
343 }
344 int p_cnt = 0;
345 for(int i = 0; i < md_list->num; i++) {
346 int group_id = md_list->group_ids[i];
347 oapv_mdp_t *mdp = md_list->md_arr[i].md_payload;
348 while(mdp != NULL) {
349 oapv_assert_rv(p_cnt < *num_plds, OAPV_ERR_REACHED_MAX);
350 pld[p_cnt].group_id = group_id;
351 pld[p_cnt].data_size = mdp->pld_size;
352 pld[p_cnt].data = mdp->pld_data;
353 pld[p_cnt].type = mdp->pld_type;
354 if(pld[p_cnt].type == OAPV_METADATA_USER_DEFINED) {
355 oapv_mcpy(pld[p_cnt].uuid, mdp->pld_data, 16);
356 }
357 else {
358 oapv_mset(pld[p_cnt].uuid, 0, 16);
359 }
360 p_cnt++;
361 mdp = mdp->next;
362 }
363 }
364 *num_plds = p_cnt;
365 return OAPV_OK;
366 }
367
oapvm_rem_all(oapvm_t mid)368 void oapvm_rem_all(oapvm_t mid)
369 {
370
371 oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
372 for(int i = 0; i < md_list->num; i++) {
373 meta_free_md(&md_list->md_arr[i]);
374 oapv_mset(&md_list->md_arr[i], 0, sizeof(oapv_md_t));
375 }
376 md_list->num = 0;
377 }
378
oapvm_create(int * err)379 oapvm_t oapvm_create(int *err)
380 {
381 oapvm_ctx_t *md_list;
382 md_list = oapv_malloc(sizeof(oapvm_ctx_t));
383 if(md_list == NULL) {
384 *err = OAPV_ERR_OUT_OF_MEMORY;
385 return NULL;
386 }
387 oapv_mset(md_list, 0, sizeof(oapvm_ctx_t));
388
389 md_list->magic = OAPVM_MAGIC_CODE;
390 return md_list;
391 }
392
oapvm_delete(oapvm_t mid)393 void oapvm_delete(oapvm_t mid)
394 {
395 oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
396 for(int i = 0; i < md_list->num; i++) {
397 meta_free_md(&md_list->md_arr[i]);
398 }
399 oapv_mfree(md_list);
400 }
401