renamed 'hf mfdes readdata, writedata' to 'read/write'
[RRG-proxmark3.git] / client / deps / tinycbor / cborvalidation.c
blobfc571695a2398ce3a5eef322fe9a0b606d3ef3c1
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:
12 ** The above copyright notice and this permission notice shall be included in
13 ** all copies or substantial portions of the Software.
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.
23 ****************************************************************************/
25 #define _BSD_SOURCE 1
26 #define _DEFAULT_SOURCE 1
27 #ifndef __STDC_LIMIT_MACROS
28 # define __STDC_LIMIT_MACROS 1
29 #endif
31 #include "cbor.h"
32 #include "cborinternal_p.h"
33 #include "compilersupport_p.h"
34 #include "utf8_p.h"
36 #include <string.h>
38 #ifndef CBOR_NO_FLOATING_POINT
39 # include <float.h>
40 # include <math.h>
41 #endif
44 #ifndef CBOR_PARSER_MAX_RECURSIONS
45 # define CBOR_PARSER_MAX_RECURSIONS 1024
46 #endif
48 /**
49 * \addtogroup CborParsing
50 * @{
53 /**
54 * \enum CborValidationFlags
55 * The CborValidationFlags enum contains flags that control the validation of a
56 * CBOR stream.
58 * \value CborValidateBasic Validates only the syntactic correctedness of the stream.
59 * \value CborValidateCanonical Validates that the stream is in canonical format, according to
60 * RFC 7049 section 3.9.
61 * \value CborValidateStrictMode Performs strict validation, according to RFC 7049 section 3.10.
62 * \value CborValidateStrictest Attempt to perform the strictest validation we know of.
64 * \value CborValidateShortestIntegrals (Canonical) Validate that integral numbers and lengths are
65 * enconded in their shortest form possible.
66 * \value CborValidateShortestFloatingPoint (Canonical) Validate that floating-point numbers are encoded
67 * in their shortest form possible.
68 * \value CborValidateShortestNumbers (Canonical) Validate both integral and floating-point numbers
69 * are in their shortest form possible.
70 * \value CborValidateNoIndeterminateLength (Canonical) Validate that no string, array or map uses
71 * indeterminate length encoding.
72 * \value CborValidateMapIsSorted (Canonical & Strict mode) Validate that map keys appear in
73 * sorted order.
74 * \value CborValidateMapKeysAreUnique (Strict mode) Validate that map keys are unique.
75 * \value CborValidateTagUse (Strict mode) Validate that known tags are used with the
76 * correct types. This does not validate that the content of
77 * those types is syntactically correct. For example, this
78 * option validates that tag 1 (DateTimeString) is used with
79 * a Text String, but it does not validate that the string is
80 * a valid date/time representation.
81 * \value CborValidateUtf8 (Strict mode) Validate that text strings are appropriately
82 * encoded in UTF-8.
83 * \value CborValidateMapKeysAreString Validate that all map keys are text strings.
84 * \value CborValidateNoUndefined Validate that no elements of type "undefined" are present.
85 * \value CborValidateNoTags Validate that no tags are used.
86 * \value CborValidateFiniteFloatingPoint Validate that all floating point numbers are finite (no NaN or
87 * infinities are allowed).
88 * \value CborValidateCompleteData Validate that the stream is complete and there is no more data
89 * in the buffer.
90 * \value CborValidateNoUnknownSimpleTypesSA Validate that all Standards Action simple types are registered
91 * with IANA.
92 * \value CborValidateNoUnknownSimpleTypes Validate that all simple types used are registered with IANA.
93 * \value CborValidateNoUnknownTagsSA Validate that all Standard Actions tags are registered with IANA.
94 * \value CborValidateNoUnknownTagsSR Validate that all Standard Actions and Specification Required tags
95 * are registered with IANA (see below for limitations).
96 * \value CborValidateNoUnkonwnTags Validate that all tags are registered with IANA
97 * (see below for limitations).
99 * \par Simple type registry
100 * The CBOR specification requires that registration for use of the first 19
101 * simple types must be done by way of Standards Action. The rest of the simple
102 * types only require a specification. The official list can be obtained from
103 * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml.
105 * \par
106 * There are no registered simple types recognized by this release of TinyCBOR
107 * (beyond those defined by RFC 7049).
109 * \par Tag registry
110 * The CBOR specification requires that registration for use of the first 23
111 * tags must be done by way of Standards Action. The next up to tag 255 only
112 * require a specification. Finally, all other tags can be registered on a
113 * first-come-first-serve basis. The official list can be ontained from
114 * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml.
116 * \par
117 * Given the variability of this list, TinyCBOR cannot recognize all tags
118 * registered with IANA. Instead, the implementation only recognizes tags
119 * that are backed by an RFC.
121 * \par
122 * These are the tags known to the current TinyCBOR release:
123 <table>
124 <tr>
125 <th>Tag</th>
126 <th>Data Item</th>
127 <th>Semantics</th>
128 </tr>
129 <tr>
130 <td>0</td>
131 <td>UTF-8 text string</td>
132 <td>Standard date/time string</td>
133 </td>
134 <tr>
135 <td>1</td>
136 <td>integer</td>
137 <td>Epoch-based date/time</td>
138 </td>
139 <tr>
140 <td>2</td>
141 <td>byte string</td>
142 <td>Positive bignum</td>
143 </td>
144 <tr>
145 <td>3</td>
146 <td>byte string</td>
147 <td>Negative bignum</td>
148 </td>
149 <tr>
150 <td>4</td>
151 <td>array</td>
152 <td>Decimal fraction</td>
153 </td>
154 <tr>
155 <td>5</td>
156 <td>array</td>
157 <td>Bigfloat</td>
158 </td>
159 <tr>
160 <td>16</td>
161 <td>array</td>
162 <td>COSE Single Recipient Encrypted Data Object (RFC 8152)</td>
163 </td>
164 <tr>
165 <td>17</td>
166 <td>array</td>
167 <td>COSE Mac w/o Recipients Object (RFC 8152)</td>
168 </td>
169 <tr>
170 <td>18</td>
171 <td>array</td>
172 <td>COSE Single Signer Data Object (RFC 8162)</td>
173 </td>
174 <tr>
175 <td>21</td>
176 <td>byte string, array, map</td>
177 <td>Expected conversion to base64url encoding</td>
178 </td>
179 <tr>
180 <td>22</td>
181 <td>byte string, array, map</td>
182 <td>Expected conversion to base64 encoding</td>
183 </td>
184 <tr>
185 <td>23</td>
186 <td>byte string, array, map</td>
187 <td>Expected conversion to base16 encoding</td>
188 </td>
189 <tr>
190 <td>24</td>
191 <td>byte string</td>
192 <td>Encoded CBOR data item</td>
193 </td>
194 <tr>
195 <td>32</td>
196 <td>UTF-8 text string</td>
197 <td>URI</td>
198 </td>
199 <tr>
200 <td>33</td>
201 <td>UTF-8 text string</td>
202 <td>base64url</td>
203 </td>
204 <tr>
205 <td>34</td>
206 <td>UTF-8 text string</td>
207 <td>base64</td>
208 </td>
209 <tr>
210 <td>35</td>
211 <td>UTF-8 text string</td>
212 <td>Regular expression</td>
213 </td>
214 <tr>
215 <td>36</td>
216 <td>UTF-8 text string</td>
217 <td>MIME message</td>
218 </td>
219 <tr>
220 <td>96</td>
221 <td>array</td>
222 <td>COSE Encrypted Data Object (RFC 8152)</td>
223 </td>
224 <tr>
225 <td>97</td>
226 <td>array</td>
227 <td>COSE MACed Data Object (RFC 8152)</td>
228 </td>
229 <tr>
230 <td>98</td>
231 <td>array</td>
232 <td>COSE Signed Data Object (RFC 8152)</td>
233 </td>
234 <tr>
235 <td>55799</td>
236 <td>any</td>
237 <td>Self-describe CBOR</td>
238 </td>
239 </table>
242 struct KnownTagData { uint32_t tag; uint32_t types; };
243 static const struct KnownTagData knownTagData[] = {
244 { 0, (uint32_t)CborTextStringType },
245 { 1, (uint32_t)(CborIntegerType + 1) },
246 { 2, (uint32_t)CborByteStringType },
247 { 3, (uint32_t)CborByteStringType },
248 { 4, (uint32_t)CborArrayType },
249 { 5, (uint32_t)CborArrayType },
250 { 16, (uint32_t)CborArrayType },
251 { 17, (uint32_t)CborArrayType },
252 { 18, (uint32_t)CborArrayType },
253 { 21, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) },
254 { 22, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) },
255 { 23, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) },
256 { 24, (uint32_t)CborByteStringType },
257 { 32, (uint32_t)CborTextStringType },
258 { 33, (uint32_t)CborTextStringType },
259 { 34, (uint32_t)CborTextStringType },
260 { 35, (uint32_t)CborTextStringType },
261 { 36, (uint32_t)CborTextStringType },
262 { 96, (uint32_t)CborArrayType },
263 { 97, (uint32_t)CborArrayType },
264 { 98, (uint32_t)CborArrayType },
265 { 55799, 0U }
268 static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft);
270 static inline CborError validate_utf8_string(const void *ptr, size_t n) {
271 const uint8_t *buffer = (const uint8_t *)ptr;
272 const uint8_t *const end = buffer + n;
273 while (buffer < end) {
274 uint32_t uc = get_utf8(&buffer, end);
275 if (uc == ~0U)
276 return CborErrorInvalidUtf8TextString;
278 return CborNoError;
281 static inline CborError validate_simple_type(uint8_t simple_type, uint32_t flags) {
282 /* At current time, all known simple types are those from RFC 7049,
283 * which are parsed by the parser into different CBOR types.
284 * That means that if we've got here, the type is unknown */
285 if (simple_type < 32)
286 return (flags & CborValidateNoUnknownSimpleTypesSA) ? CborErrorUnknownSimpleType : CborNoError;
287 return (flags & CborValidateNoUnknownSimpleTypes) == CborValidateNoUnknownSimpleTypes ?
288 CborErrorUnknownSimpleType : CborNoError;
291 static inline CborError validate_number(const CborValue *it, CborType type, uint32_t flags) {
292 CborError err = CborNoError;
293 const uint8_t *ptr = it->ptr;
294 size_t bytesUsed, bytesNeeded;
295 uint64_t value;
297 if ((flags & CborValidateShortestIntegrals) == 0)
298 return err;
299 if (type >= CborHalfFloatType && type <= CborDoubleType)
300 return err; /* checked elsewhere */
302 err = _cbor_value_extract_number(&ptr, it->parser->end, &value);
303 if (err)
304 return err;
306 bytesUsed = (size_t)(ptr - it->ptr - 1);
307 bytesNeeded = 0;
308 if (value >= Value8Bit)
309 ++bytesNeeded;
310 if (value > 0xffU)
311 ++bytesNeeded;
312 if (value > 0xffffU)
313 bytesNeeded += 2;
314 if (value > 0xffffffffU)
315 bytesNeeded += 4;
316 if (bytesNeeded < bytesUsed)
317 return CborErrorOverlongEncoding;
318 return CborNoError;
321 static inline CborError validate_tag(CborValue *it, CborTag tag, uint32_t flags, int recursionLeft) {
322 CborType type = cbor_value_get_type(it);
323 const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
324 const struct KnownTagData *tagData = knownTagData;
325 const struct KnownTagData *const knownTagDataEnd = knownTagData + knownTagCount;
327 if (!recursionLeft)
328 return CborErrorNestingTooDeep;
329 if (flags & CborValidateNoTags)
330 return CborErrorExcludedType;
332 /* find the tag data, if any */
333 for (; tagData != knownTagDataEnd; ++tagData) {
334 if (tagData->tag < tag)
335 continue;
336 if (tagData->tag > tag)
337 tagData = NULL;
338 break;
340 if (tagData == knownTagDataEnd)
341 tagData = NULL;
343 if (flags & CborValidateNoUnknownTags && !tagData) {
344 /* tag not found */
345 if (flags & CborValidateNoUnknownTagsSA && tag < 24)
346 return CborErrorUnknownTag;
347 if ((flags & CborValidateNoUnknownTagsSR) == CborValidateNoUnknownTagsSR && tag < 256)
348 return CborErrorUnknownTag;
349 if ((flags & CborValidateNoUnknownTags) == CborValidateNoUnknownTags)
350 return CborErrorUnknownTag;
353 if (flags & CborValidateTagUse && tagData && tagData->types) {
354 uint32_t allowedTypes = tagData->types;
356 /* correct Integer so it's not zero */
357 if (type == CborIntegerType)
358 type = (CborType)(type + 1);
360 while (allowedTypes) {
361 if ((uint8_t)(allowedTypes & 0xff) == type)
362 break;
363 allowedTypes >>= 8;
365 if (!allowedTypes)
366 return CborErrorInappropriateTagForType;
369 return validate_value(it, flags, recursionLeft);
372 #ifndef CBOR_NO_FLOATING_POINT
373 static inline CborError validate_floating_point(CborValue *it, CborType type, uint32_t flags) {
374 CborError err;
375 int r;
376 double val;
377 float valf;
378 uint16_t valf16;
380 if (type != CborDoubleType) {
381 if (type == CborFloatType) {
382 err = cbor_value_get_float(it, &valf);
383 val = valf;
384 } else {
385 # ifdef CBOR_NO_HALF_FLOAT_TYPE
386 (void)valf16;
387 return CborErrorUnsupportedType;
388 # else
389 err = cbor_value_get_half_float(it, &valf16);
390 val = decode_half(valf16);
391 # endif
393 } else {
394 err = cbor_value_get_double(it, &val);
396 cbor_assert(err == CborNoError); /* can't fail */
398 r = fpclassify(val);
399 if (r == FP_NAN || r == FP_INFINITE) {
400 if (flags & CborValidateFiniteFloatingPoint)
401 return CborErrorExcludedValue;
402 if (flags & CborValidateShortestFloatingPoint) {
403 if (type == CborDoubleType)
404 return CborErrorOverlongEncoding;
405 # ifndef CBOR_NO_HALF_FLOAT_TYPE
406 if (type == CborFloatType)
407 return CborErrorOverlongEncoding;
408 if (r == FP_NAN && valf16 != 0x7e00)
409 return CborErrorImproperValue;
410 if (r == FP_INFINITE && valf16 != 0x7c00 && valf16 != 0xfc00)
411 return CborErrorImproperValue;
412 # endif
416 if (flags & CborValidateShortestFloatingPoint && type > CborHalfFloatType) {
417 if (type == CborDoubleType) {
418 valf = (float)val;
419 if ((double)valf == val)
420 return CborErrorOverlongEncoding;
422 # ifndef CBOR_NO_HALF_FLOAT_TYPE
423 if (type == CborFloatType) {
424 valf16 = encode_half(valf);
425 if (valf == decode_half(valf16))
426 return CborErrorOverlongEncoding;
428 # endif
431 return CborNoError;
433 #endif
435 static CborError validate_container(CborValue *it, int containerType, uint32_t flags, int recursionLeft) {
436 CborError err;
437 const uint8_t *previous = NULL;
438 const uint8_t *previous_end = NULL;
440 if (!recursionLeft)
441 return CborErrorNestingTooDeep;
443 while (!cbor_value_at_end(it)) {
444 const uint8_t *current = cbor_value_get_next_byte(it);
446 if (containerType == CborMapType) {
447 if (flags & CborValidateMapKeysAreString) {
448 CborType type = cbor_value_get_type(it);
449 if (type == CborTagType) {
450 /* skip the tags */
451 CborValue copy = *it;
452 err = cbor_value_skip_tag(&copy);
453 if (err)
454 return err;
455 type = cbor_value_get_type(&copy);
457 if (type != CborTextStringType)
458 return CborErrorMapKeyNotString;
462 err = validate_value(it, flags, recursionLeft);
463 if (err)
464 return err;
466 if (containerType != CborMapType)
467 continue;
469 if (flags & CborValidateMapIsSorted) {
470 if (previous) {
471 uint64_t len1, len2;
472 const uint8_t *ptr;
474 /* extract the two lengths */
475 ptr = previous;
476 _cbor_value_extract_number(&ptr, it->parser->end, &len1);
477 ptr = current;
478 _cbor_value_extract_number(&ptr, it->parser->end, &len2);
480 if (len1 > len2)
481 return CborErrorMapNotSorted;
482 if (len1 == len2) {
483 size_t bytelen1 = (size_t)(previous_end - previous);
484 size_t bytelen2 = (size_t)(it->ptr - current);
485 int r = memcmp(previous, current, bytelen1 <= bytelen2 ? bytelen1 : bytelen2);
487 if (r == 0 && bytelen1 != bytelen2)
488 r = bytelen1 < bytelen2 ? -1 : +1;
489 if (r > 0)
490 return CborErrorMapNotSorted;
491 if (r == 0 && (flags & CborValidateMapKeysAreUnique) == CborValidateMapKeysAreUnique)
492 return CborErrorMapKeysNotUnique;
496 previous = current;
497 previous_end = it->ptr;
500 /* map: that was the key, so get the value */
501 err = validate_value(it, flags, recursionLeft);
502 if (err)
503 return err;
505 return CborNoError;
508 static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft) {
509 CborError err;
510 CborType type = cbor_value_get_type(it);
512 if (cbor_value_is_length_known(it)) {
513 err = validate_number(it, type, flags);
514 if (err)
515 return err;
516 } else {
517 if (flags & CborValidateNoIndeterminateLength)
518 return CborErrorUnknownLength;
521 switch (type) {
522 case CborArrayType:
523 case CborMapType: {
524 /* recursive type */
525 CborValue recursed;
526 err = cbor_value_enter_container(it, &recursed);
527 if (!err)
528 err = validate_container(&recursed, type, flags, recursionLeft - 1);
529 if (err) {
530 it->ptr = recursed.ptr;
531 return err;
533 err = cbor_value_leave_container(it, &recursed);
534 if (err)
535 return err;
536 return CborNoError;
539 case CborIntegerType: {
540 uint64_t val;
541 err = cbor_value_get_raw_integer(it, &val);
542 cbor_assert(err == CborNoError); /* can't fail */
544 break;
547 case CborByteStringType:
548 case CborTextStringType: {
549 size_t n = 0;
550 const void *ptr;
552 err = _cbor_value_prepare_string_iteration(it);
553 if (err)
554 return err;
556 while (1) {
557 err = validate_number(it, type, flags);
558 if (err)
559 return err;
561 err = _cbor_value_get_string_chunk(it, &ptr, &n, it);
562 if (err)
563 return err;
564 if (!ptr)
565 break;
567 if (type == CborTextStringType && flags & CborValidateUtf8) {
568 err = validate_utf8_string(ptr, n);
569 if (err)
570 return err;
574 return CborNoError;
577 case CborTagType: {
578 CborTag tag;
579 err = cbor_value_get_tag(it, &tag);
580 cbor_assert(err == CborNoError); /* can't fail */
582 err = cbor_value_advance_fixed(it);
583 if (err)
584 return err;
585 err = validate_tag(it, tag, flags, recursionLeft - 1);
586 if (err)
587 return err;
589 return CborNoError;
592 case CborSimpleType: {
593 uint8_t simple_type;
594 err = cbor_value_get_simple_type(it, &simple_type);
595 cbor_assert(err == CborNoError); /* can't fail */
596 err = validate_simple_type(simple_type, flags);
597 if (err)
598 return err;
599 break;
602 case CborNullType:
603 case CborBooleanType:
604 break;
606 case CborUndefinedType:
607 if (flags & CborValidateNoUndefined)
608 return CborErrorExcludedType;
609 break;
611 case CborHalfFloatType:
612 case CborFloatType:
613 case CborDoubleType: {
614 #ifdef CBOR_NO_FLOATING_POINT
615 return CborErrorUnsupportedType;
616 #else
617 err = validate_floating_point(it, type, flags);
618 if (err)
619 return err;
620 break;
621 #endif /* !CBOR_NO_FLOATING_POINT */
624 case CborInvalidType:
625 return CborErrorUnknownType;
628 err = cbor_value_advance_fixed(it);
629 return err;
633 * Performs a full validation, controlled by the \a flags options, of the CBOR
634 * stream pointed by \a it and returns the error it found. If no error was
635 * found, it returns CborNoError and the application can iterate over the items
636 * with certainty that no errors will appear during parsing.
638 * If \a flags is CborValidateBasic, the result should be the same as
639 * cbor_value_validate_basic().
641 * This function has the same timing and memory requirements as
642 * cbor_value_advance() and cbor_value_validate_basic().
644 * \sa CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance()
646 CborError cbor_value_validate(const CborValue *it, uint32_t flags) {
647 CborValue value = *it;
648 CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS);
649 if (err)
650 return err;
651 if (flags & CborValidateCompleteData && it->ptr != it->parser->end)
652 return CborErrorGarbageAtEnd;
653 return CborNoError;
657 * @}