1 /*
2 * This file has been copied from the cddl-gen submodule.
3 * Commit 9f77837f9950da1633d22abf6181a830521a6688
4 */
5
6 /*
7 * Copyright (c) 2020 Nordic Semiconductor ASA
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include <stdint.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <string.h>
16 #include "cbor_decode.h"
17 #include "cbor_common.h"
18
19
20 /** Return value length from additional value.
21 */
additional_len(uint8_t additional)22 static uint32_t additional_len(uint8_t additional)
23 {
24 if (24 <= additional && additional <= 27) {
25 /* 24 => 1
26 * 25 => 2
27 * 26 => 4
28 * 27 => 8
29 */
30 return 1 << (additional - 24);
31 }
32 return 0;
33 }
34
35 /** Extract the major type, i.e. the first 3 bits of the header byte. */
36 #define MAJOR_TYPE(header_byte) (((header_byte) >> 5) & 0x7)
37
38 /** Extract the additional info, i.e. the last 5 bits of the header byte. */
39 #define ADDITIONAL(header_byte) ((header_byte) & 0x1F)
40
41
42 #define FAIL_AND_DECR_IF(expr) \
43 do {\
44 if (expr) { \
45 (state->payload)--; \
46 FAIL(); \
47 } \
48 } while(0)
49
50 #define FAIL_IF(expr) \
51 do {\
52 if (expr) { \
53 FAIL(); \
54 } \
55 } while(0)
56
57
58 #define FAIL_RESTORE() \
59 state->payload = state->payload_bak; \
60 state->elem_count++; \
61 FAIL()
62
63 /** Get a single value.
64 *
65 * @details @p ppayload must point to the header byte. This function will
66 * retrieve the value (either from within the additional info, or from
67 * the subsequent bytes) and return it in the result. The result can
68 * have arbitrary length.
69 *
70 * The function will also validate
71 * - Min/max constraints on the value.
72 * - That @p payload doesn't overrun past @p payload_end.
73 * - That @p elem_count has not been exhausted.
74 *
75 * @p ppayload and @p elem_count are updated if the function
76 * succeeds. If not, they are left unchanged.
77 *
78 * CBOR values are always big-endian, so this function converts from
79 * big to little-endian if necessary (@ref CONFIG_BIG_ENDIAN).
80 */
value_extract(cbor_state_t * state,void * const result,uint32_t result_len)81 static bool value_extract(cbor_state_t *state,
82 void *const result, uint32_t result_len)
83 {
84 cbor_trace();
85 cbor_assert(result_len != 0, "0-length result not supported.\n");
86 cbor_assert(result != NULL, NULL);
87
88 FAIL_IF((state->elem_count == 0) \
89 || (state->payload >= state->payload_end));
90
91 uint8_t *u8_result = (uint8_t *)result;
92 uint8_t additional = ADDITIONAL(*state->payload);
93
94 state->payload_bak = state->payload;
95 (state->payload)++;
96
97 memset(result, 0, result_len);
98 if (additional <= VALUE_IN_HEADER) {
99 #ifdef CONFIG_BIG_ENDIAN
100 u8_result[result_len - 1] = additional;
101 #else
102 u8_result[0] = additional;
103 #endif /* CONFIG_BIG_ENDIAN */
104 } else {
105 uint32_t len = additional_len(additional);
106
107 FAIL_AND_DECR_IF(len > result_len);
108 FAIL_AND_DECR_IF((state->payload + len)
109 > state->payload_end);
110
111 #ifdef CONFIG_BIG_ENDIAN
112 memcpy(&u8_result[result_len - len], state->payload, len);
113 #else
114 for (uint32_t i = 0; i < len; i++) {
115 u8_result[i] = (state->payload)[len - i - 1];
116 }
117 #endif /* CONFIG_BIG_ENDIAN */
118
119 (state->payload) += len;
120 }
121
122 (state->elem_count)--;
123 return true;
124 }
125
126
int32_decode(cbor_state_t * state,int32_t * result)127 static bool int32_decode(cbor_state_t *state, int32_t *result)
128 {
129 FAIL_IF(state->payload >= state->payload_end);
130 uint8_t major_type = MAJOR_TYPE(*state->payload);
131 uint32_t uint_result;
132 int32_t int_result;
133
134 if (!value_extract(state, &uint_result, 4)) {
135 FAIL();
136 }
137
138 cbor_print("uintval: %u\r\n", uint_result);
139 if (uint_result >= (1 << (8*sizeof(uint_result)-1))) {
140 /* Value is too large to fit in a signed integer. */
141 FAIL_RESTORE();
142 }
143
144 if (major_type == CBOR_MAJOR_TYPE_NINT) {
145 /* Convert from CBOR's representation. */
146 int_result = -1 - uint_result;
147 } else {
148 int_result = uint_result;
149 }
150
151 cbor_print("val: %d\r\n", int_result);
152 *result = int_result;
153 return true;
154 }
155
156
intx32_decode(cbor_state_t * state,int32_t * result)157 bool intx32_decode(cbor_state_t *state, int32_t *result)
158 {
159 FAIL_IF(state->payload >= state->payload_end);
160 uint8_t major_type = MAJOR_TYPE(*state->payload);
161
162 if (major_type != CBOR_MAJOR_TYPE_PINT
163 && major_type != CBOR_MAJOR_TYPE_NINT) {
164 /* Value to be read doesn't have the right type. */
165 FAIL();
166 }
167
168 if (!int32_decode(state, result)) {
169 FAIL();
170 }
171 return true;
172 }
173
intx32_expect(cbor_state_t * state,int32_t result)174 bool intx32_expect(cbor_state_t *state, int32_t result)
175 {
176 int32_t value;
177
178 if (!intx32_decode(state, &value)) {
179 FAIL();
180 }
181
182 if (value != result) {
183 cbor_print("%d != %d\r\n", value, result);
184 FAIL_RESTORE();
185 }
186 return true;
187 }
188
189
uint32_decode(cbor_state_t * state,uint32_t * result)190 static bool uint32_decode(cbor_state_t *state, uint32_t *result)
191 {
192 if (!value_extract(state, result, 4)) {
193 FAIL();
194 }
195
196 return true;
197 }
198
199
uintx32_decode(cbor_state_t * state,uint32_t * result)200 bool uintx32_decode(cbor_state_t *state, uint32_t *result)
201 {
202 FAIL_IF(state->payload >= state->payload_end);
203 uint8_t major_type = MAJOR_TYPE(*state->payload);
204
205 if (major_type != CBOR_MAJOR_TYPE_PINT) {
206 /* Value to be read doesn't have the right type. */
207 FAIL();
208 }
209 if (!uint32_decode(state, result)) {
210 FAIL();
211 }
212 return true;
213 }
214
uintx32_expect(cbor_state_t * state,uint32_t result)215 bool uintx32_expect(cbor_state_t *state, uint32_t result)
216 {
217 uint32_t value;
218
219 if (!uintx32_decode(state, &value)) {
220 FAIL();
221 }
222 if (value != result) {
223 cbor_print("%u != %u\r\n", value, result);
224 FAIL_RESTORE();
225 }
226 return true;
227 }
228
uintx32_expect_union(cbor_state_t * state,uint32_t result)229 bool uintx32_expect_union(cbor_state_t *state, uint32_t result)
230 {
231 union_elem_code(state);
232 return uintx32_expect(state, result);
233 }
234
235
strx_start_decode(cbor_state_t * state,cbor_string_type_t * result,cbor_major_type_t exp_major_type)236 static bool strx_start_decode(cbor_state_t *state,
237 cbor_string_type_t *result, cbor_major_type_t exp_major_type)
238 {
239 FAIL_IF(state->payload >= state->payload_end);
240 uint8_t major_type = MAJOR_TYPE(*state->payload);
241
242 if (major_type != exp_major_type) {
243 FAIL();
244 }
245
246 if (!uint32_decode(state, &result->len)) {
247 FAIL();
248 }
249
250 if (result->len > (state->payload_end - state->payload)) {
251 cbor_print("error: 0x%x > 0x%x\r\n",
252 (uint32_t)result->len,
253 (uint32_t)(state->payload_end - state->payload));
254 FAIL_RESTORE();
255 }
256
257 result->value = state->payload;
258 return true;
259 }
260
bstrx_cbor_start_decode(cbor_state_t * state,cbor_string_type_t * result)261 bool bstrx_cbor_start_decode(cbor_state_t *state, cbor_string_type_t *result)
262 {
263 if(!strx_start_decode(state, result, CBOR_MAJOR_TYPE_BSTR)) {
264 FAIL();
265 }
266
267 if (!new_backup(state, 0xFFFFFFFF)) {
268 FAIL_RESTORE();
269 }
270
271 /* Overflow is checked in strx_start_decode() */
272 state->payload_end = result->value + result->len;
273 return true;
274 }
275
bstrx_cbor_end_decode(cbor_state_t * state)276 bool bstrx_cbor_end_decode(cbor_state_t *state)
277 {
278 if (state->payload != state->payload_end) {
279 FAIL();
280 }
281 if (!restore_backup(state,
282 FLAG_RESTORE | FLAG_DISCARD | FLAG_TRANSFER_PAYLOAD,
283 0xFFFFFFFF)) {
284 FAIL();
285 }
286
287 return true;
288 }
289
290
strx_decode(cbor_state_t * state,cbor_string_type_t * result,cbor_major_type_t exp_major_type)291 bool strx_decode(cbor_state_t *state, cbor_string_type_t *result,
292 cbor_major_type_t exp_major_type)
293 {
294 if (!strx_start_decode(state, result, exp_major_type)) {
295 FAIL();
296 }
297
298 /* Overflow is checked in strx_start_decode() */
299 (state->payload) += result->len;
300 return true;
301 }
302
303
strx_expect(cbor_state_t * state,cbor_string_type_t * result,cbor_major_type_t exp_major_type)304 bool strx_expect(cbor_state_t *state, cbor_string_type_t *result,
305 cbor_major_type_t exp_major_type)
306 {
307 cbor_string_type_t tmp_result;
308
309 if (!strx_decode(state, &tmp_result, exp_major_type)) {
310 FAIL();
311 }
312 if ((tmp_result.len != result->len)
313 || memcmp(result->value, tmp_result.value, tmp_result.len)) {
314 FAIL_RESTORE();
315 }
316 return true;
317 }
318
319
bstrx_decode(cbor_state_t * state,cbor_string_type_t * result)320 bool bstrx_decode(cbor_state_t *state, cbor_string_type_t *result)
321 {
322 return strx_decode(state, result, CBOR_MAJOR_TYPE_BSTR);
323 }
324
325
bstrx_expect(cbor_state_t * state,cbor_string_type_t * result)326 bool bstrx_expect(cbor_state_t *state, cbor_string_type_t *result)
327 {
328 return strx_expect(state, result, CBOR_MAJOR_TYPE_BSTR);
329 }
330
331
tstrx_decode(cbor_state_t * state,cbor_string_type_t * result)332 bool tstrx_decode(cbor_state_t *state, cbor_string_type_t *result)
333 {
334 return strx_decode(state, result, CBOR_MAJOR_TYPE_TSTR);
335 }
336
337
tstrx_expect(cbor_state_t * state,cbor_string_type_t * result)338 bool tstrx_expect(cbor_state_t *state, cbor_string_type_t *result)
339 {
340 return strx_expect(state, result, CBOR_MAJOR_TYPE_TSTR);
341 }
342
343
list_map_start_decode(cbor_state_t * state,cbor_major_type_t exp_major_type)344 static bool list_map_start_decode(cbor_state_t *state,
345 cbor_major_type_t exp_major_type)
346 {
347 FAIL_IF(state->payload >= state->payload_end);
348 uint8_t major_type = MAJOR_TYPE(*state->payload);
349 uint32_t new_elem_count;
350
351 if (major_type != exp_major_type) {
352 FAIL();
353 }
354
355 if (!uint32_decode(state, &new_elem_count)) {
356 FAIL();
357 }
358
359 if (!new_backup(state, new_elem_count)) {
360 FAIL_RESTORE();
361 }
362
363 return true;
364 }
365
366
list_start_decode(cbor_state_t * state)367 bool list_start_decode(cbor_state_t *state)
368 {
369 return list_map_start_decode(state, CBOR_MAJOR_TYPE_LIST);
370 }
371
372
map_start_decode(cbor_state_t * state)373 bool map_start_decode(cbor_state_t *state)
374 {
375 bool ret = list_map_start_decode(state, CBOR_MAJOR_TYPE_MAP);
376
377 if (ret) {
378 state->elem_count *= 2;
379 }
380 return ret;
381 }
382
383
list_map_end_decode(cbor_state_t * state)384 bool list_map_end_decode(cbor_state_t *state)
385 {
386 if (!restore_backup(state,
387 FLAG_RESTORE | FLAG_DISCARD | FLAG_TRANSFER_PAYLOAD,
388 0)) {
389 FAIL();
390 }
391
392 return true;
393 }
394
395
list_end_decode(cbor_state_t * state)396 bool list_end_decode(cbor_state_t *state)
397 {
398 return list_map_end_decode(state);
399 }
400
401
map_end_decode(cbor_state_t * state)402 bool map_end_decode(cbor_state_t *state)
403 {
404 return list_map_end_decode(state);
405 }
406
407
primx_decode(cbor_state_t * state,uint32_t * result)408 static bool primx_decode(cbor_state_t *state, uint32_t *result)
409 {
410 FAIL_IF(state->payload >= state->payload_end);
411 uint8_t major_type = MAJOR_TYPE(*state->payload);
412
413 if (major_type != CBOR_MAJOR_TYPE_PRIM) {
414 /* Value to be read doesn't have the right type. */
415 FAIL();
416 }
417 if (!uint32_decode(state, result)) {
418 FAIL();
419 }
420 if (*result > 0xFF) {
421 FAIL_RESTORE();
422 }
423 return true;
424 }
425
primx_expect(cbor_state_t * state,uint32_t result)426 static bool primx_expect(cbor_state_t *state, uint32_t result)
427 {
428 uint32_t value;
429
430 if (!primx_decode(state, &value)) {
431 FAIL();
432 }
433 if (value != result) {
434 FAIL_RESTORE();
435 }
436 return true;
437 }
438
439
nilx_expect(cbor_state_t * state,void * result)440 bool nilx_expect(cbor_state_t *state, void *result)
441 {
442 if (!primx_expect(state, 22)) {
443 FAIL();
444 }
445 return true;
446 }
447
448
boolx_decode(cbor_state_t * state,bool * result)449 bool boolx_decode(cbor_state_t *state, bool *result)
450 {
451 uint32_t tmp_result;
452
453 if (!primx_decode(state, &tmp_result)) {
454 FAIL();
455 }
456 (*result) = tmp_result - BOOL_TO_PRIM;
457
458 cbor_print("boolval: %u\r\n", *result);
459 return true;
460 }
461
462
boolx_expect(cbor_state_t * state,bool result)463 bool boolx_expect(cbor_state_t *state, bool result)
464 {
465 bool value;
466
467 if (!boolx_decode(state, &value)) {
468 FAIL();
469 }
470 if (value != result) {
471 FAIL_RESTORE();
472 }
473 return true;
474 }
475
476
double_decode(cbor_state_t * state,double * result)477 bool double_decode(cbor_state_t *state, double *result)
478 {
479 FAIL_IF(state->payload >= state->payload_end);
480 uint8_t major_type = MAJOR_TYPE(*state->payload);
481
482 if (major_type != CBOR_MAJOR_TYPE_PRIM) {
483 /* Value to be read doesn't have the right type. */
484 FAIL();
485 }
486 if (!value_extract(state, result,
487 sizeof(*result))) {
488 FAIL();
489 }
490 return true;
491 }
492
493
double_expect(cbor_state_t * state,double * result)494 bool double_expect(cbor_state_t *state, double *result)
495 {
496 double value;
497
498 if (!double_decode(state, &value)) {
499 FAIL();
500 }
501 if (value != *result) {
502 FAIL_RESTORE();
503 }
504 return true;
505 }
506
507
any_decode(cbor_state_t * state,void * result)508 bool any_decode(cbor_state_t *state, void *result)
509 {
510 cbor_assert(result == NULL,
511 "'any' type cannot be returned, only skipped.\n");
512
513 FAIL_IF(state->payload >= state->payload_end);
514 uint8_t major_type = MAJOR_TYPE(*state->payload);
515 uint32_t value;
516 uint32_t num_decode;
517 void *null_result = NULL;
518 uint32_t temp_elem_count;
519 uint8_t const *payload_bak;
520
521 if (!value_extract(state, &value, sizeof(value))) {
522 /* Can happen because of elem_count (or payload_end) */
523 FAIL();
524 }
525
526 switch (major_type) {
527 case CBOR_MAJOR_TYPE_BSTR:
528 case CBOR_MAJOR_TYPE_TSTR:
529 (state->payload) += value;
530 break;
531 case CBOR_MAJOR_TYPE_MAP:
532 value *= 2; /* Because all members have a key. */
533 /* Fallthrough */
534 case CBOR_MAJOR_TYPE_LIST:
535 temp_elem_count = state->elem_count;
536 payload_bak = state->payload;
537 state->elem_count = value;
538 if (!multi_decode(value, value, &num_decode,
539 (void *)any_decode, state,
540 &null_result, 0)) {
541 state->elem_count = temp_elem_count;
542 state->payload = payload_bak;
543 FAIL();
544 }
545 state->elem_count = temp_elem_count;
546 break;
547 default:
548 /* Do nothing */
549 break;
550 }
551
552 return true;
553 }
554
555
tag_decode(cbor_state_t * state,uint32_t * result)556 bool tag_decode(cbor_state_t *state, uint32_t *result)
557 {
558 FAIL_IF(state->payload >= state->payload_end);
559 uint8_t major_type = MAJOR_TYPE(*state->payload);
560
561 if (major_type != CBOR_MAJOR_TYPE_TAG) {
562 /* Value to be read doesn't have the right type. */
563 FAIL();
564 }
565 if (!uint32_decode(state, result)) {
566 FAIL();
567 }
568 state->elem_count++;
569 return true;
570 }
571
572
tag_expect(cbor_state_t * state,uint32_t result)573 bool tag_expect(cbor_state_t *state, uint32_t result)
574 {
575 uint32_t tag_val;
576
577 if (!tag_decode(state, &tag_val)) {
578 FAIL();
579 }
580 if (tag_val != result) {
581 FAIL_RESTORE();
582 }
583 return true;
584 }
585
586
multi_decode(uint32_t min_decode,uint32_t max_decode,uint32_t * num_decode,cbor_decoder_t decoder,cbor_state_t * state,void * result,uint32_t result_len)587 bool multi_decode(uint32_t min_decode,
588 uint32_t max_decode,
589 uint32_t *num_decode,
590 cbor_decoder_t decoder,
591 cbor_state_t *state,
592 void *result,
593 uint32_t result_len)
594 {
595 for (uint32_t i = 0; i < max_decode; i++) {
596 uint8_t const *payload_bak = state->payload;
597 uint32_t elem_count_bak = state->elem_count;
598
599 if (!decoder(state,
600 (uint8_t *)result + i*result_len)) {
601 *num_decode = i;
602 state->payload = payload_bak;
603 state->elem_count = elem_count_bak;
604 if (i < min_decode) {
605 FAIL();
606 } else {
607 cbor_print("Found %zu elements.\n", i);
608 }
609 return true;
610 }
611 }
612 cbor_print("Found %zu elements.\n", max_decode);
613 *num_decode = max_decode;
614 return true;
615 }
616
617
present_decode(uint32_t * present,cbor_decoder_t decoder,cbor_state_t * state,void * result)618 bool present_decode(uint32_t *present,
619 cbor_decoder_t decoder,
620 cbor_state_t *state,
621 void *result)
622 {
623 uint32_t num_decode;
624 bool retval = multi_decode(0, 1, &num_decode, decoder, state, result, 0);
625 if (retval) {
626 *present = num_decode;
627 }
628 return retval;
629 }
630