blob: a6d4d22f7d714519df351147705d3af77ec14c5b [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() */
Laurence Lundblade82634b62024-11-20 22:37:45 -0800256void
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800257QCBOREncode_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
Laurence Lundblade82634b62024-11-20 22:37:45 -0800557#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
558 if(pMe->uConfigFlags & QCBOR_ENCODE_CONFIG_DISALLOW_INDEFINITE_LENGTHS &&
559 uMajorType & QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
560 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
561 return;
562 }
563#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
564
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000565 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
566 uMajorType,
567 uMinLen,
568 uArgument);
569
570 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800571 * save object code. It is very clear that pBufferForEncodedHead is
572 * the correct size. If EncodedHead == NULLUsefulBufC then
573 * UsefulOutBuf_AppendUsefulBuf() will do nothing so there is no
574 * security hole introduced.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000575 */
576
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700577 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), EncodedHead);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700579 if(!(uMajorType & QCBOR_INDEFINITE_LEN_TYPE_MODIFIER || uMajorType == CBOR_MAJOR_TYPE_TAG)) {
580 /* Don't increment the map count for tag or break because that is
581 * not needed. Don't do it for indefinite-length arrays and maps
582 * because it is done elsewhere. This is never called for definite-length
583 * arrays and maps.
584 */
585 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700586 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700587}
588
Laurence Lundblade56230d12018-11-01 11:14:51 +0700589
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700590/*
Laurence Lundbladed253e412024-08-21 11:02:56 -0700591 * Public function for adding signed integers. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -0800592 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700593void
594QCBOREncode_AddInt64(QCBOREncodeContext *pMe, const int64_t nNum)
Laurence Lundblade067035b2018-11-28 17:35:25 -0800595{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800596 uint8_t uMajorType;
597 uint64_t uValue;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800598
599 if(nNum < 0) {
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700600 /* In CBOR -1 encodes as 0x00 with major type negative int.
601 * First add one as a signed integer because that will not
Laurence Lundblade2d493002024-02-01 11:09:17 -0700602 * overflow. Then change the sign as needed for encoding (the
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700603 * opposite order, changing the sign and subtracting, can cause
Laurence Lundblade2d493002024-02-01 11:09:17 -0700604 * an overflow when encoding INT64_MIN). */
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700605 int64_t nTmp = nNum + 1;
606 uValue = (uint64_t)-nTmp;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800607 uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
608 } else {
609 uValue = (uint64_t)nNum;
610 uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
611 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700612 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uValue, 0);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800613}
614
615
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700616/**
617 * @brief Semi-private method to add a buffer full of bytes to encoded output.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800618 *
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700619 * @param[in] pMe The encoding context to add the string to.
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700620 * @param[in] uMajorType The CBOR major type of the bytes.
621 * @param[in] Bytes The bytes to add.
622 *
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700623 * Called by inline functions to add text and byte strings.
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700624 *
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700625 * (This used to support QCBOREncode_AddEncoded() and
626 * QCBOREncode_AddBytesLenOnly(), but that was pulled out to make this
627 * smaller. This is one of the most used methods and they are some of
628 * the least used).
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700630void
631QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pMe,
632 const uint8_t uMajorType,
633 const UsefulBufC Bytes)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634{
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700635 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, Bytes.len, 0);
Laurence Lundblade15b93d42024-02-07 17:39:10 -0800636 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Bytes);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700637}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638
Laurence Lundbladecafcfe12018-10-31 21:59:50 +0700639
Laurence Lundblade55a24832018-10-30 04:35:08 +0700640/*
Laurence Lundbladed253e412024-08-21 11:02:56 -0700641 * Public function for adding raw encoded CBOR. See qcbor/qcbor_encode.h
Laurence Lundblade55a24832018-10-30 04:35:08 +0700642 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700643void
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700644QCBOREncode_AddEncoded(QCBOREncodeContext *pMe, const UsefulBufC Encoded)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700645{
Laurence Lundbladecbd7d132024-05-19 11:11:22 -0700646 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Encoded);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700647 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700648}
649
650
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700651#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade8d9e0cd2024-05-25 18:12:19 -0700652/**
653 * @brief Semi-private method to add a double using preferred encoding.
654 *
655 * @param[in] pMe The encode context.
656 * @param[in] dNum The double to add.
657 *
658 * This converts the double to a float or half-precision if it can be done
659 * without a loss of precision. See QCBOREncode_AddDouble().
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700660 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700661void
Laurence Lundblade70fc1252024-05-31 10:57:28 -0700662QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, double dNum)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700663{
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800664 IEEE754_union FloatResult;
665 bool bNoNaNPayload;
666 struct IEEE754_ToInt IntResult;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700667 uint64_t uNegValue;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700668
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800669#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade82634b62024-11-20 22:37:45 -0800670 if(IEEE754_DoubleHasNaNPayload(dNum) && !(pMe->uConfigFlags & QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800671 pMe->uError = QCBOR_ERR_NOT_ALLOWED;
672 return;
673 }
674#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
675
Laurence Lundblade82634b62024-11-20 22:37:45 -0800676 if(pMe->uConfigFlags & QCBOR_ENCODE_CONFIG_FLOAT_REDUCTION) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800677 IntResult = IEEE754_DoubleToInt(dNum);
678 switch(IntResult.type) {
679 case IEEE754_ToInt_IS_INT:
680 QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
681 return;
682 case IEEE754_ToInt_IS_UINT:
683 QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
684 return;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700685 case IEEE754_ToInt_IS_65BIT_NEG:
686 {
687 if(IntResult.integer.un_signed == 0) {
688 uNegValue = UINT64_MAX;
689 } else {
690 uNegValue = IntResult.integer.un_signed-1;
691 }
692 QCBOREncode_AddNegativeUInt64(pMe, uNegValue);
693 }
694 return;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800695 case IEEE754_ToInt_NaN:
696 dNum = NAN;
697 bNoNaNPayload = true;
698 break;
699 case IEEE754_ToInt_NO_CONVERSION:
700 bNoNaNPayload = true;
701 }
702 } else {
703 bNoNaNPayload = false;
704 }
705
706 FloatResult = IEEE754_DoubleToSmaller(dNum, true, bNoNaNPayload);
707
708 QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700709}
Laurence Lundblade9682a532020-06-06 18:33:04 -0700710
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700711
Laurence Lundblade8d9e0cd2024-05-25 18:12:19 -0700712/**
713 * @brief Semi-private method to add a float using preferred encoding.
714 *
715 * @param[in] pMe The encode context.
716 * @param[in] fNum The float to add.
717 *
718 * This converts the float to a half-precision if it can be done
719 * without a loss of precision. See QCBOREncode_AddFloat().
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800720 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700721void
Laurence Lundblade70fc1252024-05-31 10:57:28 -0700722QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, float fNum)
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700723{
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800724 IEEE754_union FloatResult;
725 bool bNoNaNPayload;
726 struct IEEE754_ToInt IntResult;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700727 uint64_t uNegValue;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700728
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800729#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade82634b62024-11-20 22:37:45 -0800730 if(IEEE754_SingleHasNaNPayload(fNum) && !(pMe->uConfigFlags & QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800731 pMe->uError = QCBOR_ERR_NOT_ALLOWED;
732 return;
733 }
734#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
735
Laurence Lundblade82634b62024-11-20 22:37:45 -0800736 if(pMe->uConfigFlags & QCBOR_ENCODE_CONFIG_FLOAT_REDUCTION) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800737 IntResult = IEEE754_SingleToInt(fNum);
738 switch(IntResult.type) {
739 case IEEE754_ToInt_IS_INT:
740 QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
741 return;
742 case IEEE754_ToInt_IS_UINT:
743 QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
744 return;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700745 case IEEE754_ToInt_IS_65BIT_NEG:
746 {
747 if(IntResult.integer.un_signed == 0) {
748 uNegValue = UINT64_MAX;
749 } else {
750 uNegValue = IntResult.integer.un_signed-1;
751 }
752 QCBOREncode_AddNegativeUInt64(pMe, uNegValue);
753 }
754 return;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800755 case IEEE754_ToInt_NaN:
756 fNum = NAN;
757 bNoNaNPayload = true;
758 break;
759 case IEEE754_ToInt_NO_CONVERSION:
760 bNoNaNPayload = true;
761 }
762 } else {
763 bNoNaNPayload = false;
764 }
765
766 FloatResult = IEEE754_SingleToHalf(fNum, bNoNaNPayload);
767
768 QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800769}
Laurence Lundbladed253e412024-08-21 11:02:56 -0700770#endif /* ! QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800771
Laurence Lundblade067035b2018-11-28 17:35:25 -0800772
773
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700774
Laurence Lundblade68769332024-11-03 13:09:20 -0800775/**
776 * @brief Convert a big number to unsigned integer.
777 *
778 * @param[in] BigNumber Big number to convert.
779 *
780 * @return Converted unsigned.
781 *
782 * The big number must be less than 8 bytes long.
783 **/
784static uint64_t
785QCBOREncode_Private_BigNumberToUInt(const UsefulBufC BigNumber)
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700786{
Laurence Lundblade68769332024-11-03 13:09:20 -0800787 uint64_t uInt;
788 size_t uIndex;
789
790 uInt = 0;
791 for(uIndex = 0; uIndex < BigNumber.len; uIndex++) {
792 uInt = (uInt << 8) + UsefulBufC_NTH_BYTE(BigNumber, uIndex);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700793 }
Laurence Lundblade68769332024-11-03 13:09:20 -0800794
795 return uInt;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700796}
797
798
Laurence Lundblade68769332024-11-03 13:09:20 -0800799/**
800 * @brief Is there a carry when you subtract 1 from the BigNumber.
801 *
802 * @param[in] BigNumber Big number to check for carry.
803 *
804 * @return If there is a carry, \c true.
805 *
Laurence Lundblade05369de2024-11-17 17:00:28 -0800806 * If this returns @c true, then @c BigNumber - 1 is one byte shorter
807 * than @c BigNumber.
Laurence Lundblade68769332024-11-03 13:09:20 -0800808 **/
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700809static bool
Laurence Lundblade68769332024-11-03 13:09:20 -0800810QCBOREncode_Private_BigNumberCarry(const UsefulBufC BigNumber)
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700811{
812 bool bCarry;
813 UsefulBufC SubBigNum;
814
Laurence Lundblade68769332024-11-03 13:09:20 -0800815 // Improvement: rework without recursion?
816
817 if(BigNumber.len == 0) {
818 return true; /* Subtracting one from zero-length string gives a carry */
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700819 } else {
Laurence Lundblade68769332024-11-03 13:09:20 -0800820 SubBigNum = UsefulBuf_Tail(BigNumber, 1);
821 bCarry = QCBOREncode_Private_BigNumberCarry(SubBigNum);
822 if(UsefulBufC_NTH_BYTE(BigNumber, 0) == 0x00 && bCarry) {
823 /* Subtracting one from 0 gives a carry */
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700824 return true;
825 } else {
826 return false;
827 }
828 }
829}
830
831
Laurence Lundblade05369de2024-11-17 17:00:28 -0800832/**
Laurence Lundblade68769332024-11-03 13:09:20 -0800833 * @brief Output negative bignum bytes with subtraction of 1.
834 *
835 * @param[in] pMe The decode context.
836 * @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
837 * @ref QCBOR_ENCODE_AS_BORROWED.
838 * @param[in] BigNumber The negative big number.
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700839 */
Laurence Lundblade68769332024-11-03 13:09:20 -0800840static void
841QCBOREncode_Private_AddTNegativeBigNumber(QCBOREncodeContext *pMe,
842 const uint8_t uTagRequirement,
843 const UsefulBufC BigNumber)
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700844{
845 size_t uLen;
846 bool bCarry;
847 bool bCopiedSomething;
848 uint8_t uByte;
849 UsefulBufC SubString;
850 UsefulBufC NextSubString;
851
Laurence Lundblade68769332024-11-03 13:09:20 -0800852 QCBOREncode_Private_BigNumberTag(pMe, uTagRequirement, true);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700853
854 /* This works on any length without the need of an additional buffer */
855
856 /* This subtracts one, possibly making the string shorter by one
857 * 0x01 -> 0x00
858 * 0x01 0x00 -> 0xff
859 * 0x00 0x01 0x00 -> 0x00 0xff
860 * 0x02 0x00 -> 0x01 0xff
861 * 0xff -> 0xfe
862 * 0xff 0x00 -> 0xfe 0xff
863 * 0x01 0x00 0x00 -> 0xff 0xff
Laurence Lundblade68769332024-11-03 13:09:20 -0800864 *
865 * This outputs the big number a byte at a time to be able to operate on
866 * a big number of any length without memory allocation.
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700867 */
868
Laurence Lundblade68769332024-11-03 13:09:20 -0800869 /* Compute the length up front because it goes in the encoded head */
870 bCarry = QCBOREncode_Private_BigNumberCarry(UsefulBuf_Tail(BigNumber, 1));
871 uLen = BigNumber.len;
872 if(bCarry && BigNumber.len > 1 && UsefulBufC_NTH_BYTE(BigNumber, 0) >= 1) {
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700873 uLen--;
874 }
Laurence Lundblade05369de2024-11-17 17:00:28 -0800875 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uLen,0);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700876
Laurence Lundblade68769332024-11-03 13:09:20 -0800877 SubString = BigNumber;
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700878 bCopiedSomething = false;
879 while(SubString.len) {
Laurence Lundblade68769332024-11-03 13:09:20 -0800880 uByte = UsefulBufC_NTH_BYTE(SubString, 0);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700881 NextSubString = UsefulBuf_Tail(SubString, 1);
Laurence Lundblade68769332024-11-03 13:09:20 -0800882 bCarry = QCBOREncode_Private_BigNumberCarry(NextSubString);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700883 if(bCarry) {
884 uByte--;
885 }
Laurence Lundblade68769332024-11-03 13:09:20 -0800886 /* This avoids all but the last leading zero. See
887 * QCBOREncode_Private_SkipLeadingZeros() */
888 if(bCopiedSomething || NextSubString.len == 0 || uByte != 0) {
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700889 UsefulOutBuf_AppendByte(&(pMe->OutBuf), uByte);
890 bCopiedSomething = true;
891 }
892 SubString = NextSubString;
893 }
894}
895
896
Laurence Lundblade68769332024-11-03 13:09:20 -0800897/**
Laurence Lundblade68769332024-11-03 13:09:20 -0800898 * @brief Remove leading zeros.
899 *
Laurence Lundblade05369de2024-11-17 17:00:28 -0800900 * @param[in] BigNumber The big number.
Laurence Lundblade68769332024-11-03 13:09:20 -0800901 *
902 * @return Big number with no leading zeros.
903 *
Laurence Lundblade05369de2024-11-17 17:00:28 -0800904 * If the big number is all zeros, this returns a big number that is
905 * one zero rather than the empty string.
Laurence Lundblade68769332024-11-03 13:09:20 -0800906 *
Laurence Lundblade05369de2024-11-17 17:00:28 -0800907 * RFC 8949 3.4.3 does not explicitly decoders MUST handle the empty
908 * string, but does say decoders MUST handle leading zeros. So
909 * Postel's Law is applied here and 0 is not encoded as an empty
910 * string.
Laurence Lundblade68769332024-11-03 13:09:20 -0800911 */
912static UsefulBufC
913QCBOREncode_Private_SkipLeadingZeros(const UsefulBufC BigNumber)
914{
915 UsefulBufC NLZ;
916 NLZ = UsefulBuf_SkipLeading(BigNumber, 0x00);
917
918 /* An all-zero string reduces to one 0, not an empty string. */
Laurence Lundblade05369de2024-11-17 17:00:28 -0800919 if(NLZ.len == 0 &&
920 BigNumber.len > 0 &&
921 UsefulBufC_NTH_BYTE(BigNumber, 0) == 0x00) {
922 NLZ.len = 1;
Laurence Lundblade68769332024-11-03 13:09:20 -0800923 }
924
925 return NLZ;
926}
927
928
Laurence Lundblade05369de2024-11-17 17:00:28 -0800929/**
930 * @brief Output a big number, preferred or not, with negative offset
931 *
932 * @param[in] pMe The decode context.
933 * @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
934 * @ref QCBOR_ENCODE_AS_BORROWED.
935 * @param[in] bPreferred Uses preferred serialization if true
936 * @param[in] bNegative Indicates big number is negative or postive.
937 * @param[in] BigNumber The big number.
938 *
939 * Regardless of whether preferred serialization is used, if the big
940 * number is negative, one is subtracted before is output per CBOR
941 * convetion for big numbers. This requires a little big number
942 * arithmetic and adds some object code.
943 *
944 * If preferred serialization is used, then if the number is smaller
945 * than UINT64_MAX and postive it is output as type 0 and if it is
946 * equal to or smaller than UINT64_MAX it is output as a type 1
947 * integer minus one.
948 *
949 * See QCBOREncode_AddTBigNumberRaw() for simple copy through.
Laurence Lundblade68769332024-11-03 13:09:20 -0800950 */
951void
Laurence Lundblade05369de2024-11-17 17:00:28 -0800952QCBOREncode_Private_AddTBigNumberMain(QCBOREncodeContext *pMe,
953 const uint8_t uTagRequirement,
954 const bool bPreferred,
955 const bool bNegative,
956 const UsefulBufC BigNumber)
Laurence Lundblade68769332024-11-03 13:09:20 -0800957{
Laurence Lundblade05369de2024-11-17 17:00:28 -0800958 uint64_t uInt;
959 bool bIs2exp64;
960 uint8_t uMajorType;
961 UsefulBufC BigNumberNLZ;
Laurence Lundblade68769332024-11-03 13:09:20 -0800962
Laurence Lundblade82634b62024-11-20 22:37:45 -0800963#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
964 if(!bPreferred && pMe->uConfigFlags & QCBOR_ENCODE_CONFIG_ONLY_PREFERRED_BIG_NUMBERS) {
965 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
966 return;
967 }
968#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
969
Laurence Lundblade05369de2024-11-17 17:00:28 -0800970 BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
Laurence Lundblade68769332024-11-03 13:09:20 -0800971
Laurence Lundblade05369de2024-11-17 17:00:28 -0800972 static const uint8_t twoExp64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
973 bIs2exp64 = ! UsefulBuf_Compare(BigNumber, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(twoExp64));
974
975 if(bPreferred && (BigNumberNLZ.len <= 8 || (bNegative && bIs2exp64))) {
976 if(bIs2exp64) {
977 /* 2^64 is a 9 byte big number. Since negative numbers are offset
978 * by one in CBOR, it can be encoded as a type 1 negative. The
979 * conversion below won't work because the uInt will overflow
980 * before the subtraction of 1.
981 */
982 uInt = UINT64_MAX;
Laurence Lundblade68769332024-11-03 13:09:20 -0800983 } else {
Laurence Lundblade05369de2024-11-17 17:00:28 -0800984 uInt = QCBOREncode_Private_BigNumberToUInt(BigNumberNLZ);
985 if(bNegative) {
986 uInt--;
987 }
988 }
989 uMajorType = bNegative ? CBOR_MAJOR_TYPE_NEGATIVE_INT :
990 CBOR_MAJOR_TYPE_POSITIVE_INT;
991 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uInt, 0);
992 } else {
993 if(bNegative) {
Laurence Lundblade68769332024-11-03 13:09:20 -0800994 QCBOREncode_Private_AddTNegativeBigNumber(pMe, uTagRequirement, BigNumberNLZ);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700995 } else {
Laurence Lundblade05369de2024-11-17 17:00:28 -0800996 QCBOREncode_AddTBigNumberRaw(pMe, false, uTagRequirement, BigNumberNLZ);
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700997 }
998 }
999}
1000
1001
Laurence Lundblade68769332024-11-03 13:09:20 -08001002
1003
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07001004#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001005/**
1006 * @brief Semi-private method to add bigfloats and decimal fractions.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001007 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001008 * @param[in] pMe The encoding context to add the value to.
Laurence Lundblade68769332024-11-03 13:09:20 -08001009 * @param[in] uTagNumber The type 6 tag indicating what this is to be.
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001010 * @param[in] nMantissa The @c int64_t mantissa if it is not a big number.
1011 * @param[in] nExponent The exponent.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001012 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001013 * This outputs either the @ref CBOR_TAG_DECIMAL_FRACTION or
1014 * @ref CBOR_TAG_BIGFLOAT tag. if @c uTag is @ref CBOR_TAG_INVALID64,
1015 * then this outputs the "borrowed" content format.
1016 *
1017 * The tag content output by this is an array with two members, the
1018 * exponent and then the mantissa. The mantissa can be either a big
1019 * number or an @c int64_t.
1020 *
1021 * This implementation cannot output an exponent further from 0 than
1022 * @c INT64_MAX.
1023 *
1024 * To output a mantissa that is between INT64_MAX and UINT64_MAX from 0,
1025 * it must be as a big number.
1026 *
Laurence Lundblade0f143652024-10-06 11:06:19 -07001027 * Typically, QCBOREncode_AddTDecimalFraction(), QCBOREncode_AddTBigFloat(),
1028 * QCBOREncode_AddTDecimalFractionBigNum() or QCBOREncode_AddTBigFloatBigNum()
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001029 * is called instead of this.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001030 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001031void
Laurence Lundblade68769332024-11-03 13:09:20 -08001032QCBOREncode_Private_AddTExpIntMantissa(QCBOREncodeContext *pMe,
1033 const int uTagRequirement,
1034 const uint64_t uTagNumber,
1035 const int64_t nExponent,
1036 const int64_t nMantissa)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001037{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001038 /* This is for encoding either a big float or a decimal fraction,
1039 * both of which are an array of two items, an exponent and a
1040 * mantissa. The difference between the two is that the exponent
1041 * is base-2 for big floats and base-10 for decimal fractions, but
1042 * that has no effect on the code here.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001043 */
Laurence Lundblade68769332024-11-03 13:09:20 -08001044 /* Separate from QCBOREncode_Private_AddTExpBigMantissa() because
1045 * linking QCBOREncode_AddTBigNumber() adds a lot because it
1046 * does preferred serialization of big numbers and the offset of 1
1047 * for CBOR negative numbers.
1048 */
1049 if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
1050 QCBOREncode_AddTagNumber(pMe, uTagNumber);
Laurence Lundbladeae66d3f2020-09-14 18:12:08 -07001051 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001052 QCBOREncode_OpenArray(pMe);
1053 QCBOREncode_AddInt64(pMe, nExponent);
Laurence Lundblade68769332024-11-03 13:09:20 -08001054 QCBOREncode_AddInt64(pMe, nMantissa);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001055 QCBOREncode_CloseArray(pMe);
1056}
Laurence Lundblade68769332024-11-03 13:09:20 -08001057
1058void
1059QCBOREncode_Private_AddTExpBigMantissa(QCBOREncodeContext *pMe,
1060 const int uTagRequirement,
1061 const uint64_t uTagNumber,
1062 const int64_t nExponent,
1063 const UsefulBufC BigNumMantissa,
1064 const bool bBigNumIsNegative)
1065{
1066 /* This is for encoding either a big float or a decimal fraction,
1067 * both of which are an array of two items, an exponent and a
1068 * mantissa. The difference between the two is that the exponent
1069 * is base-2 for big floats and base-10 for decimal fractions, but
1070 * that has no effect on the code here.
1071 */
1072 if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
Laurence Lundblade05369de2024-11-17 17:00:28 -08001073 QCBOREncode_AddTagNumber(pMe, uTagNumber);
Laurence Lundblade68769332024-11-03 13:09:20 -08001074 }
1075 QCBOREncode_OpenArray(pMe);
1076 QCBOREncode_AddInt64(pMe, nExponent);
1077 QCBOREncode_AddTBigNumber(pMe, QCBOR_ENCODE_AS_TAG, bBigNumIsNegative, BigNumMantissa);
1078 QCBOREncode_CloseArray(pMe);
1079}
1080
1081
1082void
1083QCBOREncode_Private_AddTExpBigMantissaRaw(QCBOREncodeContext *pMe,
1084 const int uTagRequirement,
1085 const uint64_t uTagNumber,
1086 const int64_t nExponent,
1087 const UsefulBufC BigNumMantissa,
1088 const bool bBigNumIsNegative)
1089{
1090 /* This is for encoding either a big float or a decimal fraction,
1091 * both of which are an array of two items, an exponent and a
1092 * mantissa. The difference between the two is that the exponent
1093 * is base-2 for big floats and base-10 for decimal fractions, but
1094 * that has no effect on the code here.
1095 */
1096 /* Separate from QCBOREncode_Private_AddTExpBigMantissa() because
1097 * linking QCBOREncode_AddTBigNumber() adds a lot because it
1098 * does preferred serialization of big numbers and the offset of 1
1099 * for CBOR negative numbers.
1100 */
1101 if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
Laurence Lundblade05369de2024-11-17 17:00:28 -08001102 QCBOREncode_AddTagNumber(pMe, uTagNumber);
Laurence Lundblade68769332024-11-03 13:09:20 -08001103 }
1104 QCBOREncode_OpenArray(pMe);
1105 QCBOREncode_AddInt64(pMe, nExponent);
1106 QCBOREncode_AddTBigNumberRaw(pMe, QCBOR_ENCODE_AS_TAG, bBigNumIsNegative, BigNumMantissa);
1107 QCBOREncode_CloseArray(pMe);
1108}
1109
Laurence Lundbladed253e412024-08-21 11:02:56 -07001110#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001111
1112
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001113/**
1114 * @brief Semi-private method to open a map, array or bstr-wrapped CBOR
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001115 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001116 * @param[in] pMe The context to add to.
1117 * @param[in] uMajorType The major CBOR type to close
1118 *
1119 * Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
1120 * QCBOREncode_BstrWrap() instead of this.
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001121 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001122void
1123QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pMe,
1124 const uint8_t uMajorType)
Laurence Lundblade067035b2018-11-28 17:35:25 -08001125{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001126 /* Add one item to the nesting level we are in for the new map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001127 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladed39cd392019-01-11 18:17:38 -08001128
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001129 /* The offset where the length of an array or map will get written
1130 * is stored in a uint32_t, not a size_t to keep stack usage
1131 * smaller. This checks to be sure there is no wrap around when
1132 * recording the offset. Note that on 64-bit machines CBOR larger
1133 * than 4GB can be encoded as long as no array/map offsets occur
1134 * past the 4GB mark, but the public interface says that the
1135 * maximum is 4GB to keep the discussion simpler.
1136 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001137 size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundbladed39cd392019-01-11 18:17:38 -08001138
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001139 /* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
1140 * code can run on a 32-bit machine and tests can pass on a 32-bit
1141 * machine. If it was exactly UINT32_MAX, then this code would not
1142 * compile or run on a 32-bit machine and an #ifdef or some machine
1143 * size detection would be needed reducing portability.
1144 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001145 if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001146 pMe->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001147
1148 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001149 /* Increase nesting level because this is a map or array. Cast
1150 * from size_t to uin32_t is safe because of check above.
1151 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001152 pMe->uError = Nesting_Increase(&(pMe->nesting), uMajorType, (uint32_t)uEndPosition);
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -08001153 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001154}
1155
Laurence Lundblade59289e52019-12-30 13:44:37 -08001156
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001157#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001158/**
1159 * @brief Semi-private method to open a map, array with indefinite length
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001160 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001161 * @param[in] pMe The context to add to.
1162 * @param[in] uMajorType The major CBOR type to close
1163 *
1164 * Call QCBOREncode_OpenArrayIndefiniteLength() or
1165 * QCBOREncode_OpenMapIndefiniteLength() instead of this.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001166 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001167void
1168QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1169 const uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001170{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001171 /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001172 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, 0, 0);
Laurence Lundblade82634b62024-11-20 22:37:45 -08001173 if(pMe->uError) {
1174 return;
1175 }
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001176
1177 /* Call the definite-length opener just to do the bookkeeping for
1178 * nesting. It will record the position of the opening item in the
1179 * encoded output but this is not used when closing this open.
1180 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001181 QCBOREncode_Private_OpenMapOrArray(pMe, uMajorType);
Jan Jongboom4a93a662019-07-25 08:44:58 +02001182}
Laurence Lundbladed253e412024-08-21 11:02:56 -07001183#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001184
1185
1186/**
1187 * @brief Check for errors when decreasing nesting.
1188 *
1189 * @param pMe QCBOR encoding context.
1190 * @param uMajorType The major type of the nesting.
1191 *
1192 * Check that there is no previous error, that there is actually some
1193 * nesting and that the major type of the opening of the nesting
1194 * matches the major type of the nesting being closed.
1195 *
1196 * This is called when closing maps, arrays, byte string wrapping and
1197 * open/close of byte strings.
1198 */
1199static bool
1200QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext *pMe,
1201 const uint8_t uMajorType)
1202{
1203#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
1204 if(pMe->uError != QCBOR_SUCCESS) {
1205 return true;
1206 }
1207
1208 if(!Nesting_IsInNest(&(pMe->nesting))) {
1209 pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
1210 return true;
1211 }
1212
1213 if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
1214 pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
1215 return true;
1216 }
1217
Laurence Lundbladed253e412024-08-21 11:02:56 -07001218#else /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001219 /* None of these checks are performed if the encode guards are
1220 * turned off as they all relate to correct calling.
1221 *
1222 * Turning off all these checks does not turn off any checking for
1223 * buffer overflows or pointer issues.
1224 */
1225
1226 (void)uMajorType;
1227 (void)pMe;
Laurence Lundbladed253e412024-08-21 11:02:56 -07001228#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001229
1230 return false;
1231}
1232
1233
1234/**
Laurence Lundbladed253e412024-08-21 11:02:56 -07001235 * @brief Insert the CBOR head for a map, array or wrapped bstr.
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001236 *
1237 * @param pMe QCBOR encoding context.
1238 * @param uMajorType One of CBOR_MAJOR_TYPE_XXXX.
1239 * @param uLen The length of the data item.
1240 *
1241 * When an array, map or bstr was opened, nothing was done but note
1242 * the position. This function goes back to that position and inserts
1243 * the CBOR Head with the major type and length.
1244 */
1245static void
1246QCBOREncode_Private_CloseAggregate(QCBOREncodeContext *pMe,
1247 uint8_t uMajorType,
1248 size_t uLen)
1249{
1250 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
1251 return;
1252 }
1253
1254 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
1255 uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
1256 }
1257
1258 /* A stack buffer large enough for a CBOR head (9 bytes) */
1259 UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
1260
1261 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
1262 uMajorType,
1263 0,
1264 uLen);
1265
1266 /* No check for EncodedHead == NULLUsefulBufC is performed here to
1267 * save object code. It is very clear that pBufferForEncodedHead is
1268 * the correct size. If EncodedHead == NULLUsefulBufC then
1269 * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
1270 * security hole introduced.
1271 */
1272 UsefulOutBuf_InsertUsefulBuf(&(pMe->OutBuf),
1273 EncodedHead,
1274 Nesting_GetStartPos(&(pMe->nesting)));
1275
1276 Nesting_Decrease(&(pMe->nesting));
1277}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001278
Laurence Lundbladeee851742020-01-08 08:37:05 -08001279
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001280/**
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08001281 * @brief Semi-private method to close a map, array or bstr wrapped CBOR.
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001282 *
1283 * @param[in] pMe The context to add to.
1284 * @param[in] uMajorType The major CBOR type to close.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001285 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001286void
1287QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pMe,
1288 const uint8_t uMajorType)
Laurence Lundbladea954db92018-09-28 19:27:31 -07001289{
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001290 QCBOREncode_Private_CloseAggregate(pMe, uMajorType, Nesting_GetCount(&(pMe->nesting)));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001291}
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001292
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001293
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08001294/**
1295 * @brief Private method to close a map without sorting.
1296 *
1297 * @param[in] pMe The encode context with map to close.
1298 *
1299 * See QCBOREncode_SerializationCDE() implemention for explantion for why
1300 * this exists in this form.
1301 */
Laurence Lundblade82634b62024-11-20 22:37:45 -08001302void
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08001303QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe)
1304{
1305 QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
1306}
1307
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001308
1309/**
1310 * @brief Decode a CBOR item head.
1311 *
1312 * @param[in] pUInBuf UsefulInputBuf to read from.
1313 * @param[out] pnMajorType Major type of decoded head.
1314 * @param[out] puArgument Argument of decoded head.
1315 * @param[out] pnAdditionalInfo Additional info from decoded head.
1316 *
1317 * @return SUCCESS if a head was decoded
1318 * HIT_END if there were not enough bytes to decode a head
1319 * UNSUPPORTED if the decoded item is not one that is supported
1320 *
1321 * This is copied from qcbor_decode.c rather than referenced. This
1322 * makes the core decoder 60 bytes smaller because it gets inlined.
1323 * It would not get inlined if it was referenced. It is important to
1324 * make the core decoder as small as possible. The copy here does make
1325 * map sorting 200 bytes bigger, but map sorting is rarely used in
1326 * environments that need small object code. It would also make
1327 * qcbor_encode.c depend on qcbor_decode.c
1328 *
1329 * This is also super stable and tested. It implements the very
1330 * well-defined part of CBOR that will never change. So this won't
1331 * change.
1332 */
1333static QCBORError
1334QCBOREncodePriv_DecodeHead(UsefulInputBuf *pUInBuf,
1335 int *pnMajorType,
1336 uint64_t *puArgument,
1337 int *pnAdditionalInfo)
1338{
1339 QCBORError uReturn;
1340
1341 /* Get the initial byte that every CBOR data item has and break it
1342 * down. */
1343 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
1344 const int nTmpMajorType = nInitialByte >> 5;
1345 const int nAdditionalInfo = nInitialByte & 0x1f;
1346
1347 /* Where the argument accumulates */
1348 uint64_t uArgument;
1349
1350 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
1351 /* Need to get 1,2,4 or 8 additional argument bytes. Map
1352 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
1353 */
1354 static const uint8_t aIterate[] = {1,2,4,8};
1355
1356 /* Loop getting all the bytes in the argument */
1357 uArgument = 0;
1358 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
1359 /* This shift and add gives the endian conversion. */
1360 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
1361 }
1362 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
1363 /* The reserved and thus-far unused additional info values */
1364 uReturn = QCBOR_ERR_UNSUPPORTED;
1365 goto Done;
1366 } else {
1367 /* Less than 24, additional info is argument or 31, an
1368 * indefinite-length. No more bytes to get.
1369 */
1370 uArgument = (uint64_t)nAdditionalInfo;
1371 }
1372
1373 if(UsefulInputBuf_GetError(pUInBuf)) {
1374 uReturn = QCBOR_ERR_HIT_END;
1375 goto Done;
1376 }
1377
1378 /* All successful if arrived here. */
1379 uReturn = QCBOR_SUCCESS;
1380 *pnMajorType = nTmpMajorType;
1381 *puArgument = uArgument;
1382 *pnAdditionalInfo = nAdditionalInfo;
1383
1384Done:
1385 return uReturn;
1386}
1387
1388
1389/**
1390 * @brief Consume the next item from a UsefulInputBuf.
1391 *
1392 * @param[in] pInBuf UsefulInputBuf from which to consume item.
1393 *
1394 * Recursive, but stack usage is light and encoding depth limit
1395 */
1396static QCBORError
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001397QCBOR_Private_ConsumeNext(UsefulInputBuf *pInBuf)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001398{
1399 int nMajor;
1400 uint64_t uArgument;
1401 int nAdditional;
1402 uint16_t uItemCount;
1403 uint16_t uMul;
1404 uint16_t i;
1405 QCBORError uCBORError;
1406
1407 uCBORError = QCBOREncodePriv_DecodeHead(pInBuf, &nMajor, &uArgument, &nAdditional);
1408 if(uCBORError != QCBOR_SUCCESS) {
1409 return uCBORError;
1410 }
1411
1412 uMul = 1;
1413
1414 switch(nMajor) {
1415 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1416 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1417 break;
1418
1419 case CBOR_MAJOR_TYPE_SIMPLE:
1420 return uArgument == CBOR_SIMPLE_BREAK ? 1 : 0;
1421 break;
1422
1423 case CBOR_MAJOR_TYPE_BYTE_STRING:
1424 case CBOR_MAJOR_TYPE_TEXT_STRING:
1425 if(nAdditional == LEN_IS_INDEFINITE) {
1426 /* Segments of indefinite length */
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001427 while(QCBOR_Private_ConsumeNext(pInBuf) == 0);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001428 }
1429 (void)UsefulInputBuf_GetBytes(pInBuf, uArgument);
1430 break;
1431
1432 case CBOR_MAJOR_TYPE_TAG:
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001433 QCBOR_Private_ConsumeNext(pInBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001434 break;
1435
1436 case CBOR_MAJOR_TYPE_MAP:
1437 uMul = 2;
1438 /* Fallthrough */
1439 case CBOR_MAJOR_TYPE_ARRAY:
1440 uItemCount = (uint16_t)uArgument * uMul;
1441 if(nAdditional == LEN_IS_INDEFINITE) {
1442 uItemCount = UINT16_MAX;
1443 }
1444 for(i = uItemCount; i > 0; i--) {
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001445 if(QCBOR_Private_ConsumeNext(pInBuf)) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001446 /* End of indefinite length */
1447 break;
1448 }
1449 }
1450 break;
1451 }
1452
1453 return QCBOR_SUCCESS;
1454}
1455
1456
1457/**
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001458 * @brief Decoded next item to get its lengths.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001459 *
1460 * Decode the next item in map no matter what type it is. It works
1461 * recursively when an item is a map or array It returns offset just
1462 * past the item decoded or zero there are no more items in the output
1463 * buffer.
1464 *
1465 * This doesn't distinguish between end of the input and an error
1466 * because it is used to decode stuff we encoded into a buffer, not
1467 * stuff that came in from outside. We still want a check for safety
1468 * in case of bugs here, but it is OK to report end of input on error.
1469 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001470struct ItemLens {
1471 uint32_t uLabelLen;
1472 uint32_t uItemLen;
1473};
1474
1475static struct ItemLens
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001476QCBOREncode_Private_DecodeNextInMap(QCBOREncodeContext *pMe, uint32_t uStart)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001477{
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001478 UsefulInputBuf InBuf;
1479 UsefulBufC EncodedMapBytes;
1480 QCBORError uCBORError;
1481 struct ItemLens Result;
1482
1483 Result.uLabelLen = 0;
1484 Result.uItemLen = 0;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001485
1486 EncodedMapBytes = UsefulOutBuf_OutUBufOffset(&(pMe->OutBuf), uStart);
1487 if(UsefulBuf_IsNULLC(EncodedMapBytes)) {
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001488 return Result;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001489 }
1490
1491 UsefulInputBuf_Init(&InBuf, EncodedMapBytes);
1492
1493 /* This is always used on maps, so consume two, the label and the value */
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001494 uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001495 if(uCBORError) {
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001496 return Result;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001497 }
1498
1499 /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001500 Result.uLabelLen = (uint32_t)UsefulInputBuf_Tell(&InBuf);
1501
1502 uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
1503 if(uCBORError) {
1504 Result.uLabelLen = 0;
1505 return Result;
1506 }
1507
1508 Result.uItemLen = (uint32_t)UsefulInputBuf_Tell(&InBuf);
1509
1510 /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
1511 return Result;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001512}
1513
1514
1515/**
1516 * @brief Sort items lexographically by encoded labels.
1517 *
1518 * @param[in] pMe Encoding context.
1519 * @param[in] uStart Offset in outbuf of first item for sorting.
1520 *
1521 * This reaches into the UsefulOutBuf in the encoding context and
1522 * sorts encoded CBOR items. The byte offset start of the items is at
1523 * @c uStart and it goes to the end of valid bytes in the
1524 * UsefulOutBuf.
1525 */
1526static void
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001527QCBOREncode_Private_SortMap(QCBOREncodeContext *pMe, uint32_t uStart)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001528{
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001529 bool bSwapped;
1530 int nComparison;
1531 uint32_t uStart1;
1532 uint32_t uStart2;
1533 struct ItemLens Lens1;
1534 struct ItemLens Lens2;
1535
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001536
1537 if(pMe->uError != QCBOR_SUCCESS) {
1538 return;
1539 }
1540
1541 /* Bubble sort because the sizes of all the items are not the
1542 * same. It works with adjacent pairs so the swap is not too
1543 * difficult even though sizes are different.
1544 *
1545 * While bubble sort is n-squared, it seems OK here because n will
1546 * usually be small and the comparison and swap functions aren't
1547 * too CPU intensive.
1548 *
1549 * Another approach would be to have an array of offsets to the
1550 * items. However this requires memory allocation and the swap
1551 * operation for quick sort or such is complicated because the item
1552 * sizes are not the same and overlap may occur in the bytes being
1553 * swapped.
1554 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001555 do { /* Loop until nothing was swapped */
1556 Lens1 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart);
1557 if(Lens1.uLabelLen == 0) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001558 /* It's an empty map. Nothing to do. */
1559 break;
1560 }
1561 uStart1 = uStart;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001562 uStart2 = uStart1 + Lens1.uItemLen;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001563 bSwapped = false;
1564
1565 while(1) {
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001566 Lens2 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart2);
1567 if(Lens2.uLabelLen == 0) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001568 break;
1569 }
1570
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001571 nComparison = UsefulOutBuf_Compare(&(pMe->OutBuf),
1572 uStart1, Lens1.uLabelLen,
1573 uStart2, Lens2.uLabelLen);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001574 if(nComparison < 0) {
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001575 UsefulOutBuf_Swap(&(pMe->OutBuf), uStart1, uStart2, uStart2 + Lens2.uItemLen);
1576 uStart1 = uStart1 + Lens2.uItemLen; /* item 2 now in position of item 1 */
1577 /* Lens1 is still valid as Lens1 for the next loop */
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001578 bSwapped = true;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001579 } else if(nComparison > 0) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001580 uStart1 = uStart2;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001581 Lens1 = Lens2;
1582 } else /* nComparison == 0 */ {
1583 pMe->uError = QCBOR_ERR_DUPLICATE_LABEL;
1584 return;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001585 }
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001586 uStart2 = uStart2 + Lens2.uItemLen;
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001587 }
1588 } while(bSwapped);
1589}
1590
1591
1592/*
1593 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1594 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001595void
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001596QCBOREncode_CloseAndSortMap(QCBOREncodeContext *pMe)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001597{
1598 uint32_t uStart;
1599
1600 /* The Header for the map we are about to sort hasn't been
1601 * inserted yet, so uStart is the position of the first item
1602 * and the end out the UsefulOutBuf data is the end of the
1603 * items we are about to sort.
1604 */
1605 uStart = Nesting_GetStartPos(&(pMe->nesting));
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001606 QCBOREncode_Private_SortMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001607
Laurence Lundblade70fc1252024-05-31 10:57:28 -07001608 QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_MAP, Nesting_GetCount(&(pMe->nesting)));
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001609}
1610
1611
Laurence Lundbladed3f07842024-06-19 13:05:07 -07001612#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001613/*
1614 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1615 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001616void
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001617QCBOREncode_CloseAndSortMapIndef(QCBOREncodeContext *pMe)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001618{
1619 uint32_t uStart;
1620
1621 uStart = Nesting_GetStartPos(&(pMe->nesting));
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001622 QCBOREncode_Private_SortMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001623
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001624 QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001625}
Laurence Lundbladed3f07842024-06-19 13:05:07 -07001626#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001627
1628
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001629/*
Laurence Lundbladed253e412024-08-21 11:02:56 -07001630 * Public function for closing bstr wrapping. See qcbor/qcbor_encode.h
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001631 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001632void
1633QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pMe,
1634 const bool bIncludeCBORHead,
1635 UsefulBufC *pWrappedCBOR)
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001636{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001637 const size_t uInsertPosition = Nesting_GetStartPos(&(pMe->nesting));
1638 const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001639
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001640 /* This subtraction can't go negative because the UsefulOutBuf
1641 * always only grows and never shrinks. UsefulOutBut itself also
1642 * has defenses such that it won't write where it should not even
1643 * if given incorrect input lengths.
1644 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001645 const size_t uBstrLen = uEndPosition - uInsertPosition;
1646
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001647 /* Actually insert */
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001648 QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001649
1650 if(pWrappedCBOR) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001651 /* Return pointer and length to the enclosed encoded CBOR. The
1652 * intended use is for it to be hashed (e.g., SHA-256) in a COSE
1653 * implementation. This must be used right away, as the pointer
1654 * and length go invalid on any subsequent calls to this
1655 * function because there might be calls to
1656 * InsertEncodedTypeAndNumber() that slides data to the right.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001657 */
1658 size_t uStartOfNew = uInsertPosition;
1659 if(!bIncludeCBORHead) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001660 /* Skip over the CBOR head to just get the inserted bstr */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001661 const size_t uNewEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001662 uStartOfNew += uNewEndPosition - uEndPosition;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001663 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001664 const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001665 *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uStartOfNew);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001666 }
1667}
1668
Laurence Lundbladeee851742020-01-08 08:37:05 -08001669
Jan Jongboom4a93a662019-07-25 08:44:58 +02001670/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001671 * Public function for canceling a bstr wrap. See qcbor/qcbor_encode.h
1672 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001673void
1674QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pMe)
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001675{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001676 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, CBOR_MAJOR_TYPE_BYTE_STRING)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001677 return;
1678 }
1679
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001680#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001681 const size_t uCurrent = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
1682 if(pMe->nesting.pCurrentNesting->uStart != uCurrent) {
1683 pMe->uError = QCBOR_ERR_CANNOT_CANCEL;
1684 return;
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001685 }
1686 /* QCBOREncode_CancelBstrWrap() can't correctly undo
Laurence Lundblade0f143652024-10-06 11:06:19 -07001687 * QCBOREncode_BstrWrapInMapSZ() or QCBOREncode_BstrWrapInMapN(). It
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001688 * can't undo the labels they add. It also doesn't catch the error
1689 * of using it this way. QCBOREncode_CancelBstrWrap() is used
1690 * infrequently and the the result is incorrect CBOR, not a
1691 * security hole, so no extra code or state is added to handle this
1692 * condition.
1693 */
Laurence Lundbladed253e412024-08-21 11:02:56 -07001694#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001695
1696 Nesting_Decrease(&(pMe->nesting));
1697 Nesting_Decrement(&(pMe->nesting));
1698}
1699
1700
1701/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001702 * Public function for opening a byte string. See qcbor/qcbor_encode.h
1703 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001704void
1705QCBOREncode_OpenBytes(QCBOREncodeContext *pMe, UsefulBuf *pPlace)
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001706{
1707 *pPlace = UsefulOutBuf_GetOutPlace(&(pMe->OutBuf));
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001708#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Paul Liétar79789772022-07-26 20:33:18 +01001709 uint8_t uMajorType = Nesting_GetMajorType(&(pMe->nesting));
1710 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
Laurence Lundblade716d10c2024-02-07 16:54:42 -08001711 /* It's OK to nest a byte string in any type but
1712 * another open byte string. */
Paul Liétar79789772022-07-26 20:33:18 +01001713 pMe->uError = QCBOR_ERR_OPEN_BYTE_STRING;
1714 return;
1715 }
Laurence Lundbladed253e412024-08-21 11:02:56 -07001716#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001717
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001718 QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001719}
1720
1721
1722/*
1723 * Public function for closing a byte string. See qcbor/qcbor_encode.h
1724 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001725void
1726QCBOREncode_CloseBytes(QCBOREncodeContext *pMe, const size_t uAmount)
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001727{
1728 UsefulOutBuf_Advance(&(pMe->OutBuf), uAmount);
1729 if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
1730 /* Advance too far. Normal off-end error handling in effect here. */
1731 return;
1732 }
1733
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001734 QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001735}
1736
1737
Laurence Lundbladecbd7d132024-05-19 11:11:22 -07001738#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001739/**
1740 * @brief Semi-private method to close a map, array with indefinite length
1741 *
1742 * @param[in] pMe The context to add to.
1743 * @param[in] uMajorType The major CBOR type to close.
1744 *
1745 * Call QCBOREncode_CloseArrayIndefiniteLength() or
1746 * QCBOREncode_CloseMapIndefiniteLength() instead of this.
Jan Jongboom4a93a662019-07-25 08:44:58 +02001747 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001748void
1749QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1750 const uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001751{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001752 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001753 return;
Jan Jongboom4a93a662019-07-25 08:44:58 +02001754 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001755
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001756 /* Append the break marker (0xff for both arrays and maps) */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001757 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001758 Nesting_Decrease(&(pMe->nesting));
Jan Jongboom4a93a662019-07-25 08:44:58 +02001759}
Laurence Lundbladed253e412024-08-21 11:02:56 -07001760#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Jan Jongboom4a93a662019-07-25 08:44:58 +02001761
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001762
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001763/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001764 * Public function to finish and get the encoded result. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001765 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001766QCBORError
1767QCBOREncode_Finish(QCBOREncodeContext *pMe, UsefulBufC *pEncodedCBOR)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001768{
Laurence Lundbladef2f0c3f2024-04-12 13:01:54 -07001769 if(QCBOREncode_GetErrorState(pMe) != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001770 goto Done;
Laurence Lundblade067035b2018-11-28 17:35:25 -08001771 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001772
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001773#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001774 if(Nesting_IsInNest(&(pMe->nesting))) {
Laurence Lundbladef2f0c3f2024-04-12 13:01:54 -07001775 pMe->uError = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001776 goto Done;
1777 }
Laurence Lundbladed253e412024-08-21 11:02:56 -07001778#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001779
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001780 *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001781
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001782Done:
Laurence Lundbladef2f0c3f2024-04-12 13:01:54 -07001783 return pMe->uError;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001784}
1785
Laurence Lundblade0595e932018-11-02 22:22:47 +07001786
Laurence Lundblade067035b2018-11-28 17:35:25 -08001787/*
Laurence Lundbladed253e412024-08-21 11:02:56 -07001788 * Public function to get size of the encoded result. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -08001789 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001790QCBORError
1791QCBOREncode_FinishGetSize(QCBOREncodeContext *pMe, size_t *puEncodedLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001792{
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001793 UsefulBufC Enc;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001794
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001795 QCBORError nReturn = QCBOREncode_Finish(pMe, &Enc);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001796
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001797 if(nReturn == QCBOR_SUCCESS) {
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001798 *puEncodedLen = Enc.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001799 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001800
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001801 return nReturn;
1802}
Laurence Lundbladee2226742024-08-16 10:50:23 -07001803
1804
1805/*
1806 * Public function to get substring of encoded-so-far. See qcbor/qcbor_encode.h
1807 */
1808UsefulBufC
1809QCBOREncode_SubString(QCBOREncodeContext *pMe, const size_t uStart)
1810{
1811 if(pMe->uError) {
1812 return NULLUsefulBufC;
1813 }
1814
1815 /* An attempt was made to detect usage errors by comparing uStart
1816 * to offsets of open arrays and maps in pMe->nesting, but it is
1817 * not possible because there's not enough information in just
1818 * the offset. It's not possible to known if Tell() was called before
1819 * or after an Open(). To detect this error, the nesting level
1820 * would also need to be known. This is not frequently used, so
1821 * it is not worth adding this complexity.
1822 */
1823
1824 const size_t uEnd = QCBOREncode_Tell(pMe);
1825
1826 return UsefulOutBuf_SubString(&(pMe->OutBuf), uStart, uEnd - uStart);
1827}