1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 Intel Corporation
4 **
5 ** Permission is hereby granted, free of charge, to any person obtaining a copy
6 ** of this software and associated documentation files (the "Software"), to deal
7 ** in the Software without restriction, including without limitation the rights
8 ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 ** copies of the Software, and to permit persons to whom the Software is
10 ** furnished to do so, subject to the following conditions:
11 **
12 ** The above copyright notice and this permission notice shall be included in
13 ** all copies or substantial portions of the Software.
14 **
15 ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ** THE SOFTWARE.
22 **
23 ****************************************************************************/
24
25 #ifndef _BSD_SOURCE
26 #define _BSD_SOURCE 1
27 #endif
28 #ifndef _DEFAULT_SOURCE
29 #define _DEFAULT_SOURCE 1
30 #endif
31 #ifndef __STDC_LIMIT_MACROS
32 # define __STDC_LIMIT_MACROS 1
33 #endif
34
35 #include "tinycbor/cbor.h"
36 #include "tinycbor/cborinternal_p.h"
37 #include "tinycbor/compilersupport_p.h"
38 #include "tinycbor/utf8_p.h"
39
40 #include <string.h>
41
42 #include <float.h>
43 #ifndef CBOR_NO_FLOATING_POINT
44 #include <math.h>
45 #endif
46
47
48 #ifndef CBOR_PARSER_MAX_RECURSIONS
49 # define CBOR_PARSER_MAX_RECURSIONS 1024
50 #endif
51
52 /**
53 * \addtogroup CborParsing
54 * @{
55 */
56
57 /**
58 * \enum CborValidationFlags
59 * The CborValidationFlags enum contains flags that control the validation of a
60 * CBOR stream.
61 *
62 * \value CborValidateBasic Validates only the syntax correctedness of the stream.
63 * \value CborValidateCanonical Validates that the stream is in canonical format, according to
64 * RFC 7049 section 3.9.
65 * \value CborValidateStrictMode Performs strict validation, according to RFC 7049 section 3.10.
66 * \value CborValidateStrictest Attempt to perform the strictest validation we know of.
67 *
68 * \value CborValidateShortestIntegrals (Canonical) Validate that integral numbers and lengths are
69 * enconded in their shortest form possible.
70 * \value CborValidateShortestFloatingPoint (Canonical) Validate that floating-point numbers are encoded
71 * in their shortest form possible.
72 * \value CborValidateShortestNumbers (Canonical) Validate both integrals and floating-point numbers
73 * are in their shortest form possible.
74 * \value CborValidateNoIndeterminateLength (Canonical) Validate that no string, array or map uses
75 * indeterminate length encoding.
76 * \value CborValidateMapIsSorted (Canonical & Strict mode) Validate that map keys appear in
77 * sorted order.
78 * \value CborValidateMapKeysAreUnique (Strict mode) Validate that map keys are unique.
79 * \value CborValidateTagUse (Strict mode) Validate that known tags are used with the
80 * correct types. This does not validate that the content of
81 * those types is syntactically correct.
82 * \value CborValidateUtf8 (Strict mode) Validate that text strings are appropriately
83 * encoded in UTF-8.
84 * \value CborValidateMapKeysAreString Validate that all map keys are text strings.
85 * \value CborValidateNoUndefined Validate that no elements of type "undefined" are present.
86 * \value CborValidateNoTags Validate that no tags are used.
87 * \value CborValidateFiniteFloatingPoint Validate that all floating point numbers are finite (no NaN or
88 * infinities are allowed).
89 * \value CborValidateCompleteData Validate that the stream is complete and there is no more data
90 * in the buffer.
91 * \value CborValidateNoUnknownSimpleTypesSA Validate that all Standards Action simple types are registered
92 * with IANA.
93 * \value CborValidateNoUnknownSimpleTypes Validate that all simple types used are registered with IANA.
94 * \value CborValidateNoUnknownTagsSA Validate that all Standard Actions tags are registered with IANA.
95 * \value CborValidateNoUnknownTagsSR Validate that all Standard Actions and Specification Required tags
96 * are registered with IANA (see below for limitations).
97 * \value CborValidateNoUnkonwnTags Validate that all tags are registered with IANA
98 * (see below for limitations).
99 *
100 * \par Simple type registry
101 * The CBOR specification requires that registration for use of the first 19
102 * simple types must be done by way of Standards Action. The rest of the simple
103 * types only require a specification. The official list can be obtained from
104 * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml.
105 *
106 * \par
107 * There are no registered simple types recognized by this release of TinyCBOR
108 * (beyond those defined by RFC 7049).
109 *
110 * \par Tag registry
111 * The CBOR specification requires that registration for use of the first 23
112 * tags must be done by way of Standards Action. The next up to tag 255 only
113 * require a specification. Finally, all other tags can be registered on a
114 * first-come-first-serve basis. The official list can be ontained from
115 * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml.
116 *
117 * \par
118 * Given the variability of this list, TinyCBOR cannot recognize all tags
119 * registered with IANA. Instead, the implementation only recognizes tags
120 * that are backed by an RFC.
121 *
122 * \par
123 * These are the tags known to the current TinyCBOR release:
124 <table>
125 <tr>
126 <th>Tag</th>
127 <th>Data Item</th>
128 <th>Semantics</th>
129 </tr>
130 <tr>
131 <td>0</td>
132 <td>UTF-8 text string</td>
133 <td>Standard date/time string</td>
134 </td>
135 <tr>
136 <td>1</td>
137 <td>integer</td>
138 <td>Epoch-based date/time</td>
139 </td>
140 <tr>
141 <td>2</td>
142 <td>byte string</td>
143 <td>Positive bignum</td>
144 </td>
145 <tr>
146 <td>3</td>
147 <td>byte string</td>
148 <td>Negative bignum</td>
149 </td>
150 <tr>
151 <td>4</td>
152 <td>array</td>
153 <td>Decimal fraction</td>
154 </td>
155 <tr>
156 <td>5</td>
157 <td>array</td>
158 <td>Bigfloat</td>
159 </td>
160 <tr>
161 <td>16</td>
162 <td>array</td>
163 <td>COSE Single Recipient Encrypted Data Object (RFC 8152)</td>
164 </td>
165 <tr>
166 <td>17</td>
167 <td>array</td>
168 <td>COSE Mac w/o Recipients Object (RFC 8152)</td>
169 </td>
170 <tr>
171 <td>18</td>
172 <td>array</td>
173 <td>COSE Single Signer Data Object (RFC 8162)</td>
174 </td>
175 <tr>
176 <td>21</td>
177 <td>byte string, array, map</td>
178 <td>Expected conversion to base64url encoding</td>
179 </td>
180 <tr>
181 <td>22</td>
182 <td>byte string, array, map</td>
183 <td>Expected conversion to base64 encoding</td>
184 </td>
185 <tr>
186 <td>23</td>
187 <td>byte string, array, map</td>
188 <td>Expected conversion to base16 encoding</td>
189 </td>
190 <tr>
191 <td>24</td>
192 <td>byte string</td>
193 <td>Encoded CBOR data item</td>
194 </td>
195 <tr>
196 <td>32</td>
197 <td>UTF-8 text string</td>
198 <td>URI</td>
199 </td>
200 <tr>
201 <td>33</td>
202 <td>UTF-8 text string</td>
203 <td>base64url</td>
204 </td>
205 <tr>
206 <td>34</td>
207 <td>UTF-8 text string</td>
208 <td>base64</td>
209 </td>
210 <tr>
211 <td>35</td>
212 <td>UTF-8 text string</td>
213 <td>Regular expression</td>
214 </td>
215 <tr>
216 <td>36</td>
217 <td>UTF-8 text string</td>
218 <td>MIME message</td>
219 </td>
220 <tr>
221 <td>96</td>
222 <td>array</td>
223 <td>COSE Encrypted Data Object (RFC 8152)</td>
224 </td>
225 <tr>
226 <td>97</td>
227 <td>array</td>
228 <td>COSE MACed Data Object (RFC 8152)</td>
229 </td>
230 <tr>
231 <td>98</td>
232 <td>array</td>
233 <td>COSE Signed Data Object (RFC 8152)</td>
234 </td>
235 <tr>
236 <td>55799</td>
237 <td>any</td>
238 <td>Self-describe CBOR</td>
239 </td>
240 </table>
241 */
242
243 struct KnownTagData { uint32_t tag; uint32_t types; };
244 static const struct KnownTagData knownTagData[] = {
245 { 0, (uint8_t)CborTextStringType },
246 { 1, (uint8_t)(CborIntegerType+1) },
247 { 2, (uint8_t)CborByteStringType },
248 { 3, (uint8_t)CborByteStringType },
249 { 4, (uint8_t)CborArrayType },
250 { 5, (uint8_t)CborArrayType },
251 { 16, (uint8_t)CborArrayType },
252 { 17, (uint8_t)CborArrayType },
253 { 18, (uint8_t)CborArrayType },
254 { 21, (uint8_t)CborByteStringType | ((uint8_t)CborArrayType << 8) | ((uint8_t)CborMapType << 16) },
255 { 22, (uint8_t)CborByteStringType | ((uint8_t)CborArrayType << 8) | ((uint8_t)CborMapType << 16) },
256 { 23, (uint8_t)CborByteStringType | ((uint8_t)CborArrayType << 8) | ((uint8_t)CborMapType << 16) },
257 { 24, (uint8_t)CborByteStringType },
258 { 32, (uint8_t)CborTextStringType },
259 { 33, (uint8_t)CborTextStringType },
260 { 34, (uint8_t)CborTextStringType },
261 { 35, (uint8_t)CborTextStringType },
262 { 36, (uint8_t)CborTextStringType },
263 { 96, (uint8_t)CborArrayType },
264 { 97, (uint8_t)CborArrayType },
265 { 98, (uint8_t)CborArrayType },
266 { 55799, 0U }
267 };
268
269 static CborError validate_value(CborValue *it, int flags, int recursionLeft);
270
validate_utf8_string(const void * ptr,size_t n)271 static inline CborError validate_utf8_string(const void *ptr, size_t n)
272 {
273 const uint8_t *buffer = (const uint8_t *)ptr;
274 const uint8_t * const end = buffer + n;
275 while (buffer < end) {
276 uint32_t uc = get_utf8(&buffer, end);
277 if (uc == ~0U)
278 return CborErrorInvalidUtf8TextString;
279 }
280 return CborNoError;
281 }
282
validate_simple_type(uint8_t simple_type,int flags)283 static inline CborError validate_simple_type(uint8_t simple_type, int flags)
284 {
285 /* At current time, all known simple types are those from RFC 7049,
286 * which are parsed by the parser into different CBOR types.
287 * That means that if we've got here, the type is unknown */
288 if (simple_type < 32)
289 return (flags & CborValidateNoUnknownSimpleTypesSA) ? CborErrorUnknownSimpleType : CborNoError;
290 return (flags & CborValidateNoUnknownSimpleTypes) == CborValidateNoUnknownSimpleTypes ?
291 CborErrorUnknownSimpleType : CborNoError;
292 }
293
validate_number(const CborValue * it,CborType type,int flags)294 static inline CborError validate_number(const CborValue *it, CborType type, int flags)
295 {
296 CborError err = CborNoError;
297 uint64_t value;
298 int offset;
299
300 if ((flags & CborValidateShortestIntegrals) == 0)
301 return err;
302 if (type >= CborHalfFloatType && type <= CborDoubleType)
303 return err; /* checked elsewhere */
304
305 offset = it->offset;
306 err = _cbor_value_extract_number(it->parser, &offset, &value);
307 if (err)
308 return err;
309
310 size_t bytesUsed = (size_t)(offset - it->offset - 1);
311 size_t bytesNeeded = 0;
312 if (value >= Value8Bit)
313 ++bytesNeeded;
314 if (value > 0xffU)
315 ++bytesNeeded;
316 if (value > 0xffffU)
317 bytesNeeded += 2;
318 if (value > 0xffffffffU)
319 bytesNeeded += 4;
320 if (bytesNeeded < bytesUsed)
321 return CborErrorOverlongEncoding;
322 return CborNoError;
323 }
324
validate_tag(CborValue * it,CborTag tag,int flags,int recursionLeft)325 static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int recursionLeft)
326 {
327 CborType type = cbor_value_get_type(it);
328 const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
329 const struct KnownTagData *tagData = knownTagData;
330 const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount;
331
332 if (!recursionLeft)
333 return CborErrorNestingTooDeep;
334 if (flags & CborValidateNoTags)
335 return CborErrorExcludedType;
336
337 /* find the tag data, if any */
338 for ( ; tagData != knownTagDataEnd; ++tagData) {
339 if (tagData->tag < tag)
340 continue;
341 if (tagData->tag > tag)
342 tagData = NULL;
343 break;
344 }
345 if (tagData == knownTagDataEnd)
346 tagData = NULL;
347
348 if (flags & CborValidateNoUnknownTags && !tagData) {
349 /* tag not found */
350 if (flags & CborValidateNoUnknownTagsSA && tag < 24)
351 return CborErrorUnknownTag;
352 if ((flags & CborValidateNoUnknownTagsSR) == CborValidateNoUnknownTagsSR && tag < 256)
353 return CborErrorUnknownTag;
354 if ((flags & CborValidateNoUnknownTags) == CborValidateNoUnknownTags)
355 return CborErrorUnknownTag;
356 }
357
358 if (flags & CborValidateTagUse && tagData && tagData->types) {
359 uint32_t allowedTypes = tagData->types;
360
361 /* correct Integer so it's not zero */
362 if (type == CborIntegerType)
363 type = (CborType)(type + 1);
364
365 while (allowedTypes) {
366 if ((uint8_t)(allowedTypes & 0xff) == type)
367 break;
368 allowedTypes >>= 8;
369 }
370 if (!allowedTypes)
371 return CborErrorInappropriateTagForType;
372 }
373
374 return validate_value(it, flags, recursionLeft);
375 }
376
377 #ifndef CBOR_NO_FLOATING_POINT
validate_floating_point(CborValue * it,CborType type,int flags)378 static inline CborError validate_floating_point(CborValue *it, CborType type, int flags)
379 {
380 CborError err;
381 double val;
382 float valf;
383 uint16_t valf16;
384
385 if (type != CborDoubleType) {
386 if (type == CborFloatType) {
387 err = cbor_value_get_float(it, &valf);
388 val = valf;
389 } else {
390 # ifdef CBOR_NO_HALF_FLOAT_TYPE
391 (void)val16;
392 return CborErrorUnsupportedType;
393 # else
394 err = cbor_value_get_half_float(it, &valf16);
395 val = decode_half(valf16);
396 # endif
397 }
398 } else {
399 err = cbor_value_get_double(it, &val);
400 }
401 cbor_assert(err == CborNoError); /* can't fail */
402
403 int r = fpclassify(val);
404 if (r == FP_NAN || r == FP_INFINITE) {
405 if (flags & CborValidateFiniteFloatingPoint)
406 return CborErrorExcludedValue;
407 if (flags & CborValidateShortestFloatingPoint) {
408 if (type == CborDoubleType)
409 return CborErrorOverlongEncoding;
410 # ifndef CBOR_NO_HALF_FLOAT_TYPE
411 if (type == CborFloatType)
412 return CborErrorOverlongEncoding;
413 if (r == FP_NAN && valf16 != 0x7e00)
414 return CborErrorImproperValue;
415 if (r == FP_INFINITE && valf16 != 0x7c00 && valf16 != 0xfc00)
416 return CborErrorImproperValue;
417 # endif
418 }
419 }
420
421 if (flags & CborValidateShortestFloatingPoint && type > CborHalfFloatType) {
422 if (type == CborDoubleType) {
423 valf = (float)val;
424 if ((double)valf == val)
425 return CborErrorOverlongEncoding;
426 }
427 # ifndef CBOR_NO_HALF_FLOAT_TYPE
428 if (type == CborFloatType) {
429 valf16 = encode_half(valf);
430 if (valf == decode_half(valf16))
431 return CborErrorOverlongEncoding;
432 }
433 # endif
434 }
435
436 return CborNoError;
437 }
438 #endif
439
validate_container(CborValue * it,int containerType,int flags,int recursionLeft)440 static CborError validate_container(CborValue *it, int containerType, int flags, int recursionLeft)
441 {
442 CborError err;
443 int previous = -1;
444 int previous_end = -1;
445
446 if (!recursionLeft)
447 return CborErrorNestingTooDeep;
448
449 while (!cbor_value_at_end(it)) {
450 int current = it->offset;
451
452 if (containerType == CborMapType) {
453 if (flags & CborValidateMapKeysAreString) {
454 CborType type = cbor_value_get_type(it);
455 if (type == CborTagType) {
456 /* skip the tags */
457 CborValue copy = *it;
458 err = cbor_value_skip_tag(©);
459 if (err)
460 return err;
461 type = cbor_value_get_type(©);
462 }
463 if (type != CborTextStringType)
464 return CborErrorMapKeyNotString;
465 }
466 }
467
468 err = validate_value(it, flags, recursionLeft);
469 if (err)
470 return err;
471
472 if (containerType != CborMapType)
473 continue;
474
475 if (flags & CborValidateMapIsSorted) {
476 if (previous != -1) {
477 uint64_t len1, len2;
478 int offset;
479
480 /* extract the two lengths */
481 offset = previous;
482 _cbor_value_extract_number(it->parser, &offset, &len1);
483 offset = current;
484 _cbor_value_extract_number(it->parser, &offset, &len2);
485
486 if (len1 > len2)
487 return CborErrorMapNotSorted;
488 if (len1 == len2) {
489 int bytelen1 = (previous_end - previous);
490 int bytelen2 = (it->offset - current);
491 int i;
492
493 for (i = 0; i < (bytelen1 <= bytelen2 ? bytelen1 : bytelen2); i++) {
494 int r = it->parser->d->get8(it->parser->d, previous + i) -
495 it->parser->d->get8(it->parser->d, current + i);
496
497 if (r < 0) {
498 break;
499 }
500 if (r == 0 && bytelen1 != bytelen2)
501 r = bytelen1 < bytelen2 ? -1 : +1;
502 if (r > 0)
503 return CborErrorMapNotSorted;
504 if (r == 0 && (flags & CborValidateMapKeysAreUnique) == CborValidateMapKeysAreUnique)
505 return CborErrorMapKeysNotUnique;
506 }
507 }
508 }
509
510 previous = current;
511 previous_end = it->offset;
512 }
513
514 /* map: that was the key, so get the value */
515 err = validate_value(it, flags, recursionLeft);
516 if (err)
517 return err;
518 }
519 return CborNoError;
520 }
521
validate_value(CborValue * it,int flags,int recursionLeft)522 static CborError validate_value(CborValue *it, int flags, int recursionLeft)
523 {
524 CborError err;
525 CborType type = cbor_value_get_type(it);
526
527 if (cbor_value_is_length_known(it)) {
528 err = validate_number(it, type, flags);
529 if (err)
530 return err;
531 } else {
532 if (flags & CborValidateNoIndeterminateLength)
533 return CborErrorUnknownLength;
534 }
535
536 switch (type) {
537 case CborArrayType:
538 case CborMapType: {
539 /* recursive type */
540 CborValue recursed;
541 err = cbor_value_enter_container(it, &recursed);
542 if (!err)
543 err = validate_container(&recursed, type, flags, recursionLeft - 1);
544 if (err) {
545 it->offset = recursed.offset;
546 return err;
547 }
548 err = cbor_value_leave_container(it, &recursed);
549 if (err)
550 return err;
551 return CborNoError;
552 }
553
554 case CborIntegerType: {
555 uint64_t val;
556 err = cbor_value_get_raw_integer(it, &val);
557 cbor_assert(err == CborNoError); /* can't fail */
558
559 break;
560 }
561
562 case CborByteStringType:
563 case CborTextStringType: {
564 size_t n = 0;
565 const void *ptr;
566
567 err = _cbor_value_prepare_string_iteration(it);
568 if (err)
569 return err;
570
571 while (1) {
572 err = validate_number(it, type, flags);
573 if (err)
574 return err;
575
576 err = _cbor_value_get_string_chunk(it, &ptr, &n, it);
577 if (err)
578 return err;
579 if (!ptr)
580 break;
581
582 if (type == CborTextStringType && flags & CborValidateUtf8) {
583 err = validate_utf8_string(ptr, n);
584 if (err)
585 return err;
586 }
587 }
588
589 return CborNoError;
590 }
591
592 case CborTagType: {
593 CborTag tag;
594 err = cbor_value_get_tag(it, &tag);
595 cbor_assert(err == CborNoError); /* can't fail */
596
597 err = cbor_value_advance_fixed(it);
598 if (err)
599 return err;
600 err = validate_tag(it, tag, flags, recursionLeft - 1);
601 if (err)
602 return err;
603
604 return CborNoError;
605 }
606
607 case CborSimpleType: {
608 uint8_t simple_type;
609 err = cbor_value_get_simple_type(it, &simple_type);
610 cbor_assert(err == CborNoError); /* can't fail */
611 err = validate_simple_type(simple_type, flags);
612 if (err)
613 return err;
614 break;
615 }
616
617 case CborNullType:
618 case CborBooleanType:
619 break;
620
621 case CborUndefinedType:
622 if (flags & CborValidateNoUndefined)
623 return CborErrorExcludedType;
624 break;
625
626 case CborHalfFloatType:
627 case CborFloatType:
628 case CborDoubleType: {
629 #ifdef CBOR_NO_FLOATING_POINT
630 return CborErrorUnsupportedType;
631 #else
632 err = validate_floating_point(it, type, flags);
633 if (err)
634 return err;
635 break;
636 }
637 #endif /* !CBOR_NO_FLOATING_POINT */
638
639 case CborInvalidType:
640 return CborErrorUnknownType;
641 }
642
643 err = cbor_value_advance_fixed(it);
644 return err;
645 }
646
647 /**
648 * Performs a full validation controlled by the \a flags options of the CBOR
649 * stream pointed by \a it and returns the error it found. If no error was
650 * found, it returns CborNoError and the application can iterate over the items
651 * with certainty that no other errors will appear during parsing.
652 *
653 * If \a flags is CborValidateBasic, the result should be the same as
654 * cbor_value_validate_basic().
655 *
656 * This function has the same timing and memory requirements as
657 * cbor_value_advance() and cbor_value_validate_basic().
658 *
659 * \sa CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance()
660 */
661 CborError cbor_value_validate(const CborValue *it, int flags)
662 {
663 CborValue value = *it;
664 CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS);
665 if (err)
666 return err;
667 if (flags & CborValidateCompleteData && it->offset != it->parser->end)
668 return CborErrorGarbageAtEnd;
669 return CborNoError;
670 }
671
672 /**
673 * @}
674 */
675