blob: 47208a80ee63f595a80438367a1a0b144661ceb0 [file] [log] [blame]
Laurence Lundbladed253e412024-08-21 11:02:56 -07001/* ===========================================================================
2 * Copyright (c) 2016-2018, The Linux Foundation.
3 * Copyright (c) 2018-2024, Laurence Lundblade.
4 * Copyright (c) 2021, Arm Limited.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of The Linux Foundation nor the names of its
17 * contributors, nor the name "Laurence Lundblade" may be used to
18 * endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ========================================================================= */
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_encode.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070036#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080038#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
39#include <math.h> /* Only for NAN definition */
40#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
41
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070042
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080043/**
44 * @file qcbor_encode.c
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080045 *
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080046 * The entire implementation of the QCBOR encoder.
47 */
48
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070049
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070050/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080051 * == Nesting Tracking ==
52 *
53 * The following functions and data type QCBORTrackNesting implement
54 * the nesting management for encoding.
55 *
56 * CBOR's two nesting types, arrays and maps, are tracked here. There
57 * is a limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and
58 * maps that can be nested in one encoding so the encoding context
59 * stays small enough to fit on the stack.
60 *
61 * When an array/map is opened, pCurrentNesting points to the element
62 * in pArrays that records the type, start position and accumulates a
63 * count of the number of items added. When closed the start position
64 * is used to go back and fill in the type and number of items in the
65 * array/map.
66 *
67 * Encoded output can be a CBOR Sequence (RFC 8742) in which case
68 * there is no top-level array or map. It starts out with a string,
69 * integer or other non-aggregate type. It may have an array or map
70 * other than at the start, in which case that nesting is tracked
71 * here.
72 *
73 * QCBOR has a special feature to allow constructing byte string
74 * wrapped CBOR directly into the output buffer, so no extra buffer is
75 * needed for byte string wrapping. This is implemented as nesting
76 * with the type CBOR_MAJOR_TYPE_BYTE_STRING and is tracked here. Byte
77 * string wrapped CBOR is used by COSE for data that is to be hashed.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070078 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -070079static void
Laurence Lundblade274ddef2022-05-17 09:12:23 -070080Nesting_Init(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070081{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080082 /* Assumes pNesting has been zeroed. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070083 pNesting->pCurrentNesting = &pNesting->pArrays[0];
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080084 /* Implied CBOR array at the top nesting level. This is never
85 * returned, but makes the item count work correctly.
86 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070087 pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY;
88}
89
Laurence Lundblade8e36f812024-01-26 10:59:29 -070090static uint8_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -070091Nesting_Increase(QCBORTrackNesting *pNesting,
Laurence Lundblade8e36f812024-01-26 10:59:29 -070092 const uint8_t uMajorType,
93 const uint32_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070094{
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070095 if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) {
Laurence Lundblade29497c02020-07-11 15:44:03 -070096 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070097 } else {
98 pNesting->pCurrentNesting++;
99 pNesting->pCurrentNesting->uCount = 0;
100 pNesting->pCurrentNesting->uStart = uPos;
101 pNesting->pCurrentNesting->uMajorType = uMajorType;
Laurence Lundblade29497c02020-07-11 15:44:03 -0700102 return QCBOR_SUCCESS;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700103 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104}
105
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700106static void
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700107Nesting_Decrease(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700108{
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700109 if(pNesting->pCurrentNesting > &pNesting->pArrays[0]) {
110 pNesting->pCurrentNesting--;
111 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700112}
113
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700114static uint8_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700115Nesting_Increment(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700116{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800117#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundbladeb95afec2024-08-26 10:51:28 -0700118 if(pNesting->pCurrentNesting->uCount >= QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700119 return QCBOR_ERR_ARRAY_TOO_LONG;
120 }
Laurence Lundbladed253e412024-08-21 11:02:56 -0700121#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800122
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700123 pNesting->pCurrentNesting->uCount++;
Laurence Lundblade2c40ab82018-12-30 14:20:29 -0800124
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700125 return QCBOR_SUCCESS;
126}
127
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700128static void
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700129Nesting_Decrement(QCBORTrackNesting *pNesting)
Laurence Lundblade8d3b8552021-06-10 11:11:54 -0700130{
131 /* No error check for going below 0 here needed because this
132 * is only used by QCBOREncode_CancelBstrWrap() and it checks
133 * the nesting level before calling this. */
134 pNesting->pCurrentNesting->uCount--;
135}
136
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700137static uint16_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700138Nesting_GetCount(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700139{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800140 /* The nesting count recorded is always the actual number of
141 * individual data items in the array or map. For arrays CBOR uses
142 * the actual item count. For maps, CBOR uses the number of pairs.
143 * This function returns the number needed for the CBOR encoding,
144 * so it divides the number of items by two for maps to get the
145 * number of pairs.
146 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800147 if(pNesting->pCurrentNesting->uMajorType == CBOR_MAJOR_TYPE_MAP) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800148 /* Cast back to uint16_t after integer promotion from bit shift */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800149 return (uint16_t)(pNesting->pCurrentNesting->uCount >> 1);
150 } else {
151 return pNesting->pCurrentNesting->uCount;
152 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153}
154
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700155static uint32_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700156Nesting_GetStartPos(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700157{
158 return pNesting->pCurrentNesting->uStart;
159}
160
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800161#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700162static uint8_t
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700163Nesting_GetMajorType(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700164{
165 return pNesting->pCurrentNesting->uMajorType;
166}
167
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700168static bool
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700169Nesting_IsInNest(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700170{
Laurence Lundbladeee851742020-01-08 08:37:05 -0800171 return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? false : true;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700172}
Laurence Lundbladee2226742024-08-16 10:50:23 -0700173#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700174
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700175
176
177
178/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800179 * == Major CBOR Types ==
180 *
181 * Encoding of the major CBOR types is by these functions:
182 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800183 * CBOR Major Type Public Function
184 * 0 QCBOREncode_AddUInt64()
185 * 0, 1 QCBOREncode_AddUInt64(), QCBOREncode_AddInt64()
186 * 2, 3 QCBOREncode_AddBuffer()
187 * 4, 5 QCBOREncode_OpenMapOrArray(), QCBOREncode_CloseMapOrArray(),
188 * QCBOREncode_OpenMapOrArrayIndefiniteLength(),
189 * QCBOREncode_CloseMapOrArrayIndefiniteLength()
Laurence Lundblade721b56e2024-10-22 03:02:04 -0700190 * 6 QCBOREncode_AddTagNumber()
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800191 * 7 QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
192 * QCBOREncode_AddDoubleNoPreferred(),
193 * QCBOREncode_AddFloatNoPreferred(), QCBOREncode_AddType7()
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800194 *
195 * Additionally, encoding of decimal fractions and bigfloats is by
196 * QCBOREncode_AddExponentAndMantissa() and byte strings that wrap
197 * encoded CBOR are handled by QCBOREncode_OpenMapOrArray() and
198 * QCBOREncode_CloseBstrWrap2().
199 *
200 *
201 * == Error Tracking Plan ==
202 *
203 * Errors are tracked internally and not returned until
204 * QCBOREncode_Finish() or QCBOREncode_GetErrorState() is called. The
205 * CBOR errors are in me->uError. UsefulOutBuf also tracks whether
206 * the buffer is full or not in its context. Once either of these
207 * errors is set they are never cleared. Only QCBOREncode_Init()
208 * resets them. Or said another way, they must never be cleared or
209 * we'll tell the caller all is good when it is not.
210 *
211 * Only one error code is reported by QCBOREncode_Finish() even if
212 * there are multiple errors. The last one set wins. The caller might
213 * have to fix one error to reveal the next one they have to fix.
214 * This is OK.
215 *
216 * The buffer full error tracked by UsefulBuf is only pulled out of
217 * UsefulBuf in QCBOREncode_Finish() so it is the one that usually
218 * wins. UsefulBuf will never go off the end of the buffer even if it
219 * is called again and again when full.
220 *
221 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS disables about half of the error
222 * checks here to reduce code size by about 150 bytes leaving only the
223 * checks for size to avoid buffer overflow. If the calling code is
224 * completely correct, checks are completely unnecessary. For
225 * example, there is no need to check that all the opens are matched
226 * by a close.
227 *
228 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS also disables the check for more
229 * than QCBOR_MAX_ITEMS_IN_ARRAY in an array. Since
Laurence Lundbladeb95afec2024-08-26 10:51:28 -0700230 * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,534) it is very unlikely
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800231 * to be reached. If it is reached, the count will wrap around to zero
232 * and CBOR that is not well formed will be produced, but there will
233 * be no buffers overrun and new security issues in the code.
234 *
235 * The 8 errors returned here fall into three categories:
236 *
237 * Sizes
238 * QCBOR_ERR_BUFFER_TOO_LARGE -- Encoded output exceeded UINT32_MAX
239 * QCBOR_ERR_BUFFER_TOO_SMALL -- Output buffer too small
240 * QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Nesting > QCBOR_MAX_ARRAY_NESTING1
241 * QCBOR_ERR_ARRAY_TOO_LONG -- Too many items added to an array/map [1]
242 *
243 * Nesting constructed incorrectly
244 * QCBOR_ERR_TOO_MANY_CLOSES -- More close calls than opens [1]
245 * QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open [1]
246 * QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes [1]
247 *
248 * Would generate not-well-formed CBOR
249 * QCBOR_ERR_ENCODE_UNSUPPORTED -- Simple type between 24 and 31 [1]
250 *
251 * [1] indicated disabled by QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700252 */
253
254
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800255/* Forward declaration for reference in QCBOREncode_Init() */
256static void
257QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe);
258
259
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260/*
Laurence Lundbladeb9ccd6b2024-02-06 05:44:25 -0700261 * Public function for initialization. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700262 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700263void
264QCBOREncode_Init(QCBOREncodeContext *pMe, UsefulBuf Storage)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700265{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700266 memset(pMe, 0, sizeof(QCBOREncodeContext));
267 UsefulOutBuf_Init(&(pMe->OutBuf), Storage);
268 Nesting_Init(&(pMe->nesting));
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800269 pMe->pfnCloseMap = QCBOREncode_Private_CloseMapUnsorted;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700270}
271
272
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000273/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800274 * Public function to encode a CBOR head. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700275 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700276UsefulBufC
277QCBOREncode_EncodeHead(UsefulBuf Buffer,
278 uint8_t uMajorType,
279 uint8_t uMinLen,
280 uint64_t uArgument)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700281{
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800282 /*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800283 * == Description of the CBOR Head ==
284 *
285 * The head of a CBOR data item
286 * +---+-----+ +--------+ +--------+ +--------+ +--------+
287 * |M T| A R G U M E N T . . . |
288 * +---+-----+ +--------+ +--------+ +--------+ ... +--------+
289 *
290 * Every CBOR data item has a "head". It is made up of the "major
291 * type" and the "argument".
292 *
293 * The major type indicates whether the data item is an integer,
294 * string, array or such. It is encoded in 3 bits giving it a range
295 * from 0 to 7. 0 indicates the major type is a positive integer,
296 * 1 a negative integer, 2 a byte string and so on.
297 *
298 * These 3 bits are the first part of the "initial byte" in a data
299 * item. Every data item has an initial byte, and some only have
300 * the initial byte.
301 *
302 * The argument is essentially a number between 0 and UINT64_MAX
303 * (18446744073709551615). This number is interpreted to mean
304 * different things for the different major types. For major type
305 * 0, a positive integer, it is value of the data item. For major
306 * type 2, a byte string, it is the length in bytes of the byte
307 * string. For major type 4, an array, it is the number of data
308 * items in the array.
309 *
310 * Special encoding is used so that the argument values less than
311 * 24 can be encoded very compactly in the same byte as the major
312 * type is encoded. When the lower 5 bits of the initial byte have
313 * a value less than 24, then that is the value of the argument.
314 *
315 * If the lower 5 bits of the initial byte are less than 24, then
316 * they are the value of the argument. This allows integer values 0
317 * - 23 to be CBOR encoded in just one byte.
318 *
319 * When the value of lower 5 bits are 24, 25, 26, or 27 the
320 * argument is encoded in 1, 2, 4 or 8 bytes following the initial
321 * byte in network byte order (bit endian). The cases when it is
322 * 28, 29 and 30 are reserved for future use. The value 31 is a
323 * special indicator for indefinite length strings, arrays and
324 * maps.
325 *
326 * The lower 5 bits are called the "additional information."
327 *
328 * Thus the CBOR head may be 1, 2, 3, 5 or 9 bytes long.
329 *
330 * It is legal in CBOR to encode the argument using any of these
331 * lengths even if it could be encoded in a shorter length. For
332 * example it is legal to encode a data item representing the
333 * positive integer 0 in 9 bytes even though it could be encoded in
334 * only 0. This is legal to allow for for very simple code or even
335 * hardware-only implementations that just output a register
336 * directly.
337 *
338 * CBOR defines preferred encoding as the encoding of the argument
339 * in the smallest number of bytes needed to encode it.
340 *
341 * This function takes the major type and argument as inputs and
342 * outputs the encoded CBOR head for them. It does conversion to
343 * network byte order. It implements CBOR preferred encoding,
344 * outputting the shortest representation of the argument.
345 *
346 * == Endian Conversion ==
347 *
348 * This code does endian conversion without hton() or knowing the
349 * endianness of the machine by using masks and shifts. This avoids
350 * the dependency on hton() and the mess of figuring out how to
351 * find the machine's endianness.
352 *
353 * This is a good efficient implementation on little-endian
354 * machines. A faster and smaller implementation is possible on
355 * big-endian machines because CBOR/network byte order is
356 * big-endian. However big-endian machines are uncommon.
357 *
358 * On x86, this is about 150 bytes instead of 500 bytes for the
359 * original, more formal unoptimized code.
360 *
361 * This also does the CBOR preferred shortest encoding for integers
362 * and is called to do endian conversion for floats.
363 *
364 * It works backwards from the least significant byte to the most
365 * significant byte.
366 *
367 * == Floating Point ==
368 *
369 * When the major type is 7 and the 5 lower bits have the values
370 * 25, 26 or 27, the argument is a floating-point number that is
371 * half, single or double-precision. Note that it is not the
372 * conversion from a floating-point value to an integer value like
373 * converting 0x00 to 0.00, it is the interpretation of the bits in
374 * the argument as an IEEE 754 float-point number.
375 *
376 * Floating-point numbers must be converted to network byte
377 * order. That is accomplished here by exactly the same code that
378 * converts integer arguments to network byte order.
379 *
380 * There is preferred encoding for floating-point numbers in CBOR,
381 * but it is very different than for integers and it is not
382 * implemented here. Half-precision is preferred to
383 * single-precision which is preferred to double-precision only if
384 * the conversion can be performed without loss of precision. Zero
385 * and infinity can always be converted to half-precision, without
386 * loss but 3.141592653589 cannot.
387 *
388 * The way this function knows to not do preferred encoding on the
389 * argument passed here when it is a floating point number is the
390 * uMinLen parameter. It should be 2, 4 or 8 for half, single and
391 * double precision floating point values. This prevents and the
392 * incorrect removal of leading zeros when encoding arguments that
393 * are floating-point numbers.
394 *
395 * == Use of Type int and Static Analyzers ==
396 *
397 * The type int is used here for several variables because of the
398 * way integer promotion works in C for variables that are uint8_t
399 * or uint16_t. The basic rule is that they will always be promoted
400 * to int if they will fit. These integer variables here need only
401 * hold values less than 255 so they will always fit into an int.
402 *
403 * Most of values stored are never negative, so one might think
404 * that unsigned int would be more correct than int. However the C
405 * integer promotion rules only promote to unsigned int if the
406 * result won't fit into an int even if the promotion is for an
407 * unsigned variable like uint8_t.
408 *
409 * By declaring these int, there are few implicit conversions and
410 * fewer casts needed. Code size is reduced a little. It makes
411 * static analyzers happier.
412 *
413 * Note also that declaring these uint8_t won't stop integer wrap
414 * around if the code is wrong. It won't make the code more
415 * correct.
416 *
417 * https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
418 * https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
419 *
420 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800421 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800422
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800423 /* The buffer must have room for the largest CBOR HEAD + one
424 * extra. The one extra is needed for this code to work as it does
425 * a pre-decrement.
426 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700427 if(Buffer.len < QCBOR_HEAD_BUFFER_SIZE) {
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000428 return NULLUsefulBufC;
429 }
430
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800431 /* Pointer to last valid byte in the buffer */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700432 uint8_t * const pBufferEnd = &((uint8_t *)Buffer.ptr)[QCBOR_HEAD_BUFFER_SIZE-1];
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000433
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800434 /* Point to the last byte and work backwards */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000435 uint8_t *pByte = pBufferEnd;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800436 /* The 5 bits in the initial byte that are not the major type */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800437 int nAdditionalInfo;
Laurence Lundblade2c40ab82018-12-30 14:20:29 -0800438
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700439#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800440 if(uMajorType > QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800441 /* Special case for start & end of indefinite length */
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800442 uMajorType = uMajorType - QCBOR_INDEFINITE_LEN_TYPE_MODIFIER;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800443 /* This takes advantage of design of CBOR where additional info
444 * is 31 for both opening and closing indefinite length
445 * maps and arrays.
446 */
447 #if CBOR_SIMPLE_BREAK != LEN_IS_INDEFINITE
448 #error additional info for opening array not the same as for closing
449 #endif
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800450 nAdditionalInfo = CBOR_SIMPLE_BREAK;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800451
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700452 } else
Laurence Lundbladed253e412024-08-21 11:02:56 -0700453#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700454 if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800455 /* Simple case where argument is < 24 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000456 nAdditionalInfo = (int)uArgument;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800457
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800458 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800459 /* This encodes the argument in 1,2,4 or 8 bytes. The outer loop
460 * runs once for 1 byte and 4 times for 8 bytes. The inner loop
461 * runs 1, 2 or 4 times depending on outer loop counter. This
462 * works backwards shifting 8 bits off the argument being
463 * encoded at a time until all bits from uArgument have been
464 * encoded and the minimum encoding size is reached. Minimum
465 * encoding size is for floating-point numbers that have some
466 * zero-value bytes that must be output.
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800467 */
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800468 static const uint8_t aIterate[] = {1,1,2,4};
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000469
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800470 /* uMinLen passed in is unsigned, but goes negative in the loop
471 * so it must be converted to a signed value.
472 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000473 int nMinLen = (int)uMinLen;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800474 int i;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000475 for(i = 0; uArgument || nMinLen > 0; i++) {
476 const int nIterations = (int)aIterate[i];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800477 for(int j = 0; j < nIterations; j++) {
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000478 *--pByte = (uint8_t)(uArgument & 0xff);
479 uArgument = uArgument >> 8;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800480 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800481 nMinLen -= nIterations;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800482 }
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800483
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800484 nAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700485 }
Laurence Lundbladef970f1d2018-12-14 01:44:23 -0800486
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800487 /* This expression integer-promotes to type int. The code above in
488 * function guarantees that nAdditionalInfo will never be larger
489 * than 0x1f. The caller may pass in a too-large uMajor type. The
Laurence Lundblade11654912024-05-09 11:49:24 -0700490 * conversion to uint8_t will cause an integer wrap around and
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800491 * incorrect CBOR will be generated, but no security issue will
492 * occur.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800493 */
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800494 const int nInitialByte = (uMajorType << 5) + nAdditionalInfo;
495 *--pByte = (uint8_t)nInitialByte;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800496
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000497#ifdef EXTRA_ENCODE_HEAD_CHECK
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800498 /* This is a sanity check that can be turned on to verify the
499 * pointer math in this function is not going wrong. Turn it on and
500 * run the whole test suite to perform the check.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800501 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000502 if(pBufferEnd - pByte > 9 || pBufferEnd - pByte < 1 || pByte < (uint8_t *)buffer.ptr) {
503 return NULLUsefulBufC;
504 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800505#endif /* EXTRA_ENCODE_HEAD_CHECK */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800506
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800507 /* Length will not go negative because the loops run for at most 8 decrements
508 * of pByte, only one other decrement is made, and the array is sized
509 * for this.
510 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000511 return (UsefulBufC){pByte, (size_t)(pBufferEnd - pByte)};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700512}
513
514
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000515/**
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700516 * @brief Increment item counter for maps and arrays.
517 *
518 * @param pMe QCBOR encoding context.
519 *
520 * This is mostly a separate function to make code more readable and
521 * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
522 */
523static void
524QCBOREncode_Private_IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
525{
526#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
527 if(pMe->uError == QCBOR_SUCCESS) {
528 pMe->uError = Nesting_Increment(&(pMe->nesting));
529 }
530#else
531 (void)Nesting_Increment(&(pMe->nesting));
Laurence Lundbladed253e412024-08-21 11:02:56 -0700532#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700533}
534
535
536/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800537 * @brief Append the CBOR head, the major type and argument
538 *
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700539 * @param pMe Encoder context.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800540 * @param uMajorType Major type to insert.
541 * @param uArgument The argument (an integer value or a length).
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800542 * @param uMinLen Minimum number of bytes for encoding the CBOR argument.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800543 *
544 * This formats the CBOR "head" and appends it to the output.
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700545 *
546 * This also increments the array/map item counter in most cases.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000547 */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700548void
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700549QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext *pMe,
550 const uint8_t uMajorType,
551 const uint64_t uArgument,
552 const uint8_t uMinLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800554 /* A stack buffer large enough for a CBOR head */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000555 UsefulBuf_MAKE_STACK_UB (pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
556
557 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
558 uMajorType,
559 uMinLen,
560 uArgument);
561
562 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800563 * save object code. It is very clear that pBufferForEncodedHead is
564 * the correct size. If EncodedHead == NULLUsefulBufC then
565 * UsefulOutBuf_AppendUsefulBuf() will do nothing so there is no
566 * security hole introduced.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000567 */
568
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700569 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), EncodedHead);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700571 if(!(uMajorType & QCBOR_INDEFINITE_LEN_TYPE_MODIFIER || uMajorType == CBOR_MAJOR_TYPE_TAG)) {
572 /* Don't increment the map count for tag or break because that is
573 * not needed. Don't do it for indefinite-length arrays and maps
574 * because it is done elsewhere. This is never called for definite-length
575 * arrays and maps.
576 */
577 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700578 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700579}
580
Laurence Lundblade56230d12018-11-01 11:14:51 +0700581
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700582/*
Laurence Lundbladed253e412024-08-21 11:02:56 -0700583 * Public function for adding signed integers. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -0800584 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700585void
586QCBOREncode_AddInt64(QCBOREncodeContext *pMe, const int64_t nNum)
Laurence Lundblade067035b2018-11-28 17:35:25 -0800587{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800588 uint8_t uMajorType;
589 uint64_t uValue;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800590
591 if(nNum < 0) {
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700592 /* In CBOR -1 encodes as 0x00 with major type negative int.
593 * First add one as a signed integer because that will not
Laurence Lundblade2d493002024-02-01 11:09:17 -0700594 * overflow. Then change the sign as needed for encoding (the
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700595 * opposite order, changing the sign and subtracting, can cause
Laurence Lundblade2d493002024-02-01 11:09:17 -0700596 * an overflow when encoding INT64_MIN). */
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700597 int64_t nTmp = nNum + 1;
598 uValue = (uint64_t)-nTmp;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800599 uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
600 } else {
601 uValue = (uint64_t)nNum;
602 uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
603 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700604 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uValue, 0);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800605}
606
607
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700608/**
609 * @brief Semi-private method to add a buffer full of bytes to encoded output.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800610 *
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700611 * @param[in] pMe The encoding context to add the string to.
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700612 * @param[in] uMajorType The CBOR major type of the bytes.
613 * @param[in] Bytes The bytes to add.
614 *
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700615 * Called by inline functions to add text and byte strings.
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700616 *
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700617 * (This used to support QCBOREncode_AddEncoded() and
618 * QCBOREncode_AddBytesLenOnly(), but that was pulled out to make this
619 * smaller. This is one of the most used methods and they are some of
620 * the least used).
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700621 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700622void
623QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pMe,
624 const uint8_t uMajorType,
625 const UsefulBufC Bytes)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626{
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700627 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, Bytes.len, 0);
Laurence Lundblade15b93d42024-02-07 17:39:10 -0800628 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Bytes);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700630
Laurence Lundbladecafcfe12018-10-31 21:59:50 +0700631
Laurence Lundblade55a24832018-10-30 04:35:08 +0700632/*
Laurence Lundbladed253e412024-08-21 11:02:56 -0700633 * Public function for adding raw encoded CBOR. See qcbor/qcbor_encode.h
Laurence Lundblade55a24832018-10-30 04:35:08 +0700634 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700635void
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700636QCBOREncode_AddEncoded(QCBOREncodeContext *pMe, const UsefulBufC Encoded)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700637{
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700638 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Encoded);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700640}
641
642
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700643#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade8d9e0cd2024-05-25 18:12:19 -0700644/**
645 * @brief Semi-private method to add a double using preferred encoding.
646 *
647 * @param[in] pMe The encode context.
648 * @param[in] dNum The double to add.
649 *
650 * This converts the double to a float or half-precision if it can be done
651 * without a loss of precision. See QCBOREncode_AddDouble().
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700652 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700653void
Laurence Lundblade70fc1252024-05-31 10:57:28 -0700654QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, double dNum)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700655{
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800656 IEEE754_union FloatResult;
657 bool bNoNaNPayload;
658 struct IEEE754_ToInt IntResult;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700659 uint64_t uNegValue;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700660
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800661#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700662 if(IEEE754_DoubleHasNaNPayload(dNum) && !(pMe->uAllow & QCBOR_ENCODE_ALLOW_NAN_PAYLOAD)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800663 pMe->uError = QCBOR_ERR_NOT_ALLOWED;
664 return;
665 }
666#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
667
668 if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
669 IntResult = IEEE754_DoubleToInt(dNum);
670 switch(IntResult.type) {
671 case IEEE754_ToInt_IS_INT:
672 QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
673 return;
674 case IEEE754_ToInt_IS_UINT:
675 QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
676 return;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700677 case IEEE754_ToInt_IS_65BIT_NEG:
678 {
679 if(IntResult.integer.un_signed == 0) {
680 uNegValue = UINT64_MAX;
681 } else {
682 uNegValue = IntResult.integer.un_signed-1;
683 }
684 QCBOREncode_AddNegativeUInt64(pMe, uNegValue);
685 }
686 return;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800687 case IEEE754_ToInt_NaN:
688 dNum = NAN;
689 bNoNaNPayload = true;
690 break;
691 case IEEE754_ToInt_NO_CONVERSION:
692 bNoNaNPayload = true;
693 }
694 } else {
695 bNoNaNPayload = false;
696 }
697
698 FloatResult = IEEE754_DoubleToSmaller(dNum, true, bNoNaNPayload);
699
700 QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700701}
Laurence Lundblade9682a532020-06-06 18:33:04 -0700702
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700703
Laurence Lundblade8d9e0cd2024-05-25 18:12:19 -0700704/**
705 * @brief Semi-private method to add a float using preferred encoding.
706 *
707 * @param[in] pMe The encode context.
708 * @param[in] fNum The float to add.
709 *
710 * This converts the float to a half-precision if it can be done
711 * without a loss of precision. See QCBOREncode_AddFloat().
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800712 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700713void
Laurence Lundblade70fc1252024-05-31 10:57:28 -0700714QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, float fNum)
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700715{
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800716 IEEE754_union FloatResult;
717 bool bNoNaNPayload;
718 struct IEEE754_ToInt IntResult;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700719 uint64_t uNegValue;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700720
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800721#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700722 if(IEEE754_SingleHasNaNPayload(fNum) && !(pMe->uAllow & QCBOR_ENCODE_ALLOW_NAN_PAYLOAD)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800723 pMe->uError = QCBOR_ERR_NOT_ALLOWED;
724 return;
725 }
726#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
727
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800728 if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
729 IntResult = IEEE754_SingleToInt(fNum);
730 switch(IntResult.type) {
731 case IEEE754_ToInt_IS_INT:
732 QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
733 return;
734 case IEEE754_ToInt_IS_UINT:
735 QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
736 return;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700737 case IEEE754_ToInt_IS_65BIT_NEG:
738 {
739 if(IntResult.integer.un_signed == 0) {
740 uNegValue = UINT64_MAX;
741 } else {
742 uNegValue = IntResult.integer.un_signed-1;
743 }
744 QCBOREncode_AddNegativeUInt64(pMe, uNegValue);
745 }
746 return;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800747 case IEEE754_ToInt_NaN:
748 fNum = NAN;
749 bNoNaNPayload = true;
750 break;
751 case IEEE754_ToInt_NO_CONVERSION:
752 bNoNaNPayload = true;
753 }
754 } else {
755 bNoNaNPayload = false;
756 }
757
758 FloatResult = IEEE754_SingleToHalf(fNum, bNoNaNPayload);
759
760 QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800761}
Laurence Lundbladed253e412024-08-21 11:02:56 -0700762#endif /* ! QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800763
Laurence Lundblade067035b2018-11-28 17:35:25 -0800764
765
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700766
Laurence Lundblade68769332024-11-03 13:09:20 -0800767/**
768 * @brief Convert a big number to unsigned integer.
769 *
770 * @param[in] BigNumber Big number to convert.
771 *
772 * @return Converted unsigned.
773 *
774 * The big number must be less than 8 bytes long.
775 **/
776static uint64_t
777QCBOREncode_Private_BigNumberToUInt(const UsefulBufC BigNumber)
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700778{
Laurence Lundblade68769332024-11-03 13:09:20 -0800779 uint64_t uInt;
780 size_t uIndex;
781
782 uInt = 0;
783 for(uIndex = 0; uIndex < BigNumber.len; uIndex++) {
784 uInt = (uInt << 8) + UsefulBufC_NTH_BYTE(BigNumber, uIndex);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700785 }
Laurence Lundblade68769332024-11-03 13:09:20 -0800786
787 return uInt;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700788}
789
790
Laurence Lundblade68769332024-11-03 13:09:20 -0800791/**
792 * @brief Is there a carry when you subtract 1 from the BigNumber.
793 *
794 * @param[in] BigNumber Big number to check for carry.
795 *
796 * @return If there is a carry, \c true.
797 *
798 * If this returns @c true, then @c BigNumber - 1 is
799 * one byte shorter than @c BigNumber.
800 **/
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700801static bool
Laurence Lundblade68769332024-11-03 13:09:20 -0800802QCBOREncode_Private_BigNumberCarry(const UsefulBufC BigNumber)
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700803{
804 bool bCarry;
805 UsefulBufC SubBigNum;
806
Laurence Lundblade68769332024-11-03 13:09:20 -0800807 // Improvement: rework without recursion?
808
809 if(BigNumber.len == 0) {
810 return true; /* Subtracting one from zero-length string gives a carry */
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700811 } else {
Laurence Lundblade68769332024-11-03 13:09:20 -0800812 SubBigNum = UsefulBuf_Tail(BigNumber, 1);
813 bCarry = QCBOREncode_Private_BigNumberCarry(SubBigNum);
814 if(UsefulBufC_NTH_BYTE(BigNumber, 0) == 0x00 && bCarry) {
815 /* Subtracting one from 0 gives a carry */
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700816 return true;
817 } else {
818 return false;
819 }
820 }
821}
822
823
824/*
Laurence Lundblade68769332024-11-03 13:09:20 -0800825 * @brief Output negative bignum bytes with subtraction of 1.
826 *
827 * @param[in] pMe The decode context.
828 * @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
829 * @ref QCBOR_ENCODE_AS_BORROWED.
830 * @param[in] BigNumber The negative big number.
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700831 */
Laurence Lundblade68769332024-11-03 13:09:20 -0800832static void
833QCBOREncode_Private_AddTNegativeBigNumber(QCBOREncodeContext *pMe,
834 const uint8_t uTagRequirement,
835 const UsefulBufC BigNumber)
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700836{
837 size_t uLen;
838 bool bCarry;
839 bool bCopiedSomething;
840 uint8_t uByte;
841 UsefulBufC SubString;
842 UsefulBufC NextSubString;
843
Laurence Lundblade68769332024-11-03 13:09:20 -0800844 QCBOREncode_Private_BigNumberTag(pMe, uTagRequirement, true);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700845
846 /* This works on any length without the need of an additional buffer */
847
848 /* This subtracts one, possibly making the string shorter by one
849 * 0x01 -> 0x00
850 * 0x01 0x00 -> 0xff
851 * 0x00 0x01 0x00 -> 0x00 0xff
852 * 0x02 0x00 -> 0x01 0xff
853 * 0xff -> 0xfe
854 * 0xff 0x00 -> 0xfe 0xff
855 * 0x01 0x00 0x00 -> 0xff 0xff
Laurence Lundblade68769332024-11-03 13:09:20 -0800856 *
857 * This outputs the big number a byte at a time to be able to operate on
858 * a big number of any length without memory allocation.
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700859 */
860
Laurence Lundblade68769332024-11-03 13:09:20 -0800861 /* Compute the length up front because it goes in the encoded head */
862 bCarry = QCBOREncode_Private_BigNumberCarry(UsefulBuf_Tail(BigNumber, 1));
863 uLen = BigNumber.len;
864 if(bCarry && BigNumber.len > 1 && UsefulBufC_NTH_BYTE(BigNumber, 0) >= 1) {
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700865 uLen--;
866 }
867 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uLen, 0);
868
Laurence Lundblade68769332024-11-03 13:09:20 -0800869 SubString = BigNumber;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700870 bCopiedSomething = false;
871 while(SubString.len) {
Laurence Lundblade68769332024-11-03 13:09:20 -0800872 uByte = UsefulBufC_NTH_BYTE(SubString, 0);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700873 NextSubString = UsefulBuf_Tail(SubString, 1);
Laurence Lundblade68769332024-11-03 13:09:20 -0800874 bCarry = QCBOREncode_Private_BigNumberCarry(NextSubString);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700875 if(bCarry) {
876 uByte--;
877 }
Laurence Lundblade68769332024-11-03 13:09:20 -0800878 /* This avoids all but the last leading zero. See
879 * QCBOREncode_Private_SkipLeadingZeros() */
880 if(bCopiedSomething || NextSubString.len == 0 || uByte != 0) {
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700881 UsefulOutBuf_AppendByte(&(pMe->OutBuf), uByte);
882 bCopiedSomething = true;
883 }
884 SubString = NextSubString;
885 }
886}
887
888
Laurence Lundblade68769332024-11-03 13:09:20 -0800889/**
890 * @brief Convert a negative big number to unsigned int if possible.
891 *
892 * @param[in] BigNumber The negative big number.
893 * @param[out] puInt The converted negative big number.
894 *
895 * @return If conversion was possible, returns @c true.
896 *
897 * The parameters here are unsigned integers, but they always
898 * represent negative numbers.
899 *
900 * Conversion is possible if the big number is greater than -(2^64).
901 * Conversion include offset of 1 for encoding CBOR negative numbers.
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700902 */
Laurence Lundblade68769332024-11-03 13:09:20 -0800903static bool
904QCBOREncode_Private_NegativeBigNumberToUInt(const UsefulBufC BigNumber, uint64_t *puInt)
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700905{
Laurence Lundblade68769332024-11-03 13:09:20 -0800906 bool bIs2exp64;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700907
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700908 static const uint8_t twoExp64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
909
Laurence Lundblade68769332024-11-03 13:09:20 -0800910 bIs2exp64 = ! UsefulBuf_Compare(BigNumber, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(twoExp64));
911
912 if(BigNumber.len > 8 && !bIs2exp64) {
913 return false;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700914 }
915
Laurence Lundblade68769332024-11-03 13:09:20 -0800916 /* Must convert to CBOR type 1, a negative integer */
917 if(bIs2exp64) {
918 /* 2^64 is a 9 byte big number. Since negative numbers are offset
919 * by one in CBOR, it can be encoded as a type 1 negative. The
920 * conversion below won't work because the uInt will overflow
921 * before the subtraction of 1.
922 */
923 *puInt = UINT64_MAX;
924 } else {
925 *puInt = QCBOREncode_Private_BigNumberToUInt(BigNumber);
926 (*puInt)--; /* CBOR's negative offset of 1 */
927 }
928 return true;
929}
930
931
932/**
933 * @brief Remove leading zeros.
934 *
935 * @param[in] BigNumber The negative big number.
936 *
937 * @return Big number with no leading zeros.
938 *
939 * If the big number is all zeros, this returns a big number
940 * that is one zero rather than the empty string.
941 *
942 * 3.4.3 does not explicitly decoders MUST handle the empty string,
943 * but does say decoders MUST handle leading zeros. So Postel's Law
944 * is applied here and 0 is not encoded as an empty string.
945 */
946static UsefulBufC
947QCBOREncode_Private_SkipLeadingZeros(const UsefulBufC BigNumber)
948{
949 UsefulBufC NLZ;
950 NLZ = UsefulBuf_SkipLeading(BigNumber, 0x00);
951
952 /* An all-zero string reduces to one 0, not an empty string. */
953 if(NLZ.len == 0 && BigNumber.len > 0 && UsefulBufC_NTH_BYTE(BigNumber, 0) == 0x00) {
954 NLZ.len++;
955 }
956
957 return NLZ;
958}
959
960
961/*
962 * Public functions for adding a big number. See qcbor/qcbor_encode.h
963 */
964void
965QCBOREncode_AddTBigNumber(QCBOREncodeContext *pMe,
966 const uint8_t uTagRequirement,
967 const bool bNegative,
968 const UsefulBufC BigNumber)
969{
970 uint64_t uInt;
971
972 const UsefulBufC BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
973
974 /* Preferred serialization requires reduction to type 0 and 1 integers */
975 if(bNegative) {
976 if(QCBOREncode_Private_NegativeBigNumberToUInt(BigNumberNLZ, &uInt)) {
977 /* Might be a 65-bit negative; use special add method for such */
978 QCBOREncode_AddNegativeUInt64(pMe, uInt);
979 } else {
980 QCBOREncode_Private_AddTNegativeBigNumber(pMe, uTagRequirement, BigNumberNLZ);
981 }
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700982
983 } else {
Laurence Lundblade68769332024-11-03 13:09:20 -0800984 if(BigNumberNLZ.len <= sizeof(uint64_t)) {
985 QCBOREncode_AddUInt64(pMe, QCBOREncode_Private_BigNumberToUInt(BigNumberNLZ));
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700986 } else {
Laurence Lundblade68769332024-11-03 13:09:20 -0800987 QCBOREncode_AddTBigNumberRaw(pMe, bNegative, uTagRequirement, BigNumberNLZ);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700988 }
989 }
990}
991
992
Laurence Lundblade68769332024-11-03 13:09:20 -0800993/*
994 * Public functions for adding a big number. See qcbor/qcbor_encode.h
995 */
996void
997QCBOREncode_AddTBigNumberNoPreferred(QCBOREncodeContext *pMe,
998 const uint8_t uTagRequirement,
999 const bool bNegative,
1000 const UsefulBufC BigNumber)
1001{
1002 const UsefulBufC BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
1003
1004 if(bNegative) {
1005 QCBOREncode_Private_AddTNegativeBigNumber(pMe, uTagRequirement, BigNumberNLZ);
1006 } else {
1007 QCBOREncode_AddTBigNumberRaw(pMe, false, uTagRequirement, BigNumberNLZ);
1008 }
1009}
1010
1011
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07001012#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001013/**
1014 * @brief Semi-private method to add bigfloats and decimal fractions.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001015 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001016 * @param[in] pMe The encoding context to add the value to.
Laurence Lundblade68769332024-11-03 13:09:20 -08001017 * @param[in] uTagNumber The type 6 tag indicating what this is to be.
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001018 * @param[in] nMantissa The @c int64_t mantissa if it is not a big number.
1019 * @param[in] nExponent The exponent.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001020 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001021 * This outputs either the @ref CBOR_TAG_DECIMAL_FRACTION or
1022 * @ref CBOR_TAG_BIGFLOAT tag. if @c uTag is @ref CBOR_TAG_INVALID64,
1023 * then this outputs the "borrowed" content format.
1024 *
1025 * The tag content output by this is an array with two members, the
1026 * exponent and then the mantissa. The mantissa can be either a big
1027 * number or an @c int64_t.
1028 *
1029 * This implementation cannot output an exponent further from 0 than
1030 * @c INT64_MAX.
1031 *
1032 * To output a mantissa that is between INT64_MAX and UINT64_MAX from 0,
1033 * it must be as a big number.
1034 *
Laurence Lundblade0f143652024-10-06 11:06:19 -07001035 * Typically, QCBOREncode_AddTDecimalFraction(), QCBOREncode_AddTBigFloat(),
1036 * QCBOREncode_AddTDecimalFractionBigNum() or QCBOREncode_AddTBigFloatBigNum()
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001037 * is called instead of this.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001038 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001039void
Laurence Lundblade68769332024-11-03 13:09:20 -08001040QCBOREncode_Private_AddTExpIntMantissa(QCBOREncodeContext *pMe,
1041 const int uTagRequirement,
1042 const uint64_t uTagNumber,
1043 const int64_t nExponent,
1044 const int64_t nMantissa)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001045{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001046 /* This is for encoding either a big float or a decimal fraction,
1047 * both of which are an array of two items, an exponent and a
1048 * mantissa. The difference between the two is that the exponent
1049 * is base-2 for big floats and base-10 for decimal fractions, but
1050 * that has no effect on the code here.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001051 */
Laurence Lundblade68769332024-11-03 13:09:20 -08001052 /* Separate from QCBOREncode_Private_AddTExpBigMantissa() because
1053 * linking QCBOREncode_AddTBigNumber() adds a lot because it
1054 * does preferred serialization of big numbers and the offset of 1
1055 * for CBOR negative numbers.
1056 */
1057 if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
1058 QCBOREncode_AddTagNumber(pMe, uTagNumber);
Laurence Lundbladeae66d3f2020-09-14 18:12:08 -07001059 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001060 QCBOREncode_OpenArray(pMe);
1061 QCBOREncode_AddInt64(pMe, nExponent);
Laurence Lundblade68769332024-11-03 13:09:20 -08001062 QCBOREncode_AddInt64(pMe, nMantissa);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001063 QCBOREncode_CloseArray(pMe);
1064}
Laurence Lundblade68769332024-11-03 13:09:20 -08001065
1066void
1067QCBOREncode_Private_AddTExpBigMantissa(QCBOREncodeContext *pMe,
1068 const int uTagRequirement,
1069 const uint64_t uTagNumber,
1070 const int64_t nExponent,
1071 const UsefulBufC BigNumMantissa,
1072 const bool bBigNumIsNegative)
1073{
1074 /* This is for encoding either a big float or a decimal fraction,
1075 * both of which are an array of two items, an exponent and a
1076 * mantissa. The difference between the two is that the exponent
1077 * is base-2 for big floats and base-10 for decimal fractions, but
1078 * that has no effect on the code here.
1079 */
1080 if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
1081 QCBOREncode_AddTag(pMe, uTagNumber);
1082 }
1083 QCBOREncode_OpenArray(pMe);
1084 QCBOREncode_AddInt64(pMe, nExponent);
1085 QCBOREncode_AddTBigNumber(pMe, QCBOR_ENCODE_AS_TAG, bBigNumIsNegative, BigNumMantissa);
1086 QCBOREncode_CloseArray(pMe);
1087}
1088
1089
1090void
1091QCBOREncode_Private_AddTExpBigMantissaRaw(QCBOREncodeContext *pMe,
1092 const int uTagRequirement,
1093 const uint64_t uTagNumber,
1094 const int64_t nExponent,
1095 const UsefulBufC BigNumMantissa,
1096 const bool bBigNumIsNegative)
1097{
1098 /* This is for encoding either a big float or a decimal fraction,
1099 * both of which are an array of two items, an exponent and a
1100 * mantissa. The difference between the two is that the exponent
1101 * is base-2 for big floats and base-10 for decimal fractions, but
1102 * that has no effect on the code here.
1103 */
1104 /* Separate from QCBOREncode_Private_AddTExpBigMantissa() because
1105 * linking QCBOREncode_AddTBigNumber() adds a lot because it
1106 * does preferred serialization of big numbers and the offset of 1
1107 * for CBOR negative numbers.
1108 */
1109 if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
1110 QCBOREncode_AddTag(pMe, uTagNumber);
1111 }
1112 QCBOREncode_OpenArray(pMe);
1113 QCBOREncode_AddInt64(pMe, nExponent);
1114 QCBOREncode_AddTBigNumberRaw(pMe, QCBOR_ENCODE_AS_TAG, bBigNumIsNegative, BigNumMantissa);
1115 QCBOREncode_CloseArray(pMe);
1116}
1117
Laurence Lundbladed253e412024-08-21 11:02:56 -07001118#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001119
1120
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001121/**
1122 * @brief Semi-private method to open a map, array or bstr-wrapped CBOR
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001123 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001124 * @param[in] pMe The context to add to.
1125 * @param[in] uMajorType The major CBOR type to close
1126 *
1127 * Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
1128 * QCBOREncode_BstrWrap() instead of this.
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001129 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001130void
1131QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pMe,
1132 const uint8_t uMajorType)
Laurence Lundblade067035b2018-11-28 17:35:25 -08001133{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001134 /* Add one item to the nesting level we are in for the new map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001135 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladed39cd392019-01-11 18:17:38 -08001136
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001137 /* The offset where the length of an array or map will get written
1138 * is stored in a uint32_t, not a size_t to keep stack usage
1139 * smaller. This checks to be sure there is no wrap around when
1140 * recording the offset. Note that on 64-bit machines CBOR larger
1141 * than 4GB can be encoded as long as no array/map offsets occur
1142 * past the 4GB mark, but the public interface says that the
1143 * maximum is 4GB to keep the discussion simpler.
1144 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001145 size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundbladed39cd392019-01-11 18:17:38 -08001146
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001147 /* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
1148 * code can run on a 32-bit machine and tests can pass on a 32-bit
1149 * machine. If it was exactly UINT32_MAX, then this code would not
1150 * compile or run on a 32-bit machine and an #ifdef or some machine
1151 * size detection would be needed reducing portability.
1152 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001153 if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001154 pMe->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001155
1156 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001157 /* Increase nesting level because this is a map or array. Cast
1158 * from size_t to uin32_t is safe because of check above.
1159 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001160 pMe->uError = Nesting_Increase(&(pMe->nesting), uMajorType, (uint32_t)uEndPosition);
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -08001161 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001162}
1163
Laurence Lundblade59289e52019-12-30 13:44:37 -08001164
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001165#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001166/**
1167 * @brief Semi-private method to open a map, array with indefinite length
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001168 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001169 * @param[in] pMe The context to add to.
1170 * @param[in] uMajorType The major CBOR type to close
1171 *
1172 * Call QCBOREncode_OpenArrayIndefiniteLength() or
1173 * QCBOREncode_OpenMapIndefiniteLength() instead of this.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001174 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001175void
1176QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1177 const uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001178{
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08001179#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
1180 if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
1181 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
1182 return;
1183 }
1184#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001185 /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001186 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, 0, 0);
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001187
1188 /* Call the definite-length opener just to do the bookkeeping for
1189 * nesting. It will record the position of the opening item in the
1190 * encoded output but this is not used when closing this open.
1191 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001192 QCBOREncode_Private_OpenMapOrArray(pMe, uMajorType);
Jan Jongboom4a93a662019-07-25 08:44:58 +02001193}
Laurence Lundbladed253e412024-08-21 11:02:56 -07001194#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001195
1196
1197/**
1198 * @brief Check for errors when decreasing nesting.
1199 *
1200 * @param pMe QCBOR encoding context.
1201 * @param uMajorType The major type of the nesting.
1202 *
1203 * Check that there is no previous error, that there is actually some
1204 * nesting and that the major type of the opening of the nesting
1205 * matches the major type of the nesting being closed.
1206 *
1207 * This is called when closing maps, arrays, byte string wrapping and
1208 * open/close of byte strings.
1209 */
1210static bool
1211QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext *pMe,
1212 const uint8_t uMajorType)
1213{
1214#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
1215 if(pMe->uError != QCBOR_SUCCESS) {
1216 return true;
1217 }
1218
1219 if(!Nesting_IsInNest(&(pMe->nesting))) {
1220 pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
1221 return true;
1222 }
1223
1224 if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
1225 pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
1226 return true;
1227 }
1228
Laurence Lundbladed253e412024-08-21 11:02:56 -07001229#else /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001230 /* None of these checks are performed if the encode guards are
1231 * turned off as they all relate to correct calling.
1232 *
1233 * Turning off all these checks does not turn off any checking for
1234 * buffer overflows or pointer issues.
1235 */
1236
1237 (void)uMajorType;
1238 (void)pMe;
Laurence Lundbladed253e412024-08-21 11:02:56 -07001239#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001240
1241 return false;
1242}
1243
1244
1245/**
Laurence Lundbladed253e412024-08-21 11:02:56 -07001246 * @brief Insert the CBOR head for a map, array or wrapped bstr.
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001247 *
1248 * @param pMe QCBOR encoding context.
1249 * @param uMajorType One of CBOR_MAJOR_TYPE_XXXX.
1250 * @param uLen The length of the data item.
1251 *
1252 * When an array, map or bstr was opened, nothing was done but note
1253 * the position. This function goes back to that position and inserts
1254 * the CBOR Head with the major type and length.
1255 */
1256static void
1257QCBOREncode_Private_CloseAggregate(QCBOREncodeContext *pMe,
1258 uint8_t uMajorType,
1259 size_t uLen)
1260{
1261 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
1262 return;
1263 }
1264
1265 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
1266 uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
1267 }
1268
1269 /* A stack buffer large enough for a CBOR head (9 bytes) */
1270 UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
1271
1272 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
1273 uMajorType,
1274 0,
1275 uLen);
1276
1277 /* No check for EncodedHead == NULLUsefulBufC is performed here to
1278 * save object code. It is very clear that pBufferForEncodedHead is
1279 * the correct size. If EncodedHead == NULLUsefulBufC then
1280 * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
1281 * security hole introduced.
1282 */
1283 UsefulOutBuf_InsertUsefulBuf(&(pMe->OutBuf),
1284 EncodedHead,
1285 Nesting_GetStartPos(&(pMe->nesting)));
1286
1287 Nesting_Decrease(&(pMe->nesting));
1288}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001289
Laurence Lundbladeee851742020-01-08 08:37:05 -08001290
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001291/**
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08001292 * @brief Semi-private method to close a map, array or bstr wrapped CBOR.
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001293 *
1294 * @param[in] pMe The context to add to.
1295 * @param[in] uMajorType The major CBOR type to close.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001296 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001297void
1298QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pMe,
1299 const uint8_t uMajorType)
Laurence Lundbladea954db92018-09-28 19:27:31 -07001300{
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001301 QCBOREncode_Private_CloseAggregate(pMe, uMajorType, Nesting_GetCount(&(pMe->nesting)));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001302}
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001303
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001304
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08001305/**
1306 * @brief Private method to close a map without sorting.
1307 *
1308 * @param[in] pMe The encode context with map to close.
1309 *
1310 * See QCBOREncode_SerializationCDE() implemention for explantion for why
1311 * this exists in this form.
1312 */
1313static void
1314QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe)
1315{
1316 QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
1317}
1318
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001319
1320/**
1321 * @brief Decode a CBOR item head.
1322 *
1323 * @param[in] pUInBuf UsefulInputBuf to read from.
1324 * @param[out] pnMajorType Major type of decoded head.
1325 * @param[out] puArgument Argument of decoded head.
1326 * @param[out] pnAdditionalInfo Additional info from decoded head.
1327 *
1328 * @return SUCCESS if a head was decoded
1329 * HIT_END if there were not enough bytes to decode a head
1330 * UNSUPPORTED if the decoded item is not one that is supported
1331 *
1332 * This is copied from qcbor_decode.c rather than referenced. This
1333 * makes the core decoder 60 bytes smaller because it gets inlined.
1334 * It would not get inlined if it was referenced. It is important to
1335 * make the core decoder as small as possible. The copy here does make
1336 * map sorting 200 bytes bigger, but map sorting is rarely used in
1337 * environments that need small object code. It would also make
1338 * qcbor_encode.c depend on qcbor_decode.c
1339 *
1340 * This is also super stable and tested. It implements the very
1341 * well-defined part of CBOR that will never change. So this won't
1342 * change.
1343 */
1344static QCBORError
1345QCBOREncodePriv_DecodeHead(UsefulInputBuf *pUInBuf,
1346 int *pnMajorType,
1347 uint64_t *puArgument,
1348 int *pnAdditionalInfo)
1349{
1350 QCBORError uReturn;
1351
1352 /* Get the initial byte that every CBOR data item has and break it
1353 * down. */
1354 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
1355 const int nTmpMajorType = nInitialByte >> 5;
1356 const int nAdditionalInfo = nInitialByte & 0x1f;
1357
1358 /* Where the argument accumulates */
1359 uint64_t uArgument;
1360
1361 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
1362 /* Need to get 1,2,4 or 8 additional argument bytes. Map
1363 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
1364 */
1365 static const uint8_t aIterate[] = {1,2,4,8};
1366
1367 /* Loop getting all the bytes in the argument */
1368 uArgument = 0;
1369 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
1370 /* This shift and add gives the endian conversion. */
1371 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
1372 }
1373 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
1374 /* The reserved and thus-far unused additional info values */
1375 uReturn = QCBOR_ERR_UNSUPPORTED;
1376 goto Done;
1377 } else {
1378 /* Less than 24, additional info is argument or 31, an
1379 * indefinite-length. No more bytes to get.
1380 */
1381 uArgument = (uint64_t)nAdditionalInfo;
1382 }
1383
1384 if(UsefulInputBuf_GetError(pUInBuf)) {
1385 uReturn = QCBOR_ERR_HIT_END;
1386 goto Done;
1387 }
1388
1389 /* All successful if arrived here. */
1390 uReturn = QCBOR_SUCCESS;
1391 *pnMajorType = nTmpMajorType;
1392 *puArgument = uArgument;
1393 *pnAdditionalInfo = nAdditionalInfo;
1394
1395Done:
1396 return uReturn;
1397}
1398
1399
1400/**
1401 * @brief Consume the next item from a UsefulInputBuf.
1402 *
1403 * @param[in] pInBuf UsefulInputBuf from which to consume item.
1404 *
1405 * Recursive, but stack usage is light and encoding depth limit
1406 */
1407static QCBORError
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001408QCBOR_Private_ConsumeNext(UsefulInputBuf *pInBuf)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001409{
1410 int nMajor;
1411 uint64_t uArgument;
1412 int nAdditional;
1413 uint16_t uItemCount;
1414 uint16_t uMul;
1415 uint16_t i;
1416 QCBORError uCBORError;
1417
1418 uCBORError = QCBOREncodePriv_DecodeHead(pInBuf, &nMajor, &uArgument, &nAdditional);
1419 if(uCBORError != QCBOR_SUCCESS) {
1420 return uCBORError;
1421 }
1422
1423 uMul = 1;
1424
1425 switch(nMajor) {
1426 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1427 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1428 break;
1429
1430 case CBOR_MAJOR_TYPE_SIMPLE:
1431 return uArgument == CBOR_SIMPLE_BREAK ? 1 : 0;
1432 break;
1433
1434 case CBOR_MAJOR_TYPE_BYTE_STRING:
1435 case CBOR_MAJOR_TYPE_TEXT_STRING:
1436 if(nAdditional == LEN_IS_INDEFINITE) {
1437 /* Segments of indefinite length */
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001438 while(QCBOR_Private_ConsumeNext(pInBuf) == 0);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001439 }
1440 (void)UsefulInputBuf_GetBytes(pInBuf, uArgument);
1441 break;
1442
1443 case CBOR_MAJOR_TYPE_TAG:
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001444 QCBOR_Private_ConsumeNext(pInBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001445 break;
1446
1447 case CBOR_MAJOR_TYPE_MAP:
1448 uMul = 2;
1449 /* Fallthrough */
1450 case CBOR_MAJOR_TYPE_ARRAY:
1451 uItemCount = (uint16_t)uArgument * uMul;
1452 if(nAdditional == LEN_IS_INDEFINITE) {
1453 uItemCount = UINT16_MAX;
1454 }
1455 for(i = uItemCount; i > 0; i--) {
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001456 if(QCBOR_Private_ConsumeNext(pInBuf)) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001457 /* End of indefinite length */
1458 break;
1459 }
1460 }
1461 break;
1462 }
1463
1464 return QCBOR_SUCCESS;
1465}
1466
1467
1468/**
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001469 * @brief Decoded next item to get its lengths.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001470 *
1471 * Decode the next item in map no matter what type it is. It works
1472 * recursively when an item is a map or array It returns offset just
1473 * past the item decoded or zero there are no more items in the output
1474 * buffer.
1475 *
1476 * This doesn't distinguish between end of the input and an error
1477 * because it is used to decode stuff we encoded into a buffer, not
1478 * stuff that came in from outside. We still want a check for safety
1479 * in case of bugs here, but it is OK to report end of input on error.
1480 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001481struct ItemLens {
1482 uint32_t uLabelLen;
1483 uint32_t uItemLen;
1484};
1485
1486static struct ItemLens
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001487QCBOREncode_Private_DecodeNextInMap(QCBOREncodeContext *pMe, uint32_t uStart)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001488{
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001489 UsefulInputBuf InBuf;
1490 UsefulBufC EncodedMapBytes;
1491 QCBORError uCBORError;
1492 struct ItemLens Result;
1493
1494 Result.uLabelLen = 0;
1495 Result.uItemLen = 0;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001496
1497 EncodedMapBytes = UsefulOutBuf_OutUBufOffset(&(pMe->OutBuf), uStart);
1498 if(UsefulBuf_IsNULLC(EncodedMapBytes)) {
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001499 return Result;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001500 }
1501
1502 UsefulInputBuf_Init(&InBuf, EncodedMapBytes);
1503
1504 /* This is always used on maps, so consume two, the label and the value */
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001505 uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001506 if(uCBORError) {
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001507 return Result;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001508 }
1509
1510 /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001511 Result.uLabelLen = (uint32_t)UsefulInputBuf_Tell(&InBuf);
1512
1513 uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
1514 if(uCBORError) {
1515 Result.uLabelLen = 0;
1516 return Result;
1517 }
1518
1519 Result.uItemLen = (uint32_t)UsefulInputBuf_Tell(&InBuf);
1520
1521 /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
1522 return Result;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001523}
1524
1525
1526/**
1527 * @brief Sort items lexographically by encoded labels.
1528 *
1529 * @param[in] pMe Encoding context.
1530 * @param[in] uStart Offset in outbuf of first item for sorting.
1531 *
1532 * This reaches into the UsefulOutBuf in the encoding context and
1533 * sorts encoded CBOR items. The byte offset start of the items is at
1534 * @c uStart and it goes to the end of valid bytes in the
1535 * UsefulOutBuf.
1536 */
1537static void
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001538QCBOREncode_Private_SortMap(QCBOREncodeContext *pMe, uint32_t uStart)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001539{
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001540 bool bSwapped;
1541 int nComparison;
1542 uint32_t uStart1;
1543 uint32_t uStart2;
1544 struct ItemLens Lens1;
1545 struct ItemLens Lens2;
1546
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001547
1548 if(pMe->uError != QCBOR_SUCCESS) {
1549 return;
1550 }
1551
1552 /* Bubble sort because the sizes of all the items are not the
1553 * same. It works with adjacent pairs so the swap is not too
1554 * difficult even though sizes are different.
1555 *
1556 * While bubble sort is n-squared, it seems OK here because n will
1557 * usually be small and the comparison and swap functions aren't
1558 * too CPU intensive.
1559 *
1560 * Another approach would be to have an array of offsets to the
1561 * items. However this requires memory allocation and the swap
1562 * operation for quick sort or such is complicated because the item
1563 * sizes are not the same and overlap may occur in the bytes being
1564 * swapped.
1565 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001566 do { /* Loop until nothing was swapped */
1567 Lens1 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart);
1568 if(Lens1.uLabelLen == 0) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001569 /* It's an empty map. Nothing to do. */
1570 break;
1571 }
1572 uStart1 = uStart;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001573 uStart2 = uStart1 + Lens1.uItemLen;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001574 bSwapped = false;
1575
1576 while(1) {
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001577 Lens2 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart2);
1578 if(Lens2.uLabelLen == 0) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001579 break;
1580 }
1581
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001582 nComparison = UsefulOutBuf_Compare(&(pMe->OutBuf),
1583 uStart1, Lens1.uLabelLen,
1584 uStart2, Lens2.uLabelLen);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001585 if(nComparison < 0) {
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001586 UsefulOutBuf_Swap(&(pMe->OutBuf), uStart1, uStart2, uStart2 + Lens2.uItemLen);
1587 uStart1 = uStart1 + Lens2.uItemLen; /* item 2 now in position of item 1 */
1588 /* Lens1 is still valid as Lens1 for the next loop */
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001589 bSwapped = true;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001590 } else if(nComparison > 0) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001591 uStart1 = uStart2;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001592 Lens1 = Lens2;
1593 } else /* nComparison == 0 */ {
1594 pMe->uError = QCBOR_ERR_DUPLICATE_LABEL;
1595 return;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001596 }
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001597 uStart2 = uStart2 + Lens2.uItemLen;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001598 }
1599 } while(bSwapped);
1600}
1601
1602
1603/*
1604 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1605 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001606void
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001607QCBOREncode_CloseAndSortMap(QCBOREncodeContext *pMe)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001608{
1609 uint32_t uStart;
1610
1611 /* The Header for the map we are about to sort hasn't been
1612 * inserted yet, so uStart is the position of the first item
1613 * and the end out the UsefulOutBuf data is the end of the
1614 * items we are about to sort.
1615 */
1616 uStart = Nesting_GetStartPos(&(pMe->nesting));
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001617 QCBOREncode_Private_SortMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001618
Laurence Lundblade70fc1252024-05-31 10:57:28 -07001619 QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_MAP, Nesting_GetCount(&(pMe->nesting)));
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001620}
1621
1622
Laurence Lundbladed3f07842024-06-19 13:05:07 -07001623#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001624/*
1625 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1626 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001627void
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001628QCBOREncode_CloseAndSortMapIndef(QCBOREncodeContext *pMe)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001629{
1630 uint32_t uStart;
1631
1632 uStart = Nesting_GetStartPos(&(pMe->nesting));
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001633 QCBOREncode_Private_SortMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001634
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001635 QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001636}
Laurence Lundbladed3f07842024-06-19 13:05:07 -07001637#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001638
1639
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001640/*
Laurence Lundbladed253e412024-08-21 11:02:56 -07001641 * Public function for closing bstr wrapping. See qcbor/qcbor_encode.h
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001642 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001643void
1644QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pMe,
1645 const bool bIncludeCBORHead,
1646 UsefulBufC *pWrappedCBOR)
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001647{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001648 const size_t uInsertPosition = Nesting_GetStartPos(&(pMe->nesting));
1649 const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001650
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001651 /* This subtraction can't go negative because the UsefulOutBuf
1652 * always only grows and never shrinks. UsefulOutBut itself also
1653 * has defenses such that it won't write where it should not even
1654 * if given incorrect input lengths.
1655 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001656 const size_t uBstrLen = uEndPosition - uInsertPosition;
1657
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001658 /* Actually insert */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001659 QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001660
1661 if(pWrappedCBOR) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001662 /* Return pointer and length to the enclosed encoded CBOR. The
1663 * intended use is for it to be hashed (e.g., SHA-256) in a COSE
1664 * implementation. This must be used right away, as the pointer
1665 * and length go invalid on any subsequent calls to this
1666 * function because there might be calls to
1667 * InsertEncodedTypeAndNumber() that slides data to the right.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001668 */
1669 size_t uStartOfNew = uInsertPosition;
1670 if(!bIncludeCBORHead) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001671 /* Skip over the CBOR head to just get the inserted bstr */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001672 const size_t uNewEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001673 uStartOfNew += uNewEndPosition - uEndPosition;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001674 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001675 const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001676 *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uStartOfNew);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001677 }
1678}
1679
Laurence Lundbladeee851742020-01-08 08:37:05 -08001680
Jan Jongboom4a93a662019-07-25 08:44:58 +02001681/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001682 * Public function for canceling a bstr wrap. See qcbor/qcbor_encode.h
1683 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001684void
1685QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pMe)
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001686{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001687 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, CBOR_MAJOR_TYPE_BYTE_STRING)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001688 return;
1689 }
1690
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001691#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001692 const size_t uCurrent = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
1693 if(pMe->nesting.pCurrentNesting->uStart != uCurrent) {
1694 pMe->uError = QCBOR_ERR_CANNOT_CANCEL;
1695 return;
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001696 }
1697 /* QCBOREncode_CancelBstrWrap() can't correctly undo
Laurence Lundblade0f143652024-10-06 11:06:19 -07001698 * QCBOREncode_BstrWrapInMapSZ() or QCBOREncode_BstrWrapInMapN(). It
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001699 * can't undo the labels they add. It also doesn't catch the error
1700 * of using it this way. QCBOREncode_CancelBstrWrap() is used
1701 * infrequently and the the result is incorrect CBOR, not a
1702 * security hole, so no extra code or state is added to handle this
1703 * condition.
1704 */
Laurence Lundbladed253e412024-08-21 11:02:56 -07001705#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001706
1707 Nesting_Decrease(&(pMe->nesting));
1708 Nesting_Decrement(&(pMe->nesting));
1709}
1710
1711
1712/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001713 * Public function for opening a byte string. See qcbor/qcbor_encode.h
1714 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001715void
1716QCBOREncode_OpenBytes(QCBOREncodeContext *pMe, UsefulBuf *pPlace)
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001717{
1718 *pPlace = UsefulOutBuf_GetOutPlace(&(pMe->OutBuf));
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001719#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Paul Liétar79789772022-07-26 20:33:18 +01001720 uint8_t uMajorType = Nesting_GetMajorType(&(pMe->nesting));
1721 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
Laurence Lundblade716d10c2024-02-07 16:54:42 -08001722 /* It's OK to nest a byte string in any type but
1723 * another open byte string. */
Paul Liétar79789772022-07-26 20:33:18 +01001724 pMe->uError = QCBOR_ERR_OPEN_BYTE_STRING;
1725 return;
1726 }
Laurence Lundbladed253e412024-08-21 11:02:56 -07001727#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001728
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001729 QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001730}
1731
1732
1733/*
1734 * Public function for closing a byte string. See qcbor/qcbor_encode.h
1735 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001736void
1737QCBOREncode_CloseBytes(QCBOREncodeContext *pMe, const size_t uAmount)
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001738{
1739 UsefulOutBuf_Advance(&(pMe->OutBuf), uAmount);
1740 if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
1741 /* Advance too far. Normal off-end error handling in effect here. */
1742 return;
1743 }
1744
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001745 QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001746}
1747
1748
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001749#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001750/**
1751 * @brief Semi-private method to close a map, array with indefinite length
1752 *
1753 * @param[in] pMe The context to add to.
1754 * @param[in] uMajorType The major CBOR type to close.
1755 *
1756 * Call QCBOREncode_CloseArrayIndefiniteLength() or
1757 * QCBOREncode_CloseMapIndefiniteLength() instead of this.
Jan Jongboom4a93a662019-07-25 08:44:58 +02001758 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001759void
1760QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1761 const uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001762{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001763 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001764 return;
Jan Jongboom4a93a662019-07-25 08:44:58 +02001765 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001766
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001767 /* Append the break marker (0xff for both arrays and maps) */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001768 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001769 Nesting_Decrease(&(pMe->nesting));
Jan Jongboom4a93a662019-07-25 08:44:58 +02001770}
Laurence Lundbladed253e412024-08-21 11:02:56 -07001771#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Jan Jongboom4a93a662019-07-25 08:44:58 +02001772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001773
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001774/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001775 * Public function to finish and get the encoded result. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001776 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001777QCBORError
1778QCBOREncode_Finish(QCBOREncodeContext *pMe, UsefulBufC *pEncodedCBOR)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001779{
Laurence Lundbladef2f0c3f2024-04-12 13:01:54 -07001780 if(QCBOREncode_GetErrorState(pMe) != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001781 goto Done;
Laurence Lundblade067035b2018-11-28 17:35:25 -08001782 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001783
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001784#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001785 if(Nesting_IsInNest(&(pMe->nesting))) {
Laurence Lundbladef2f0c3f2024-04-12 13:01:54 -07001786 pMe->uError = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001787 goto Done;
1788 }
Laurence Lundbladed253e412024-08-21 11:02:56 -07001789#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001790
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001791 *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001792
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001793Done:
Laurence Lundbladef2f0c3f2024-04-12 13:01:54 -07001794 return pMe->uError;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001795}
1796
Laurence Lundblade0595e932018-11-02 22:22:47 +07001797
Laurence Lundblade067035b2018-11-28 17:35:25 -08001798/*
Laurence Lundbladed253e412024-08-21 11:02:56 -07001799 * Public function to get size of the encoded result. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -08001800 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001801QCBORError
1802QCBOREncode_FinishGetSize(QCBOREncodeContext *pMe, size_t *puEncodedLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001803{
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001804 UsefulBufC Enc;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001805
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001806 QCBORError nReturn = QCBOREncode_Finish(pMe, &Enc);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001807
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001808 if(nReturn == QCBOR_SUCCESS) {
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001809 *puEncodedLen = Enc.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001810 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001811
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001812 return nReturn;
1813}
Laurence Lundbladee2226742024-08-16 10:50:23 -07001814
1815
1816/*
1817 * Public function to get substring of encoded-so-far. See qcbor/qcbor_encode.h
1818 */
1819UsefulBufC
1820QCBOREncode_SubString(QCBOREncodeContext *pMe, const size_t uStart)
1821{
1822 if(pMe->uError) {
1823 return NULLUsefulBufC;
1824 }
1825
1826 /* An attempt was made to detect usage errors by comparing uStart
1827 * to offsets of open arrays and maps in pMe->nesting, but it is
1828 * not possible because there's not enough information in just
1829 * the offset. It's not possible to known if Tell() was called before
1830 * or after an Open(). To detect this error, the nesting level
1831 * would also need to be known. This is not frequently used, so
1832 * it is not worth adding this complexity.
1833 */
1834
1835 const size_t uEnd = QCBOREncode_Tell(pMe);
1836
1837 return UsefulOutBuf_SubString(&(pMe->OutBuf), uStart, uEnd - uStart);
1838}