1 // SPDX-License-Identifier: BSD-3-Clause
2 /*==============================================================================
3 Copyright (c) 2016-2018, The Linux Foundation.
4 Copyright (c) 2018-2024, Laurence Lundblade.
5 Copyright (c) 2021, Arm Limited.
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11 * Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following
15 disclaimer in the documentation and/or other materials provided
16 with the distribution.
17 * Neither the name of The Linux Foundation nor the names of its
18 contributors, nor the name "Laurence Lundblade" may be used to
19 endorse or promote products derived from this software without
20 specific prior written permission.
21
22 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
23 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
25 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
26 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 =============================================================================*/
34
35
36 #include "qcbor/qcbor_encode.h"
37 #include "ieee754.h"
38
39
40 /**
41 * @file qcbor_encode.c
42 *
43 * The entire implementation of the QCBOR encoder.
44 */
45
46
47 /*
48 * == Nesting Tracking ==
49 *
50 * The following functions and data type QCBORTrackNesting implement
51 * the nesting management for encoding.
52 *
53 * CBOR's two nesting types, arrays and maps, are tracked here. There
54 * is a limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and
55 * maps that can be nested in one encoding so the encoding context
56 * stays small enough to fit on the stack.
57 *
58 * When an array/map is opened, pCurrentNesting points to the element
59 * in pArrays that records the type, start position and accumulates a
60 * count of the number of items added. When closed the start position
61 * is used to go back and fill in the type and number of items in the
62 * array/map.
63 *
64 * Encoded output can be a CBOR Sequence (RFC 8742) in which case
65 * there is no top-level array or map. It starts out with a string,
66 * integer or other non-aggregate type. It may have an array or map
67 * other than at the start, in which case that nesting is tracked
68 * here.
69 *
70 * QCBOR has a special feature to allow constructing byte string
71 * wrapped CBOR directly into the output buffer, so no extra buffer is
72 * needed for byte string wrapping. This is implemented as nesting
73 * with the type CBOR_MAJOR_TYPE_BYTE_STRING and is tracked here. Byte
74 * string wrapped CBOR is used by COSE for data that is to be hashed.
75 */
76 static void
Nesting_Init(QCBORTrackNesting * pNesting)77 Nesting_Init(QCBORTrackNesting *pNesting)
78 {
79 /* Assumes pNesting has been zeroed. */
80 pNesting->pCurrentNesting = &pNesting->pArrays[0];
81 /* Implied CBOR array at the top nesting level. This is never
82 * returned, but makes the item count work correctly.
83 */
84 pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY;
85 }
86
87 static uint8_t
Nesting_Increase(QCBORTrackNesting * pNesting,const uint8_t uMajorType,const uint32_t uPos)88 Nesting_Increase(QCBORTrackNesting *pNesting,
89 const uint8_t uMajorType,
90 const uint32_t uPos)
91 {
92 if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) {
93 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
94 } else {
95 pNesting->pCurrentNesting++;
96 pNesting->pCurrentNesting->uCount = 0;
97 pNesting->pCurrentNesting->uStart = uPos;
98 pNesting->pCurrentNesting->uMajorType = uMajorType;
99 return QCBOR_SUCCESS;
100 }
101 }
102
103 static void
Nesting_Decrease(QCBORTrackNesting * pNesting)104 Nesting_Decrease(QCBORTrackNesting *pNesting)
105 {
106 if(pNesting->pCurrentNesting > &pNesting->pArrays[0]) {
107 pNesting->pCurrentNesting--;
108 }
109 }
110
111 static uint8_t
Nesting_Increment(QCBORTrackNesting * pNesting)112 Nesting_Increment(QCBORTrackNesting *pNesting)
113 {
114 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
115 if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
116 return QCBOR_ERR_ARRAY_TOO_LONG;
117 }
118 #endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
119
120 pNesting->pCurrentNesting->uCount++;
121
122 return QCBOR_SUCCESS;
123 }
124
125 static void
Nesting_Decrement(QCBORTrackNesting * pNesting)126 Nesting_Decrement(QCBORTrackNesting *pNesting)
127 {
128 /* No error check for going below 0 here needed because this
129 * is only used by QCBOREncode_CancelBstrWrap() and it checks
130 * the nesting level before calling this. */
131 pNesting->pCurrentNesting->uCount--;
132 }
133
134 static uint16_t
Nesting_GetCount(QCBORTrackNesting * pNesting)135 Nesting_GetCount(QCBORTrackNesting *pNesting)
136 {
137 /* The nesting count recorded is always the actual number of
138 * individual data items in the array or map. For arrays CBOR uses
139 * the actual item count. For maps, CBOR uses the number of pairs.
140 * This function returns the number needed for the CBOR encoding,
141 * so it divides the number of items by two for maps to get the
142 * number of pairs.
143 */
144 if(pNesting->pCurrentNesting->uMajorType == CBOR_MAJOR_TYPE_MAP) {
145 /* Cast back to uint16_t after integer promotion from bit shift */
146 return (uint16_t)(pNesting->pCurrentNesting->uCount >> 1);
147 } else {
148 return pNesting->pCurrentNesting->uCount;
149 }
150 }
151
152 static uint32_t
Nesting_GetStartPos(QCBORTrackNesting * pNesting)153 Nesting_GetStartPos(QCBORTrackNesting *pNesting)
154 {
155 return pNesting->pCurrentNesting->uStart;
156 }
157
158 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
159 static uint8_t
Nesting_GetMajorType(QCBORTrackNesting * pNesting)160 Nesting_GetMajorType(QCBORTrackNesting *pNesting)
161 {
162 return pNesting->pCurrentNesting->uMajorType;
163 }
164
165 static bool
Nesting_IsInNest(QCBORTrackNesting * pNesting)166 Nesting_IsInNest(QCBORTrackNesting *pNesting)
167 {
168 return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? false : true;
169 }
170 #endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
171
172
173
174
175 /*
176 * == Major CBOR Types ==
177 *
178 * Encoding of the major CBOR types is by these functions:
179 *
180 * CBOR Major Type Public Function
181 * 0 QCBOREncode_AddUInt64()
182 * 0, 1 QCBOREncode_AddUInt64(), QCBOREncode_AddInt64()
183 * 2, 3 QCBOREncode_AddBuffer()
184 * 4, 5 QCBOREncode_OpenMapOrArray(), QCBOREncode_CloseMapOrArray(),
185 * QCBOREncode_OpenMapOrArrayIndefiniteLength(),
186 * QCBOREncode_CloseMapOrArrayIndefiniteLength()
187 * 6 QCBOREncode_AddTag()
188 * 7 QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
189 * QCBOREncode_AddDoubleNoPreferred(),
190 * QCBOREncode_AddFloatNoPreferred(), QCBOREncode_AddType7()
191 *
192 * Additionally, encoding of decimal fractions and bigfloats is by
193 * QCBOREncode_AddExponentAndMantissa() and byte strings that wrap
194 * encoded CBOR are handled by QCBOREncode_OpenMapOrArray() and
195 * QCBOREncode_CloseBstrWrap2().
196 *
197 *
198 * == Error Tracking Plan ==
199 *
200 * Errors are tracked internally and not returned until
201 * QCBOREncode_Finish() or QCBOREncode_GetErrorState() is called. The
202 * CBOR errors are in me->uError. UsefulOutBuf also tracks whether
203 * the buffer is full or not in its context. Once either of these
204 * errors is set they are never cleared. Only QCBOREncode_Init()
205 * resets them. Or said another way, they must never be cleared or
206 * we'll tell the caller all is good when it is not.
207 *
208 * Only one error code is reported by QCBOREncode_Finish() even if
209 * there are multiple errors. The last one set wins. The caller might
210 * have to fix one error to reveal the next one they have to fix.
211 * This is OK.
212 *
213 * The buffer full error tracked by UsefulBuf is only pulled out of
214 * UsefulBuf in QCBOREncode_Finish() so it is the one that usually
215 * wins. UsefulBuf will never go off the end of the buffer even if it
216 * is called again and again when full.
217 *
218 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS disables about half of the error
219 * checks here to reduce code size by about 150 bytes leaving only the
220 * checks for size to avoid buffer overflow. If the calling code is
221 * completely correct, checks are completely unnecessary. For
222 * example, there is no need to check that all the opens are matched
223 * by a close.
224 *
225 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS also disables the check for more
226 * than QCBOR_MAX_ITEMS_IN_ARRAY in an array. Since
227 * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,535) it is very unlikely
228 * to be reached. If it is reached, the count will wrap around to zero
229 * and CBOR that is not well formed will be produced, but there will
230 * be no buffers overrun and new security issues in the code.
231 *
232 * The 8 errors returned here fall into three categories:
233 *
234 * Sizes
235 * QCBOR_ERR_BUFFER_TOO_LARGE -- Encoded output exceeded UINT32_MAX
236 * QCBOR_ERR_BUFFER_TOO_SMALL -- Output buffer too small
237 * QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Nesting > QCBOR_MAX_ARRAY_NESTING1
238 * QCBOR_ERR_ARRAY_TOO_LONG -- Too many items added to an array/map [1]
239 *
240 * Nesting constructed incorrectly
241 * QCBOR_ERR_TOO_MANY_CLOSES -- More close calls than opens [1]
242 * QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open [1]
243 * QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes [1]
244 *
245 * Would generate not-well-formed CBOR
246 * QCBOR_ERR_ENCODE_UNSUPPORTED -- Simple type between 24 and 31 [1]
247 *
248 * [1] indicated disabled by QCBOR_DISABLE_ENCODE_USAGE_GUARDS
249 */
250
251
252 /*
253 * Public function for initialization. See qcbor/qcbor_encode.h
254 */
255 void
QCBOREncode_Init(QCBOREncodeContext * pMe,UsefulBuf Storage)256 QCBOREncode_Init(QCBOREncodeContext *pMe, UsefulBuf Storage)
257 {
258 memset(pMe, 0, sizeof(QCBOREncodeContext));
259 UsefulOutBuf_Init(&(pMe->OutBuf), Storage);
260 Nesting_Init(&(pMe->nesting));
261 }
262
263
264 /*
265 * Public function to encode a CBOR head. See qcbor/qcbor_encode.h
266 */
267 UsefulBufC
QCBOREncode_EncodeHead(UsefulBuf Buffer,uint8_t uMajorType,uint8_t uMinLen,uint64_t uArgument)268 QCBOREncode_EncodeHead(UsefulBuf Buffer,
269 uint8_t uMajorType,
270 uint8_t uMinLen,
271 uint64_t uArgument)
272 {
273 /*
274 * == Description of the CBOR Head ==
275 *
276 * The head of a CBOR data item
277 * +---+-----+ +--------+ +--------+ +--------+ +--------+
278 * |M T| A R G U M E N T . . . |
279 * +---+-----+ +--------+ +--------+ +--------+ ... +--------+
280 *
281 * Every CBOR data item has a "head". It is made up of the "major
282 * type" and the "argument".
283 *
284 * The major type indicates whether the data item is an integer,
285 * string, array or such. It is encoded in 3 bits giving it a range
286 * from 0 to 7. 0 indicates the major type is a positive integer,
287 * 1 a negative integer, 2 a byte string and so on.
288 *
289 * These 3 bits are the first part of the "initial byte" in a data
290 * item. Every data item has an initial byte, and some only have
291 * the initial byte.
292 *
293 * The argument is essentially a number between 0 and UINT64_MAX
294 * (18446744073709551615). This number is interpreted to mean
295 * different things for the different major types. For major type
296 * 0, a positive integer, it is value of the data item. For major
297 * type 2, a byte string, it is the length in bytes of the byte
298 * string. For major type 4, an array, it is the number of data
299 * items in the array.
300 *
301 * Special encoding is used so that the argument values less than
302 * 24 can be encoded very compactly in the same byte as the major
303 * type is encoded. When the lower 5 bits of the initial byte have
304 * a value less than 24, then that is the value of the argument.
305 *
306 * If the lower 5 bits of the initial byte are less than 24, then
307 * they are the value of the argument. This allows integer values 0
308 * - 23 to be CBOR encoded in just one byte.
309 *
310 * When the value of lower 5 bits are 24, 25, 26, or 27 the
311 * argument is encoded in 1, 2, 4 or 8 bytes following the initial
312 * byte in network byte order (bit endian). The cases when it is
313 * 28, 29 and 30 are reserved for future use. The value 31 is a
314 * special indicator for indefinite length strings, arrays and
315 * maps.
316 *
317 * The lower 5 bits are called the "additional information."
318 *
319 * Thus the CBOR head may be 1, 2, 3, 5 or 9 bytes long.
320 *
321 * It is legal in CBOR to encode the argument using any of these
322 * lengths even if it could be encoded in a shorter length. For
323 * example it is legal to encode a data item representing the
324 * positive integer 0 in 9 bytes even though it could be encoded in
325 * only 0. This is legal to allow for for very simple code or even
326 * hardware-only implementations that just output a register
327 * directly.
328 *
329 * CBOR defines preferred encoding as the encoding of the argument
330 * in the smallest number of bytes needed to encode it.
331 *
332 * This function takes the major type and argument as inputs and
333 * outputs the encoded CBOR head for them. It does conversion to
334 * network byte order. It implements CBOR preferred encoding,
335 * outputting the shortest representation of the argument.
336 *
337 * == Endian Conversion ==
338 *
339 * This code does endian conversion without hton() or knowing the
340 * endianness of the machine by using masks and shifts. This avoids
341 * the dependency on hton() and the mess of figuring out how to
342 * find the machine's endianness.
343 *
344 * This is a good efficient implementation on little-endian
345 * machines. A faster and smaller implementation is possible on
346 * big-endian machines because CBOR/network byte order is
347 * big-endian. However big-endian machines are uncommon.
348 *
349 * On x86, this is about 150 bytes instead of 500 bytes for the
350 * original, more formal unoptimized code.
351 *
352 * This also does the CBOR preferred shortest encoding for integers
353 * and is called to do endian conversion for floats.
354 *
355 * It works backwards from the least significant byte to the most
356 * significant byte.
357 *
358 * == Floating Point ==
359 *
360 * When the major type is 7 and the 5 lower bits have the values
361 * 25, 26 or 27, the argument is a floating-point number that is
362 * half, single or double-precision. Note that it is not the
363 * conversion from a floating-point value to an integer value like
364 * converting 0x00 to 0.00, it is the interpretation of the bits in
365 * the argument as an IEEE 754 float-point number.
366 *
367 * Floating-point numbers must be converted to network byte
368 * order. That is accomplished here by exactly the same code that
369 * converts integer arguments to network byte order.
370 *
371 * There is preferred encoding for floating-point numbers in CBOR,
372 * but it is very different than for integers and it is not
373 * implemented here. Half-precision is preferred to
374 * single-precision which is preferred to double-precision only if
375 * the conversion can be performed without loss of precision. Zero
376 * and infinity can always be converted to half-precision, without
377 * loss but 3.141592653589 cannot.
378 *
379 * The way this function knows to not do preferred encoding on the
380 * argument passed here when it is a floating point number is the
381 * uMinLen parameter. It should be 2, 4 or 8 for half, single and
382 * double precision floating point values. This prevents and the
383 * incorrect removal of leading zeros when encoding arguments that
384 * are floating-point numbers.
385 *
386 * == Use of Type int and Static Analyzers ==
387 *
388 * The type int is used here for several variables because of the
389 * way integer promotion works in C for variables that are uint8_t
390 * or uint16_t. The basic rule is that they will always be promoted
391 * to int if they will fit. These integer variables here need only
392 * hold values less than 255 so they will always fit into an int.
393 *
394 * Most of values stored are never negative, so one might think
395 * that unsigned int would be more correct than int. However the C
396 * integer promotion rules only promote to unsigned int if the
397 * result won't fit into an int even if the promotion is for an
398 * unsigned variable like uint8_t.
399 *
400 * By declaring these int, there are few implicit conversions and
401 * fewer casts needed. Code size is reduced a little. It makes
402 * static analyzers happier.
403 *
404 * Note also that declaring these uint8_t won't stop integer wrap
405 * around if the code is wrong. It won't make the code more
406 * correct.
407 *
408 * https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
409 * https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
410 *
411 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
412 */
413
414 /* The buffer must have room for the largest CBOR HEAD + one
415 * extra. The one extra is needed for this code to work as it does
416 * a pre-decrement.
417 */
418 if(Buffer.len < QCBOR_HEAD_BUFFER_SIZE) {
419 return NULLUsefulBufC;
420 }
421
422 /* Pointer to last valid byte in the buffer */
423 uint8_t * const pBufferEnd = &((uint8_t *)Buffer.ptr)[QCBOR_HEAD_BUFFER_SIZE-1];
424
425 /* Point to the last byte and work backwards */
426 uint8_t *pByte = pBufferEnd;
427 /* The 5 bits in the initial byte that are not the major type */
428 int nAdditionalInfo;
429
430 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
431 if(uMajorType > QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
432 /* Special case for start & end of indefinite length */
433 uMajorType = uMajorType - QCBOR_INDEFINITE_LEN_TYPE_MODIFIER;
434 /* This takes advantage of design of CBOR where additional info
435 * is 31 for both opening and closing indefinite length
436 * maps and arrays.
437 */
438 #if CBOR_SIMPLE_BREAK != LEN_IS_INDEFINITE
439 #error additional info for opening array not the same as for closing
440 #endif
441 nAdditionalInfo = CBOR_SIMPLE_BREAK;
442
443 } else
444 #endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
445 if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
446 /* Simple case where argument is < 24 */
447 nAdditionalInfo = (int)uArgument;
448
449 } else {
450 /* This encodes the argument in 1,2,4 or 8 bytes. The outer loop
451 * runs once for 1 byte and 4 times for 8 bytes. The inner loop
452 * runs 1, 2 or 4 times depending on outer loop counter. This
453 * works backwards shifting 8 bits off the argument being
454 * encoded at a time until all bits from uArgument have been
455 * encoded and the minimum encoding size is reached. Minimum
456 * encoding size is for floating-point numbers that have some
457 * zero-value bytes that must be output.
458 */
459 static const uint8_t aIterate[] = {1,1,2,4};
460
461 /* uMinLen passed in is unsigned, but goes negative in the loop
462 * so it must be converted to a signed value.
463 */
464 int nMinLen = (int)uMinLen;
465 int i;
466 for(i = 0; uArgument || nMinLen > 0; i++) {
467 const int nIterations = (int)aIterate[i];
468 for(int j = 0; j < nIterations; j++) {
469 *--pByte = (uint8_t)(uArgument & 0xff);
470 uArgument = uArgument >> 8;
471 }
472 nMinLen -= nIterations;
473 }
474
475 nAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
476 }
477
478 /* This expression integer-promotes to type int. The code above in
479 * function guarantees that nAdditionalInfo will never be larger
480 * than 0x1f. The caller may pass in a too-large uMajor type. The
481 * conversion to uint8_t will cause an integer wrap around and
482 * incorrect CBOR will be generated, but no security issue will
483 * occur.
484 */
485 const int nInitialByte = (uMajorType << 5) + nAdditionalInfo;
486 *--pByte = (uint8_t)nInitialByte;
487
488 #ifdef EXTRA_ENCODE_HEAD_CHECK
489 /* This is a sanity check that can be turned on to verify the
490 * pointer math in this function is not going wrong. Turn it on and
491 * run the whole test suite to perform the check.
492 */
493 if(pBufferEnd - pByte > 9 || pBufferEnd - pByte < 1 || pByte < (uint8_t *)buffer.ptr) {
494 return NULLUsefulBufC;
495 }
496 #endif /* EXTRA_ENCODE_HEAD_CHECK */
497
498 /* Length will not go negative because the loops run for at most 8 decrements
499 * of pByte, only one other decrement is made, and the array is sized
500 * for this.
501 */
502 return (UsefulBufC){pByte, (size_t)(pBufferEnd - pByte)};
503 }
504
505
506 /**
507 * @brief Increment item counter for maps and arrays.
508 *
509 * @param pMe QCBOR encoding context.
510 *
511 * This is mostly a separate function to make code more readable and
512 * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
513 */
514 static void
QCBOREncode_Private_IncrementMapOrArrayCount(QCBOREncodeContext * pMe)515 QCBOREncode_Private_IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
516 {
517 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
518 if(pMe->uError == QCBOR_SUCCESS) {
519 pMe->uError = Nesting_Increment(&(pMe->nesting));
520 }
521 #else
522 (void)Nesting_Increment(&(pMe->nesting));
523 #endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
524 }
525
526
527 /**
528 * @brief Append the CBOR head, the major type and argument
529 *
530 * @param pMe Encoder context.
531 * @param uMajorType Major type to insert.
532 * @param uArgument The argument (an integer value or a length).
533 * @param uMinLen The minimum number of bytes for encoding the CBOR argument.
534 *
535 * This formats the CBOR "head" and appends it to the output.
536 *
537 * This also increments the array/map item counter in most cases.
538 */
539 void
QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext * pMe,const uint8_t uMajorType,const uint64_t uArgument,const uint8_t uMinLen)540 QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext *pMe,
541 const uint8_t uMajorType,
542 const uint64_t uArgument,
543 const uint8_t uMinLen)
544 {
545 /* A stack buffer large enough for a CBOR head */
546 UsefulBuf_MAKE_STACK_UB (pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
547
548 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
549 uMajorType,
550 uMinLen,
551 uArgument);
552
553 /* No check for EncodedHead == NULLUsefulBufC is performed here to
554 * save object code. It is very clear that pBufferForEncodedHead is
555 * the correct size. If EncodedHead == NULLUsefulBufC then
556 * UsefulOutBuf_AppendUsefulBuf() will do nothing so there is no
557 * security hole introduced.
558 */
559
560 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), EncodedHead);
561
562 if(!(uMajorType & QCBOR_INDEFINITE_LEN_TYPE_MODIFIER || uMajorType == CBOR_MAJOR_TYPE_TAG)) {
563 /* Don't increment the map count for tag or break because that is
564 * not needed. Don't do it for indefinite-length arrays and maps
565 * because it is done elsewhere. This is never called for definite-length
566 * arrays and maps.
567 */
568 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
569 }
570 }
571
572
573 /*
574 * Public functions for adding signed integers. See qcbor/qcbor_encode.h
575 */
576 void
QCBOREncode_AddInt64(QCBOREncodeContext * pMe,const int64_t nNum)577 QCBOREncode_AddInt64(QCBOREncodeContext *pMe, const int64_t nNum)
578 {
579 uint8_t uMajorType;
580 uint64_t uValue;
581
582 if(nNum < 0) {
583 /* In CBOR -1 encodes as 0x00 with major type negative int.
584 * First add one as a signed integer because that will not
585 * overflow. Then change the sign as needed for encoding. (The
586 * opposite order, changing the sign and subtracting, can cause
587 * an overflow when encoding INT64_MIN. */
588 int64_t nTmp = nNum + 1;
589 uValue = (uint64_t)-nTmp;
590 uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
591 } else {
592 uValue = (uint64_t)nNum;
593 uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
594 }
595 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uValue, 0);
596 }
597
598
599 /**
600 * @brief Semi-private method to add a buffer full of bytes to encoded output.
601 *
602 * @param[in] pMe The encoding context to add the string to.
603 * @param[in] uMajorType The CBOR major type of the bytes.
604 * @param[in] Bytes The bytes to add.
605 *
606 * Called by inline functions to add text and byte strings.
607 *
608 * (This used to support QCBOREncode_AddEncoded() and
609 * QCBOREncode_AddBytesLenOnly(), but that was pulled out to make this
610 * smaller. This is one of the most used methods and they are some of
611 * the least used).
612 */
613 void
QCBOREncode_Private_AddBuffer(QCBOREncodeContext * pMe,const uint8_t uMajorType,const UsefulBufC Bytes)614 QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pMe,
615 const uint8_t uMajorType,
616 const UsefulBufC Bytes)
617 {
618 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, Bytes.len, 0);
619 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Bytes);
620 }
621
622
623 /*
624 * Public functions for adding raw encoded CBOR. See qcbor/qcbor_encode.h
625 */
626 void
QCBOREncode_AddEncoded(QCBOREncodeContext * pMe,const UsefulBufC Encoded)627 QCBOREncode_AddEncoded(QCBOREncodeContext *pMe, const UsefulBufC Encoded)
628 {
629 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Encoded);
630 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
631 }
632
633
634 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
635 /**
636 * @brief Semi-private method to add a double using preferred encoding.
637 *
638 * @param[in] pMe The encode context.
639 * @param[in] dNum The double to add.
640 *
641 * This converts the double to a float or half-precision if it can be done
642 * without a loss of precision. See QCBOREncode_AddDouble().
643 */
644 void
QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext * pMe,const double dNum)645 QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, const double dNum)
646 {
647 const IEEE754_union uNum = IEEE754_DoubleToSmaller(dNum, true);
648 QCBOREncode_Private_AddType7(pMe, (uint8_t)uNum.uSize, uNum.uValue);
649 }
650
651
652 /**
653 * @brief Semi-private method to add a float using preferred encoding.
654 *
655 * @param[in] pMe The encode context.
656 * @param[in] fNum The float to add.
657 *
658 * This converts the float to a half-precision if it can be done
659 * without a loss of precision. See QCBOREncode_AddFloat().
660 */
661 void
QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext * pMe,const float fNum)662 QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, const float fNum)
663 {
664 const IEEE754_union uNum = IEEE754_SingleToHalf(fNum);
665 QCBOREncode_Private_AddType7(pMe, (uint8_t)uNum.uSize, uNum.uValue);
666 }
667 #endif /* !QCBOR_DISABLE_PREFERRED_FLOAT */
668
669
670 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
671 /**
672 * @brief Semi-private method to add bigfloats and decimal fractions.
673 *
674 * @param[in] pMe The encoding context to add the value to.
675 * @param[in] uTag The type 6 tag indicating what this is to be.
676 * @param[in] BigNumMantissa Is @ref NULLUsefulBufC if mantissa is an
677 * @c int64_t or the actual big number mantissa
678 * if not.
679 * @param[in] bBigNumIsNegative This is @c true if the big number is negative.
680 * @param[in] nMantissa The @c int64_t mantissa if it is not a big number.
681 * @param[in] nExponent The exponent.
682 *
683 * This outputs either the @ref CBOR_TAG_DECIMAL_FRACTION or
684 * @ref CBOR_TAG_BIGFLOAT tag. if @c uTag is @ref CBOR_TAG_INVALID64,
685 * then this outputs the "borrowed" content format.
686 *
687 * The tag content output by this is an array with two members, the
688 * exponent and then the mantissa. The mantissa can be either a big
689 * number or an @c int64_t.
690 *
691 * This implementation cannot output an exponent further from 0 than
692 * @c INT64_MAX.
693 *
694 * To output a mantissa that is between INT64_MAX and UINT64_MAX from 0,
695 * it must be as a big number.
696 *
697 * Typically, QCBOREncode_AddDecimalFraction(), QCBOREncode_AddBigFloat(),
698 * QCBOREncode_AddDecimalFractionBigNum() or QCBOREncode_AddBigFloatBigNum()
699 * is called instead of this.
700 */
701 void
QCBOREncode_Private_AddExpMantissa(QCBOREncodeContext * pMe,const uint64_t uTag,const UsefulBufC BigNumMantissa,const bool bBigNumIsNegative,const int64_t nMantissa,const int64_t nExponent)702 QCBOREncode_Private_AddExpMantissa(QCBOREncodeContext *pMe,
703 const uint64_t uTag,
704 const UsefulBufC BigNumMantissa,
705 const bool bBigNumIsNegative,
706 const int64_t nMantissa,
707 const int64_t nExponent)
708 {
709 /* This is for encoding either a big float or a decimal fraction,
710 * both of which are an array of two items, an exponent and a
711 * mantissa. The difference between the two is that the exponent
712 * is base-2 for big floats and base-10 for decimal fractions, but
713 * that has no effect on the code here.
714 */
715 if(uTag != CBOR_TAG_INVALID64) {
716 QCBOREncode_AddTag(pMe, uTag);
717 }
718 QCBOREncode_OpenArray(pMe);
719 QCBOREncode_AddInt64(pMe, nExponent);
720 if(!UsefulBuf_IsNULLC(BigNumMantissa)) {
721 if(bBigNumIsNegative) {
722 QCBOREncode_AddNegativeBignum(pMe, BigNumMantissa);
723 } else {
724 QCBOREncode_AddPositiveBignum(pMe, BigNumMantissa);
725 }
726 } else {
727 QCBOREncode_AddInt64(pMe, nMantissa);
728 }
729 QCBOREncode_CloseArray(pMe);
730 }
731 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
732
733
734 /**
735 * @brief Semi-private method to open a map, array or bstr-wrapped CBOR
736 *
737 * @param[in] pMe The context to add to.
738 * @param[in] uMajorType The major CBOR type to close
739 *
740 * Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
741 * QCBOREncode_BstrWrap() instead of this.
742 */
743 void
QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext * pMe,const uint8_t uMajorType)744 QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pMe,
745 const uint8_t uMajorType)
746 {
747 /* Add one item to the nesting level we are in for the new map or array */
748 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
749
750 /* The offset where the length of an array or map will get written
751 * is stored in a uint32_t, not a size_t to keep stack usage
752 * smaller. This checks to be sure there is no wrap around when
753 * recording the offset. Note that on 64-bit machines CBOR larger
754 * than 4GB can be encoded as long as no array/map offsets occur
755 * past the 4GB mark, but the public interface says that the
756 * maximum is 4GB to keep the discussion simpler.
757 */
758 size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
759
760 /* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
761 * code can run on a 32-bit machine and tests can pass on a 32-bit
762 * machine. If it was exactly UINT32_MAX, then this code would not
763 * compile or run on a 32-bit machine and an #ifdef or some machine
764 * size detection would be needed reducing portability.
765 */
766 if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
767 pMe->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
768
769 } else {
770 /* Increase nesting level because this is a map or array. Cast
771 * from size_t to uin32_t is safe because of check above.
772 */
773 pMe->uError = Nesting_Increase(&(pMe->nesting), uMajorType, (uint32_t)uEndPosition);
774 }
775 }
776
777
778 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
779 /**
780 * @brief Semi-private method to open a map, array with indefinite length
781 *
782 * @param[in] pMe The context to add to.
783 * @param[in] uMajorType The major CBOR type to close
784 *
785 * Call QCBOREncode_OpenArrayIndefiniteLength() or
786 * QCBOREncode_OpenMapIndefiniteLength() instead of this.
787 */
788 void
QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext * pMe,const uint8_t uMajorType)789 QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
790 const uint8_t uMajorType)
791 {
792 /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
793 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, 0, 0);
794
795 /* Call the definite-length opener just to do the bookkeeping for
796 * nesting. It will record the position of the opening item in the
797 * encoded output but this is not used when closing this open.
798 */
799 QCBOREncode_Private_OpenMapOrArray(pMe, uMajorType);
800 }
801 #endif
802
803
804 /**
805 * @brief Check for errors when decreasing nesting.
806 *
807 * @param pMe QCBOR encoding context.
808 * @param uMajorType The major type of the nesting.
809 *
810 * Check that there is no previous error, that there is actually some
811 * nesting and that the major type of the opening of the nesting
812 * matches the major type of the nesting being closed.
813 *
814 * This is called when closing maps, arrays, byte string wrapping and
815 * open/close of byte strings.
816 */
817 static bool
QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext * pMe,const uint8_t uMajorType)818 QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext *pMe,
819 const uint8_t uMajorType)
820 {
821 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
822 if(pMe->uError != QCBOR_SUCCESS) {
823 return true;
824 }
825
826 if(!Nesting_IsInNest(&(pMe->nesting))) {
827 pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
828 return true;
829 }
830
831 if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
832 pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
833 return true;
834 }
835
836 #else /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
837 /* None of these checks are performed if the encode guards are
838 * turned off as they all relate to correct calling.
839 *
840 * Turning off all these checks does not turn off any checking for
841 * buffer overflows or pointer issues.
842 */
843
844 (void)uMajorType;
845 (void)pMe;
846 #endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
847
848 return false;
849 }
850
851
852 /**
853 * @brief Insert the CBOR head for a map, array or wrapped bstr
854 *
855 * @param pMe QCBOR encoding context.
856 * @param uMajorType One of CBOR_MAJOR_TYPE_XXXX.
857 * @param uLen The length of the data item.
858 *
859 * When an array, map or bstr was opened, nothing was done but note
860 * the position. This function goes back to that position and inserts
861 * the CBOR Head with the major type and length.
862 */
863 static void
QCBOREncode_Private_CloseAggregate(QCBOREncodeContext * pMe,uint8_t uMajorType,size_t uLen)864 QCBOREncode_Private_CloseAggregate(QCBOREncodeContext *pMe,
865 uint8_t uMajorType,
866 size_t uLen)
867 {
868 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
869 return;
870 }
871
872 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
873 uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
874 }
875
876 /* A stack buffer large enough for a CBOR head (9 bytes) */
877 UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
878
879 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
880 uMajorType,
881 0,
882 uLen);
883
884 /* No check for EncodedHead == NULLUsefulBufC is performed here to
885 * save object code. It is very clear that pBufferForEncodedHead is
886 * the correct size. If EncodedHead == NULLUsefulBufC then
887 * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
888 * security hole introduced.
889 */
890 UsefulOutBuf_InsertUsefulBuf(&(pMe->OutBuf),
891 EncodedHead,
892 Nesting_GetStartPos(&(pMe->nesting)));
893
894 Nesting_Decrease(&(pMe->nesting));
895 }
896
897
898 /**
899 * @brief Semi-private method to close a map, array or bstr wrapped CBOR
900 *
901 * @param[in] pMe The context to add to.
902 * @param[in] uMajorType The major CBOR type to close.
903 *
904 * Call QCBOREncode_CloseArray() or QCBOREncode_CloseMap() instead of this.
905 */
906 void
QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext * pMe,const uint8_t uMajorType)907 QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pMe,
908 const uint8_t uMajorType)
909 {
910 QCBOREncode_Private_CloseAggregate(pMe, uMajorType, Nesting_GetCount(&(pMe->nesting)));
911 }
912
913
914 /*
915 * Public functions for closing bstr wrapping. See qcbor/qcbor_encode.h
916 */
917 void
QCBOREncode_CloseBstrWrap2(QCBOREncodeContext * pMe,const bool bIncludeCBORHead,UsefulBufC * pWrappedCBOR)918 QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pMe,
919 const bool bIncludeCBORHead,
920 UsefulBufC *pWrappedCBOR)
921 {
922 const size_t uInsertPosition = Nesting_GetStartPos(&(pMe->nesting));
923 const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
924
925 /* This subtraction can't go negative because the UsefulOutBuf
926 * always only grows and never shrinks. UsefulOutBut itself also
927 * has defenses such that it won't write where it should not even
928 * if given incorrect input lengths.
929 */
930 const size_t uBstrLen = uEndPosition - uInsertPosition;
931
932 /* Actually insert */
933 QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
934
935 if(pWrappedCBOR) {
936 /* Return pointer and length to the enclosed encoded CBOR. The
937 * intended use is for it to be hashed (e.g., SHA-256) in a COSE
938 * implementation. This must be used right away, as the pointer
939 * and length go invalid on any subsequent calls to this
940 * function because there might be calls to
941 * InsertEncodedTypeAndNumber() that slides data to the right.
942 */
943 size_t uStartOfNew = uInsertPosition;
944 if(!bIncludeCBORHead) {
945 /* Skip over the CBOR head to just get the inserted bstr */
946 const size_t uNewEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
947 uStartOfNew += uNewEndPosition - uEndPosition;
948 }
949 const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
950 *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uStartOfNew);
951 }
952 }
953
954
955 /*
956 * Public function for canceling a bstr wrap. See qcbor/qcbor_encode.h
957 */
958 void
QCBOREncode_CancelBstrWrap(QCBOREncodeContext * pMe)959 QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pMe)
960 {
961 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, CBOR_MAJOR_TYPE_BYTE_STRING)) {
962 return;
963 }
964
965 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
966 const size_t uCurrent = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
967 if(pMe->nesting.pCurrentNesting->uStart != uCurrent) {
968 pMe->uError = QCBOR_ERR_CANNOT_CANCEL;
969 return;
970 }
971 /* QCBOREncode_CancelBstrWrap() can't correctly undo
972 * QCBOREncode_BstrWrapInMap() or QCBOREncode_BstrWrapInMapN(). It
973 * can't undo the labels they add. It also doesn't catch the error
974 * of using it this way. QCBOREncode_CancelBstrWrap() is used
975 * infrequently and the the result is incorrect CBOR, not a
976 * security hole, so no extra code or state is added to handle this
977 * condition.
978 */
979 #endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
980
981 Nesting_Decrease(&(pMe->nesting));
982 Nesting_Decrement(&(pMe->nesting));
983 }
984
985
986 /*
987 * Public function for opening a byte string. See qcbor/qcbor_encode.h
988 */
989 void
QCBOREncode_OpenBytes(QCBOREncodeContext * pMe,UsefulBuf * pPlace)990 QCBOREncode_OpenBytes(QCBOREncodeContext *pMe, UsefulBuf *pPlace)
991 {
992 *pPlace = UsefulOutBuf_GetOutPlace(&(pMe->OutBuf));
993 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
994 uint8_t uMajorType = Nesting_GetMajorType(&(pMe->nesting));
995 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
996 /* It's OK to nest a byte string in any type but
997 * another open byte string. */
998 pMe->uError = QCBOR_ERR_OPEN_BYTE_STRING;
999 return;
1000 }
1001 #endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
1002
1003 QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR);
1004 }
1005
1006
1007 /*
1008 * Public function for closing a byte string. See qcbor/qcbor_encode.h
1009 */
1010 void
QCBOREncode_CloseBytes(QCBOREncodeContext * pMe,const size_t uAmount)1011 QCBOREncode_CloseBytes(QCBOREncodeContext *pMe, const size_t uAmount)
1012 {
1013 UsefulOutBuf_Advance(&(pMe->OutBuf), uAmount);
1014 if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
1015 /* Advance too far. Normal off-end error handling in effect here. */
1016 return;
1017 }
1018
1019 QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
1020 }
1021
1022
1023 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1024
1025 /**
1026 * @brief Semi-private method to close a map, array with indefinite length
1027 *
1028 * @param[in] pMe The context to add to.
1029 * @param[in] uMajorType The major CBOR type to close.
1030 *
1031 * Call QCBOREncode_CloseArrayIndefiniteLength() or
1032 * QCBOREncode_CloseMapIndefiniteLength() instead of this.
1033 */
1034 void
QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext * pMe,const uint8_t uMajorType)1035 QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1036 const uint8_t uMajorType)
1037 {
1038 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
1039 return;
1040 }
1041
1042 /* Append the break marker (0xff for both arrays and maps) */
1043 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
1044 Nesting_Decrease(&(pMe->nesting));
1045 }
1046 #endif
1047
1048
1049 /*
1050 * Public function to finish and get the encoded result. See qcbor/qcbor_encode.h
1051 */
1052 QCBORError
QCBOREncode_Finish(QCBOREncodeContext * pMe,UsefulBufC * pEncodedCBOR)1053 QCBOREncode_Finish(QCBOREncodeContext *pMe, UsefulBufC *pEncodedCBOR)
1054 {
1055 if(QCBOREncode_GetErrorState(pMe) != QCBOR_SUCCESS) {
1056 goto Done;
1057 }
1058
1059 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
1060 if(Nesting_IsInNest(&(pMe->nesting))) {
1061 pMe->uError = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1062 goto Done;
1063 }
1064 #endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
1065
1066 *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
1067
1068 Done:
1069 return pMe->uError;
1070 }
1071
1072
1073 /*
1074 * Public functions to get size of the encoded result. See qcbor/qcbor_encode.h
1075 */
1076 QCBORError
QCBOREncode_FinishGetSize(QCBOREncodeContext * pMe,size_t * puEncodedLen)1077 QCBOREncode_FinishGetSize(QCBOREncodeContext *pMe, size_t *puEncodedLen)
1078 {
1079 UsefulBufC Enc;
1080
1081 QCBORError nReturn = QCBOREncode_Finish(pMe, &Enc);
1082
1083 if(nReturn == QCBOR_SUCCESS) {
1084 *puEncodedLen = Enc.len;
1085 }
1086
1087 return nReturn;
1088 }
1089