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(&copy);
459                     if (err)
460                         return err;
461                     type = cbor_value_get_type(&copy);
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