blob: da24c91658dacabed2afe4077021b6cf9e9b9d39 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundblade240ca822024-01-16 11:11:00 -07003 Copyright (c) 2018-2024, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
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.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
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 Lundbladee75f5962024-02-15 17:51:32 -080038#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
39#include <math.h> /* Only for NAN */
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 Lundblade1ef8b2d2018-12-14 23:13:34 -0800118 if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700119 return QCBOR_ERR_ARRAY_TOO_LONG;
120 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800121#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 Lundbladed8e1c512020-11-04 23:03:44 -0800173#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()
190 * 6 QCBOREncode_AddTag()
191 * 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
230 * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,535) it is very unlikely
231 * 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
Laurence Lundbladeff8106f2024-02-05 20:02:30 -0700254
255/* Forward declaration for reference in QCBOREncode_Init() */
256static void
257QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe);
258
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700259
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260/*
Laurence Lundbladeff8106f2024-02-05 20:02:30 -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 Lundblade240ca822024-01-16 11:11:00 -0700266 memset(pMe, 0, sizeof(QCBOREncodeContext));
267 UsefulOutBuf_Init(&(pMe->OutBuf), Storage);
268 Nesting_Init(&(pMe->nesting));
Laurence Lundbladeff8106f2024-02-05 20:02:30 -0700269 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 Lundblade8c858ab2020-11-02 19:53:49 -0800439 if(uMajorType > QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800440 /* Special case for start & end of indefinite length */
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800441 uMajorType = uMajorType - QCBOR_INDEFINITE_LEN_TYPE_MODIFIER;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800442 /* This takes advantage of design of CBOR where additional info
443 * is 31 for both opening and closing indefinite length
444 * maps and arrays.
445 */
446 #if CBOR_SIMPLE_BREAK != LEN_IS_INDEFINITE
447 #error additional info for opening array not the same as for closing
448 #endif
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800449 nAdditionalInfo = CBOR_SIMPLE_BREAK;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800450
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000451 } else if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800452 /* Simple case where argument is < 24 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000453 nAdditionalInfo = (int)uArgument;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800454
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800455 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800456 /* This encodes the argument in 1,2,4 or 8 bytes. The outer loop
457 * runs once for 1 byte and 4 times for 8 bytes. The inner loop
458 * runs 1, 2 or 4 times depending on outer loop counter. This
459 * works backwards shifting 8 bits off the argument being
460 * encoded at a time until all bits from uArgument have been
461 * encoded and the minimum encoding size is reached. Minimum
462 * encoding size is for floating-point numbers that have some
463 * zero-value bytes that must be output.
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800464 */
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800465 static const uint8_t aIterate[] = {1,1,2,4};
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000466
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800467 /* uMinLen passed in is unsigned, but goes negative in the loop
468 * so it must be converted to a signed value.
469 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000470 int nMinLen = (int)uMinLen;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800471 int i;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000472 for(i = 0; uArgument || nMinLen > 0; i++) {
473 const int nIterations = (int)aIterate[i];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800474 for(int j = 0; j < nIterations; j++) {
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000475 *--pByte = (uint8_t)(uArgument & 0xff);
476 uArgument = uArgument >> 8;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800477 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800478 nMinLen -= nIterations;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800479 }
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800480
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800481 nAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700482 }
Laurence Lundbladef970f1d2018-12-14 01:44:23 -0800483
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800484 /* This expression integer-promotes to type int. The code above in
485 * function guarantees that nAdditionalInfo will never be larger
486 * than 0x1f. The caller may pass in a too-large uMajor type. The
487 * conversion to unint8_t will cause an integer wrap around and
488 * incorrect CBOR will be generated, but no security issue will
489 * occur.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800490 */
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800491 const int nInitialByte = (uMajorType << 5) + nAdditionalInfo;
492 *--pByte = (uint8_t)nInitialByte;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800493
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000494#ifdef EXTRA_ENCODE_HEAD_CHECK
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800495 /* This is a sanity check that can be turned on to verify the
496 * pointer math in this function is not going wrong. Turn it on and
497 * run the whole test suite to perform the check.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800498 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000499 if(pBufferEnd - pByte > 9 || pBufferEnd - pByte < 1 || pByte < (uint8_t *)buffer.ptr) {
500 return NULLUsefulBufC;
501 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800502#endif /* EXTRA_ENCODE_HEAD_CHECK */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800503
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800504 /* Length will not go negative because the loops run for at most 8 decrements
505 * of pByte, only one other decrement is made, and the array is sized
506 * for this.
507 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000508 return (UsefulBufC){pByte, (size_t)(pBufferEnd - pByte)};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700509}
510
511
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000512/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800513 * @brief Append the CBOR head, the major type and argument
514 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700515 * @param pMe Encoder context.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800516 * @param uMajorType Major type to insert.
517 * @param uArgument The argument (an integer value or a length).
518 * @param uMinLen The minimum number of bytes for encoding the CBOR argument.
519 *
520 * This formats the CBOR "head" and appends it to the output.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000521 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700522static void
523QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext *pMe,
524 const uint8_t uMajorType,
525 const uint64_t uArgument,
526 const uint8_t uMinLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700527{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800528 /* A stack buffer large enough for a CBOR head */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000529 UsefulBuf_MAKE_STACK_UB (pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
530
531 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
532 uMajorType,
533 uMinLen,
534 uArgument);
535
536 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800537 * save object code. It is very clear that pBufferForEncodedHead is
538 * the correct size. If EncodedHead == NULLUsefulBufC then
539 * UsefulOutBuf_AppendUsefulBuf() will do nothing so there is no
540 * security hole introduced.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000541 */
542
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700543 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), EncodedHead);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544}
545
546
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000547/**
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700548 * @brief Check for errors when decreasing nesting.
549 *
550 * @param pMe QCBOR encoding context.
551 * @param uMajorType The major type of the nesting.
552 *
553 * Check that there is no previous error, that there is actually some
554 * nesting and that the major type of the opening of the nesting
555 * matches the major type of the nesting being closed.
556 *
557 * This is called when closing maps, arrays, byte string wrapping and
558 * open/close of byte strings.
559 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700560static bool
561QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext *pMe,
562 const uint8_t uMajorType)
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700563{
564#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
565 if(pMe->uError != QCBOR_SUCCESS) {
566 return true;
567 }
568
569 if(!Nesting_IsInNest(&(pMe->nesting))) {
570 pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
571 return true;
572 }
573
574 if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
575 pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
576 return true;
577 }
578
579#else
580 /* None of these checks are performed if the encode guards are
581 * turned off as they all relate to correct calling.
582 *
583 * Turning off all these checks does not turn off any checking for
584 * buffer overflows or pointer issues.
585 */
586
587 (void)uMajorType;
588 (void)pMe;
589#endif
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700590
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700591 return false;
592}
593
594
595/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800596 * @brief Insert the CBOR head for a map, array or wrapped bstr
597 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700598 * @param pMe QCBOR encoding context.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800599 * @param uMajorType One of CBOR_MAJOR_TYPE_XXXX.
600 * @param uLen The length of the data item.
601 *
602 * When an array, map or bstr was opened, nothing was done but note
603 * the position. This function goes back to that position and inserts
604 * the CBOR Head with the major type and length.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000605 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700606static void
607QCBOREncode_Private_InsertCBORHead(QCBOREncodeContext *pMe,
608 uint8_t uMajorType,
609 size_t uLen)
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000610{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700611 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700612 return;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000613 }
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700614
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600615 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
616 uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
617 }
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800618
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700619 /* A stack buffer large enough for a CBOR head (9 bytes) */
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800620 UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800621
622 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
623 uMajorType,
624 0,
625 uLen);
626
627 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800628 * save object code. It is very clear that pBufferForEncodedHead is
629 * the correct size. If EncodedHead == NULLUsefulBufC then
630 * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
Laurence Lundblade9e2f7082021-05-17 02:10:48 -0700631 * security hole introduced.
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800632 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700633 UsefulOutBuf_InsertUsefulBuf(&(pMe->OutBuf),
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800634 EncodedHead,
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700635 Nesting_GetStartPos(&(pMe->nesting)));
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800636
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700637 Nesting_Decrease(&(pMe->nesting));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000638}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639
Laurence Lundblade241705e2018-12-30 18:56:14 -0800640
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800641/**
642 * @brief Increment item counter for maps and arrays.
643 *
644 * @param pMe QCBOR encoding context.
645 *
646 * This is mostly a separate function to make code more readable and
647 * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800648 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700649static void
650QCBOREncode_Private_IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800651{
652#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
653 if(pMe->uError == QCBOR_SUCCESS) {
654 pMe->uError = Nesting_Increment(&(pMe->nesting));
655 }
656#else
657 (void)Nesting_Increment(&(pMe->nesting));
658#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
659}
660
661
662/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800663 * Public functions for adding unsigned integers. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700665void
666QCBOREncode_AddUInt64(QCBOREncodeContext *pMe, const uint64_t uValue)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700668 QCBOREncode_Private_AppendCBORHead(pMe,
669 CBOR_MAJOR_TYPE_POSITIVE_INT,
670 uValue,
671 0);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800672
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700673 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700674}
675
Laurence Lundblade56230d12018-11-01 11:14:51 +0700676
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700677/*
Laurence Lundblade2d493002024-02-01 11:09:17 -0700678 * Public functions for adding negative integers. See qcbor/qcbor_encode.h
679 */
680void QCBOREncode_AddNegativeUInt64(QCBOREncodeContext *pMe, const uint64_t uValue)
681{
Laurence Lundblade8e5f42d2024-02-11 14:25:32 -0800682#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
683 if(!(pMe->uAllow & QCBOR_ENCODE_ALLOW_65_BIG_NEG)) {
684 pMe->uError = QCBOR_ERR_NOT_ALLOWED;
685 return;
686 }
687#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
688
Laurence Lundblade2d493002024-02-01 11:09:17 -0700689 // TODO: Error out in dCBOR mode
690 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_NEGATIVE_INT, uValue, 0);
691
692 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
693}
694
695
696/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800697 * Public functions for adding signed integers. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -0800698 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700699void
700QCBOREncode_AddInt64(QCBOREncodeContext *pMe, const int64_t nNum)
Laurence Lundblade067035b2018-11-28 17:35:25 -0800701{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800702 uint8_t uMajorType;
703 uint64_t uValue;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800704
705 if(nNum < 0) {
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700706 /* In CBOR -1 encodes as 0x00 with major type negative int.
707 * First add one as a signed integer because that will not
Laurence Lundblade2d493002024-02-01 11:09:17 -0700708 * overflow. Then change the sign as needed for encoding (the
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700709 * opposite order, changing the sign and subtracting, can cause
Laurence Lundblade2d493002024-02-01 11:09:17 -0700710 * an overflow when encoding INT64_MIN). */
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700711 int64_t nTmp = nNum + 1;
712 uValue = (uint64_t)-nTmp;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800713 uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
714 } else {
715 uValue = (uint64_t)nNum;
716 uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
717 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700718 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uValue, 0);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800719
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700720 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800721}
722
723
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700724/**
725 * @brief Semi-private method to add a buffer full of bytes to encoded output.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800726 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700727 * @param[in] pMe The encoding context to add the integer to.
728 * @param[in] uMajorType The CBOR major type of the bytes.
729 * @param[in] Bytes The bytes to add.
730 *
731 * Use QCBOREncode_AddText() or QCBOREncode_AddBytes() or
732 * QCBOREncode_AddEncoded() instead. They are inline functions that
733 * call this and supply the correct major type. This function is
734 * public to make the inline functions work to keep the overall code
735 * size down and because the C language has no way to make it private.
736 *
737 * If this is called the major type should be @c CBOR_MAJOR_TYPE_TEXT_STRING,
738 * @c CBOR_MAJOR_TYPE_BYTE_STRING or @c CBOR_MAJOR_NONE_TYPE_RAW. The
739 * last one is special for adding already-encoded CBOR.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800740 *
741 * This does the work of adding actual strings bytes to the CBOR
742 * output (as opposed to adding numbers and opening / closing
743 * aggregate types).
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800745 * There are four use cases:
746 * CBOR_MAJOR_TYPE_BYTE_STRING -- Byte strings
747 * CBOR_MAJOR_TYPE_TEXT_STRING -- Text strings
748 * CBOR_MAJOR_NONE_TYPE_RAW -- Already-encoded CBOR
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800749 *
750 * The first two add the head plus the actual bytes. The third just
751 * adds the bytes as the heas is presumed to be in the bytes. The
752 * fourth just adds the head for the very special case of
753 * QCBOREncode_AddBytesLenOnly().
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700754 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700755void
756QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pMe,
757 const uint8_t uMajorType,
758 const UsefulBufC Bytes)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800760 /* If it is not Raw CBOR, add the type and the length */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800761 if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
762 uint8_t uRealMajorType = uMajorType;
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700763 QCBOREncode_Private_AppendCBORHead(pMe, uRealMajorType, Bytes.len, 0);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800764 }
765
Laurence Lundblade15b93d42024-02-07 17:39:10 -0800766 /* Actually add the bytes */
767 UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Bytes);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800768
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700769 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770}
771
Laurence Lundbladecafcfe12018-10-31 21:59:50 +0700772
Laurence Lundblade55a24832018-10-30 04:35:08 +0700773/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800774 * Public functions for adding a tag. See qcbor/qcbor_encode.h
Laurence Lundblade55a24832018-10-30 04:35:08 +0700775 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700776void
777QCBOREncode_AddTag(QCBOREncodeContext *pMe, const uint64_t uTag)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700778{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700779 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_TAG, uTag, 0);
Laurence Lundblade55a24832018-10-30 04:35:08 +0700780}
781
782
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700783/**
784 * @brief Semi-private method to add simple types.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800785 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700786 * @param[in] pMe The encoding context to add the simple value to.
787 * @param[in] uMinLen Minimum encoding size for uNum. Usually 0.
788 * @param[in] uNum One of CBOR_SIMPLEV_FALSE through _UNDEF or other.
789 *
790 * This is used to add simple types like true and false.
791 *
792 * Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(),
793 * QCBOREncode_AddUndef() instead of this.
794 *
795 * This function can add simple values that are not defined by CBOR
796 * yet. This expansion point in CBOR should not be used unless they are
797 * standardized.
798 *
799 * Error handling is the same as QCBOREncode_AddInt64().
Laurence Lundblade56230d12018-11-01 11:14:51 +0700800 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700801void
802QCBOREncode_Private_AddType7(QCBOREncodeContext *pMe,
803 const uint8_t uMinLen,
804 const uint64_t uNum)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700805{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800806#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700807 if(pMe->uError == QCBOR_SUCCESS) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700808 if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700809 pMe->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800810 return;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700811 }
Laurence Lundblade487930f2018-11-30 11:01:45 -0800812 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800813#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
814
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800815 /* AppendCBORHead() does endian swapping for the float / double */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700816 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_SIMPLE, uNum, uMinLen);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800817
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700818 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundblade55a24832018-10-30 04:35:08 +0700819}
820
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700821
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200822#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700823/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800824 * Public functions for adding a double. See qcbor/qcbor_encode.h
825 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700826void
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700827QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pMe, double dNum)
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700828{
Laurence Lundblade240ca822024-01-16 11:11:00 -0700829#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
830 if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
831 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
832 return;
833 }
834#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
835
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700836 QCBOREncode_Private_AddType7(pMe,
837 sizeof(uint64_t),
838 UsefulBufUtil_CopyDoubleToUint64(dNum));
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700839}
840
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700841
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700842/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800843 * Public functions for adding a double. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700845void
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700846QCBOREncode_AddDouble(QCBOREncodeContext *pMe, double dNum)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847{
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700848#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade240ca822024-01-16 11:11:00 -0700849 IEEE754_union FloatResult;
850 bool bNoNaNPayload;
851 struct IEEE754_ToInt IntResult;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700852
Laurence Lundblade8e5f42d2024-02-11 14:25:32 -0800853#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
854 if(IEEE754_IsNotStandardDoubleNaN(dNum) && !(pMe->uAllow & QCBOR_ENCODE_ALLOW_NAN_PAYLOAD)) {
855 pMe->uError = QCBOR_ERR_NOT_ALLOWED;
856 return;
857 }
858#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
859
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700860 if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
Laurence Lundblade240ca822024-01-16 11:11:00 -0700861 IntResult = IEEE754_DoubleToInt(dNum);
862 switch(IntResult.type) {
863 case IEEE754_ToInt_IS_INT:
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700864 QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
Laurence Lundblade240ca822024-01-16 11:11:00 -0700865 return;
866 case IEEE754_ToInt_IS_UINT:
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700867 QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
Laurence Lundblade240ca822024-01-16 11:11:00 -0700868 return;
Laurence Lundbladee75f5962024-02-15 17:51:32 -0800869 case IEEE754_ToInt_NAN:
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700870 dNum = NAN;
871 bNoNaNPayload = true;
872 break;
Laurence Lundblade240ca822024-01-16 11:11:00 -0700873 case IEEE754_ToInt_NO_CONVERSION:
874 bNoNaNPayload = true;
875 }
876 } else {
877 bNoNaNPayload = false;
878 }
879
880 FloatResult = IEEE754_DoubleToSmaller(dNum, true, bNoNaNPayload);
881
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700882 QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
Laurence Lundblade240ca822024-01-16 11:11:00 -0700883
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800884#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700885 QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800886#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700887}
Laurence Lundblade9682a532020-06-06 18:33:04 -0700888
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700889
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700890
891
892/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800893 * Public functions for adding a float. See qcbor/qcbor_encode.h
894 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700895void
896QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pMe, const float fNum)
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700897{
Laurence Lundblade240ca822024-01-16 11:11:00 -0700898#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
899 if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
900 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
901 return;
902 }
903#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700904 QCBOREncode_Private_AddType7(pMe,
905 sizeof(uint32_t),
906 UsefulBufUtil_CopyFloatToUint32(fNum));
Laurence Lundblade9682a532020-06-06 18:33:04 -0700907}
908
909
910/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800911 * Public functions for adding a float. See qcbor/qcbor_encode.h
Laurence Lundblade9682a532020-06-06 18:33:04 -0700912 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700913void
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700914QCBOREncode_AddFloat(QCBOREncodeContext *pMe, float fNum)
Laurence Lundblade9682a532020-06-06 18:33:04 -0700915{
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700916#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade240ca822024-01-16 11:11:00 -0700917 IEEE754_union FloatResult;
918 bool bNoNaNPayload;
919 struct IEEE754_ToInt IntResult;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700920
Laurence Lundblade8e5f42d2024-02-11 14:25:32 -0800921#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
922 if(IEEE754_IsNotStandardSingleNaN(fNum) && !(pMe->uAllow & QCBOR_ENCODE_ALLOW_NAN_PAYLOAD)) {
923 pMe->uError = QCBOR_ERR_NOT_ALLOWED;
924 return;
925 }
926#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
927
928
Laurence Lundblade240ca822024-01-16 11:11:00 -0700929 if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
930 IntResult = IEEE754_SingleToInt(fNum);
931 switch(IntResult.type) {
932 case IEEE754_ToInt_IS_INT:
933 QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
934 return;
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700935 case IEEE754_ToInt_IS_UINT:
Laurence Lundblade240ca822024-01-16 11:11:00 -0700936 QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
937 return;
Laurence Lundbladee75f5962024-02-15 17:51:32 -0800938 case IEEE754_ToInt_NAN:
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700939 fNum = NAN;
940 bNoNaNPayload = true;
941 break;
Laurence Lundblade240ca822024-01-16 11:11:00 -0700942 case IEEE754_ToInt_NO_CONVERSION:
943 bNoNaNPayload = true;
944 }
945 } else {
946 bNoNaNPayload = false;
947 }
948
949 FloatResult = IEEE754_SingleToHalf(fNum, bNoNaNPayload);
950
Laurence Lundbladed98ffbf2024-01-27 23:27:59 -0700951 QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800952#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700953 QCBOREncode_AddFloatNoPreferred(pMe, fNum);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800954#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800955}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200956#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800957
958
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -0700959#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700960/**
961 * @brief Semi-private method to add bigfloats and decimal fractions.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800962 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700963 * @param[in] pMe The encoding context to add the value to.
964 * @param[in] uTag The type 6 tag indicating what this is to be.
965 * @param[in] BigNumMantissa Is @ref NULLUsefulBufC if mantissa is an
966 * @c int64_t or the actual big number mantissa
967 * if not.
968 * @param[in] bBigNumIsNegative This is @c true if the big number is negative.
969 * @param[in] nMantissa The @c int64_t mantissa if it is not a big number.
970 * @param[in] nExponent The exponent.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800971 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700972 * This outputs either the @ref CBOR_TAG_DECIMAL_FRACTION or
973 * @ref CBOR_TAG_BIGFLOAT tag. if @c uTag is @ref CBOR_TAG_INVALID64,
974 * then this outputs the "borrowed" content format.
975 *
976 * The tag content output by this is an array with two members, the
977 * exponent and then the mantissa. The mantissa can be either a big
978 * number or an @c int64_t.
979 *
980 * This implementation cannot output an exponent further from 0 than
981 * @c INT64_MAX.
982 *
983 * To output a mantissa that is between INT64_MAX and UINT64_MAX from 0,
984 * it must be as a big number.
985 *
986 * Typically, QCBOREncode_AddDecimalFraction(), QCBOREncode_AddBigFloat(),
987 * QCBOREncode_AddDecimalFractionBigNum() or QCBOREncode_AddBigFloatBigNum()
988 * is called instead of this.
Laurence Lundblade59289e52019-12-30 13:44:37 -0800989 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700990void
991QCBOREncode_Private_AddExpMantissa(QCBOREncodeContext *pMe,
992 const uint64_t uTag,
993 const UsefulBufC BigNumMantissa,
994 const bool bBigNumIsNegative,
995 const int64_t nMantissa,
996 const int64_t nExponent)
Laurence Lundblade59289e52019-12-30 13:44:37 -0800997{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800998 /* This is for encoding either a big float or a decimal fraction,
999 * both of which are an array of two items, an exponent and a
1000 * mantissa. The difference between the two is that the exponent
1001 * is base-2 for big floats and base-10 for decimal fractions, but
1002 * that has no effect on the code here.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001003 */
Laurence Lundbladeae66d3f2020-09-14 18:12:08 -07001004 if(uTag != CBOR_TAG_INVALID64) {
1005 QCBOREncode_AddTag(pMe, uTag);
1006 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001007 QCBOREncode_OpenArray(pMe);
1008 QCBOREncode_AddInt64(pMe, nExponent);
1009 if(!UsefulBuf_IsNULLC(BigNumMantissa)) {
1010 if(bBigNumIsNegative) {
1011 QCBOREncode_AddNegativeBignum(pMe, BigNumMantissa);
1012 } else {
1013 QCBOREncode_AddPositiveBignum(pMe, BigNumMantissa);
1014 }
1015 } else {
1016 QCBOREncode_AddInt64(pMe, nMantissa);
1017 }
1018 QCBOREncode_CloseArray(pMe);
1019}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07001020#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001021
1022
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001023/**
1024 * @brief Semi-private method to open a map, array or bstr-wrapped CBOR
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001025 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001026 * @param[in] pMe The context to add to.
1027 * @param[in] uMajorType The major CBOR type to close
1028 *
1029 * Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
1030 * QCBOREncode_BstrWrap() instead of this.
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001031 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001032void
1033QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pMe,
1034 const uint8_t uMajorType)
Laurence Lundblade067035b2018-11-28 17:35:25 -08001035{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001036 /* Add one item to the nesting level we are in for the new map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001037 QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
Laurence Lundbladed39cd392019-01-11 18:17:38 -08001038
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001039 /* The offset where the length of an array or map will get written
1040 * is stored in a uint32_t, not a size_t to keep stack usage
1041 * smaller. This checks to be sure there is no wrap around when
1042 * recording the offset. Note that on 64-bit machines CBOR larger
1043 * than 4GB can be encoded as long as no array/map offsets occur
1044 * past the 4GB mark, but the public interface says that the
1045 * maximum is 4GB to keep the discussion simpler.
1046 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001047 size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundbladed39cd392019-01-11 18:17:38 -08001048
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001049 /* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
1050 * code can run on a 32-bit machine and tests can pass on a 32-bit
1051 * machine. If it was exactly UINT32_MAX, then this code would not
1052 * compile or run on a 32-bit machine and an #ifdef or some machine
1053 * size detection would be needed reducing portability.
1054 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001055 if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001056 pMe->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001057
1058 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001059 /* Increase nesting level because this is a map or array. Cast
1060 * from size_t to uin32_t is safe because of check above.
1061 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001062 pMe->uError = Nesting_Increase(&(pMe->nesting), uMajorType, (uint32_t)uEndPosition);
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -08001063 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001064}
1065
Laurence Lundblade59289e52019-12-30 13:44:37 -08001066
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001067/**
1068 * @brief Semi-private method to open a map, array with indefinite length
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001069 *
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001070 * @param[in] pMe The context to add to.
1071 * @param[in] uMajorType The major CBOR type to close
1072 *
1073 * Call QCBOREncode_OpenArrayIndefiniteLength() or
1074 * QCBOREncode_OpenMapIndefiniteLength() instead of this.
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001075 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001076void
1077QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1078 const uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001079{
Laurence Lundblade240ca822024-01-16 11:11:00 -07001080#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
1081 if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
1082 pMe->uError = QCBOR_ERR_NOT_PREFERRED;
1083 return;
1084 }
1085#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001086 /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001087 QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, 0, 0);
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001088
1089 /* Call the definite-length opener just to do the bookkeeping for
1090 * nesting. It will record the position of the opening item in the
1091 * encoded output but this is not used when closing this open.
1092 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001093 QCBOREncode_Private_OpenMapOrArray(pMe, uMajorType);
Jan Jongboom4a93a662019-07-25 08:44:58 +02001094}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001095
Laurence Lundbladeee851742020-01-08 08:37:05 -08001096
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001097/**
Laurence Lundbladeff8106f2024-02-05 20:02:30 -07001098 * @brief Semi-private method to close a map, array or bstr wrapped CBOR.
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001099 *
1100 * @param[in] pMe The context to add to.
1101 * @param[in] uMajorType The major CBOR type to close.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001102 */
Laurence Lundblade240ca822024-01-16 11:11:00 -07001103void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001104QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pMe,
1105 const uint8_t uMajorType)
Laurence Lundblade240ca822024-01-16 11:11:00 -07001106{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001107 QCBOREncode_Private_InsertCBORHead(pMe, uMajorType, Nesting_GetCount(&(pMe->nesting)));
Laurence Lundblade240ca822024-01-16 11:11:00 -07001108}
1109
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001110
Laurence Lundbladeff8106f2024-02-05 20:02:30 -07001111/**
1112 * @brief Private method to close a map without sorting.
1113 *
1114 * @param[in] pMe The encode context with map to close.
1115 *
1116 * See QCBOREncode_SerializationCDE() implemention for explantion for why this exists in this form.
1117 */
1118static void
1119QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe)
Laurence Lundblade240ca822024-01-16 11:11:00 -07001120{
Laurence Lundbladeff8106f2024-02-05 20:02:30 -07001121 QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
Laurence Lundblade240ca822024-01-16 11:11:00 -07001122}
1123
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001124
1125/**
1126 * @brief Decode a CBOR item head.
1127 *
1128 * @param[in] pUInBuf UsefulInputBuf to read from.
1129 * @param[out] pnMajorType Major type of decoded head.
1130 * @param[out] puArgument Argument of decoded head.
1131 * @param[out] pnAdditionalInfo Additional info from decoded head.
1132 *
1133 * @return SUCCESS if a head was decoded
1134 * HIT_END if there were not enough bytes to decode a head
1135 * UNSUPPORTED if the decoded item is not one that is supported
1136 *
1137 * This is copied from qcbor_decode.c rather than referenced. This
1138 * makes the core decoder 60 bytes smaller because it gets inlined.
1139 * It would not get inlined if it was referenced. It is important to
1140 * make the core decoder as small as possible. The copy here does make
1141 * map sorting 200 bytes bigger, but map sorting is rarely used in
1142 * environments that need small object code. It would also make
1143 * qcbor_encode.c depend on qcbor_decode.c
1144 *
1145 * This is also super stable and tested. It implements the very
1146 * well-defined part of CBOR that will never change. So this won't
1147 * change.
1148 */
1149static QCBORError
1150QCBOREncodePriv_DecodeHead(UsefulInputBuf *pUInBuf,
1151 int *pnMajorType,
1152 uint64_t *puArgument,
1153 int *pnAdditionalInfo)
1154{
1155 QCBORError uReturn;
1156
1157 /* Get the initial byte that every CBOR data item has and break it
1158 * down. */
1159 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
1160 const int nTmpMajorType = nInitialByte >> 5;
1161 const int nAdditionalInfo = nInitialByte & 0x1f;
1162
1163 /* Where the argument accumulates */
1164 uint64_t uArgument;
1165
1166 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
1167 /* Need to get 1,2,4 or 8 additional argument bytes. Map
1168 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
1169 */
1170 static const uint8_t aIterate[] = {1,2,4,8};
1171
1172 /* Loop getting all the bytes in the argument */
1173 uArgument = 0;
1174 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
1175 /* This shift and add gives the endian conversion. */
1176 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
1177 }
1178 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
1179 /* The reserved and thus-far unused additional info values */
1180 uReturn = QCBOR_ERR_UNSUPPORTED;
1181 goto Done;
1182 } else {
1183 /* Less than 24, additional info is argument or 31, an
1184 * indefinite-length. No more bytes to get.
1185 */
1186 uArgument = (uint64_t)nAdditionalInfo;
1187 }
1188
1189 if(UsefulInputBuf_GetError(pUInBuf)) {
1190 uReturn = QCBOR_ERR_HIT_END;
1191 goto Done;
1192 }
1193
1194 /* All successful if arrived here. */
1195 uReturn = QCBOR_SUCCESS;
1196 *pnMajorType = nTmpMajorType;
1197 *puArgument = uArgument;
1198 *pnAdditionalInfo = nAdditionalInfo;
1199
1200Done:
1201 return uReturn;
1202}
1203
1204
1205/**
1206 * @brief Consume the next item from a UsefulInputBuf.
1207 *
1208 * @param[in] pInBuf UsefulInputBuf from which to consume item.
1209 *
1210 * Recursive, but stack usage is light and encoding depth limit
1211 */
1212static QCBORError
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001213QCBOR_Private_ConsumeNext(UsefulInputBuf *pInBuf)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001214{
1215 int nMajor;
1216 uint64_t uArgument;
1217 int nAdditional;
1218 uint16_t uItemCount;
1219 uint16_t uMul;
1220 uint16_t i;
1221 QCBORError uCBORError;
1222
1223 uCBORError = QCBOREncodePriv_DecodeHead(pInBuf, &nMajor, &uArgument, &nAdditional);
1224 if(uCBORError != QCBOR_SUCCESS) {
1225 return uCBORError;
1226 }
1227
1228 uMul = 1;
1229
1230 switch(nMajor) {
1231 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1232 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1233 break;
1234
1235 case CBOR_MAJOR_TYPE_SIMPLE:
1236 return uArgument == CBOR_SIMPLE_BREAK ? 1 : 0;
1237 break;
1238
1239 case CBOR_MAJOR_TYPE_BYTE_STRING:
1240 case CBOR_MAJOR_TYPE_TEXT_STRING:
1241 if(nAdditional == LEN_IS_INDEFINITE) {
1242 /* Segments of indefinite length */
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001243 while(QCBOR_Private_ConsumeNext(pInBuf) == 0);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001244 }
1245 (void)UsefulInputBuf_GetBytes(pInBuf, uArgument);
1246 break;
1247
1248 case CBOR_MAJOR_TYPE_TAG:
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001249 QCBOR_Private_ConsumeNext(pInBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001250 break;
1251
1252 case CBOR_MAJOR_TYPE_MAP:
1253 uMul = 2;
1254 /* Fallthrough */
1255 case CBOR_MAJOR_TYPE_ARRAY:
1256 uItemCount = (uint16_t)uArgument * uMul;
1257 if(nAdditional == LEN_IS_INDEFINITE) {
1258 uItemCount = UINT16_MAX;
1259 }
1260 for(i = uItemCount; i > 0; i--) {
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001261 if(QCBOR_Private_ConsumeNext(pInBuf)) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001262 /* End of indefinite length */
1263 break;
1264 }
1265 }
1266 break;
1267 }
1268
1269 return QCBOR_SUCCESS;
1270}
1271
1272
1273/**
1274 * @brief Decoded next item to get its length.
1275 *
1276 * Decode the next item in map no matter what type it is. It works
1277 * recursively when an item is a map or array It returns offset just
1278 * past the item decoded or zero there are no more items in the output
1279 * buffer.
1280 *
1281 * This doesn't distinguish between end of the input and an error
1282 * because it is used to decode stuff we encoded into a buffer, not
1283 * stuff that came in from outside. We still want a check for safety
1284 * in case of bugs here, but it is OK to report end of input on error.
1285 */
1286static uint32_t
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001287QCBOREncode_Private_DecodeNextInMap(QCBOREncodeContext *pMe, uint32_t uStart)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001288{
1289 UsefulInputBuf InBuf;
1290 UsefulBufC EncodedMapBytes;
1291 QCBORError uCBORError;
1292
1293 EncodedMapBytes = UsefulOutBuf_OutUBufOffset(&(pMe->OutBuf), uStart);
1294 if(UsefulBuf_IsNULLC(EncodedMapBytes)) {
1295 return 0;
1296 }
1297
1298 UsefulInputBuf_Init(&InBuf, EncodedMapBytes);
1299
1300 /* This is always used on maps, so consume two, the label and the value */
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001301 uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001302 if(uCBORError) {
1303 return 0;
1304 }
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001305 uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001306 if(uCBORError) {
1307 return 0;
1308 }
1309
1310 /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
1311 return (uint32_t)UsefulInputBuf_Tell(&InBuf);
1312}
1313
1314
1315/**
1316 * @brief Sort items lexographically by encoded labels.
1317 *
1318 * @param[in] pMe Encoding context.
1319 * @param[in] uStart Offset in outbuf of first item for sorting.
1320 *
1321 * This reaches into the UsefulOutBuf in the encoding context and
1322 * sorts encoded CBOR items. The byte offset start of the items is at
1323 * @c uStart and it goes to the end of valid bytes in the
1324 * UsefulOutBuf.
1325 */
1326static void
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001327QCBOREncode_Private_SortMap(QCBOREncodeContext *pMe, uint32_t uStart)
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001328{
1329 bool bSwapped;
1330 int nComparison;
1331 uint32_t uLen2;
1332 uint32_t uLen1;
1333 uint32_t uStart1;
1334 uint32_t uStart2;
1335
1336 if(pMe->uError != QCBOR_SUCCESS) {
1337 return;
1338 }
1339
1340 /* Bubble sort because the sizes of all the items are not the
1341 * same. It works with adjacent pairs so the swap is not too
1342 * difficult even though sizes are different.
1343 *
1344 * While bubble sort is n-squared, it seems OK here because n will
1345 * usually be small and the comparison and swap functions aren't
1346 * too CPU intensive.
1347 *
1348 * Another approach would be to have an array of offsets to the
1349 * items. However this requires memory allocation and the swap
1350 * operation for quick sort or such is complicated because the item
1351 * sizes are not the same and overlap may occur in the bytes being
1352 * swapped.
1353 */
1354 do {
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001355 uLen1 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001356 if(uLen1 == 0) {
1357 /* It's an empty map. Nothing to do. */
1358 break;
1359 }
1360 uStart1 = uStart;
1361 uStart2 = uStart1 + uLen1;
1362 bSwapped = false;
1363
1364 while(1) {
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001365 uLen2 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001366 if(uLen2 == 0) {
1367 break;
1368 }
1369
1370 nComparison = UsefulOutBuf_Compare(&(pMe->OutBuf), uStart1, uStart2);
1371 if(nComparison < 0) {
1372 UsefulOutBuf_Swap(&(pMe->OutBuf), uStart1, uStart2, uStart2 + uLen2);
1373 uStart1 = uStart1 + uLen2;
1374 bSwapped = true;
1375 } else {
1376 uStart1 = uStart2;
1377 }
1378 uStart2 = uStart2 + uLen2;
1379 }
1380 } while(bSwapped);
1381}
1382
1383
1384/*
1385 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1386 */
1387void QCBOREncode_CloseAndSortMap(QCBOREncodeContext *pMe)
1388{
1389 uint32_t uStart;
1390
1391 /* The Header for the map we are about to sort hasn't been
1392 * inserted yet, so uStart is the position of the first item
1393 * and the end out the UsefulOutBuf data is the end of the
1394 * items we are about to sort.
1395 */
1396 uStart = Nesting_GetStartPos(&(pMe->nesting));
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001397 QCBOREncode_Private_SortMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001398
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001399 QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_TYPE_MAP, Nesting_GetCount(&(pMe->nesting)));
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001400}
1401
1402
1403/*
1404 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1405 */
1406void QCBOREncode_CloseAndSortMapIndef(QCBOREncodeContext *pMe)
1407{
1408 uint32_t uStart;
1409
1410 uStart = Nesting_GetStartPos(&(pMe->nesting));
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001411 QCBOREncode_Private_SortMap(pMe, uStart);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001412
Laurence Lundblade3b703b82024-01-27 20:17:20 -07001413 QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001414}
1415
1416
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001417/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001418 * Public functions for closing bstr wrapping. See qcbor/qcbor_encode.h
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001419 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001420void
1421QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pMe,
1422 const bool bIncludeCBORHead,
1423 UsefulBufC *pWrappedCBOR)
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001424{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001425 const size_t uInsertPosition = Nesting_GetStartPos(&(pMe->nesting));
1426 const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001427
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001428 /* This subtraction can't go negative because the UsefulOutBuf
1429 * always only grows and never shrinks. UsefulOutBut itself also
1430 * has defenses such that it won't write where it should not even
1431 * if given incorrect input lengths.
1432 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001433 const size_t uBstrLen = uEndPosition - uInsertPosition;
1434
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001435 /* Actually insert */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001436 QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001437
1438 if(pWrappedCBOR) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001439 /* Return pointer and length to the enclosed encoded CBOR. The
1440 * intended use is for it to be hashed (e.g., SHA-256) in a COSE
1441 * implementation. This must be used right away, as the pointer
1442 * and length go invalid on any subsequent calls to this
1443 * function because there might be calls to
1444 * InsertEncodedTypeAndNumber() that slides data to the right.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001445 */
1446 size_t uStartOfNew = uInsertPosition;
1447 if(!bIncludeCBORHead) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001448 /* Skip over the CBOR head to just get the inserted bstr */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001449 const size_t uNewEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001450 uStartOfNew += uNewEndPosition - uEndPosition;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001451 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001452 const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001453 *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uStartOfNew);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001454 }
1455}
1456
Laurence Lundbladeee851742020-01-08 08:37:05 -08001457
Jan Jongboom4a93a662019-07-25 08:44:58 +02001458/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001459 * Public function for canceling a bstr wrap. See qcbor/qcbor_encode.h
1460 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001461void
1462QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pMe)
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001463{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001464 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, CBOR_MAJOR_TYPE_BYTE_STRING)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001465 return;
1466 }
1467
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001468#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001469 const size_t uCurrent = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
1470 if(pMe->nesting.pCurrentNesting->uStart != uCurrent) {
1471 pMe->uError = QCBOR_ERR_CANNOT_CANCEL;
1472 return;
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001473 }
1474 /* QCBOREncode_CancelBstrWrap() can't correctly undo
1475 * QCBOREncode_BstrWrapInMap() or QCBOREncode_BstrWrapInMapN(). It
1476 * can't undo the labels they add. It also doesn't catch the error
1477 * of using it this way. QCBOREncode_CancelBstrWrap() is used
1478 * infrequently and the the result is incorrect CBOR, not a
1479 * security hole, so no extra code or state is added to handle this
1480 * condition.
1481 */
1482#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
1483
1484 Nesting_Decrease(&(pMe->nesting));
1485 Nesting_Decrement(&(pMe->nesting));
1486}
1487
1488
1489/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001490 * Public function for opening a byte string. See qcbor/qcbor_encode.h
1491 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001492void
1493QCBOREncode_OpenBytes(QCBOREncodeContext *pMe, UsefulBuf *pPlace)
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001494{
1495 *pPlace = UsefulOutBuf_GetOutPlace(&(pMe->OutBuf));
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001496#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Paul Liétar79789772022-07-26 20:33:18 +01001497 uint8_t uMajorType = Nesting_GetMajorType(&(pMe->nesting));
1498 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
Laurence Lundblade716d10c2024-02-07 16:54:42 -08001499 /* It's OK to nest a byte string in any type but
1500 * another open byte string. */
Paul Liétar79789772022-07-26 20:33:18 +01001501 pMe->uError = QCBOR_ERR_OPEN_BYTE_STRING;
1502 return;
1503 }
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001504#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
1505
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001506 QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001507}
1508
1509
1510/*
1511 * Public function for closing a byte string. See qcbor/qcbor_encode.h
1512 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001513void
1514QCBOREncode_CloseBytes(QCBOREncodeContext *pMe, const size_t uAmount)
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001515{
1516 UsefulOutBuf_Advance(&(pMe->OutBuf), uAmount);
1517 if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
1518 /* Advance too far. Normal off-end error handling in effect here. */
1519 return;
1520 }
1521
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001522 QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001523}
1524
1525
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001526/**
1527 * @brief Semi-private method to close a map, array with indefinite length
1528 *
1529 * @param[in] pMe The context to add to.
1530 * @param[in] uMajorType The major CBOR type to close.
1531 *
1532 * Call QCBOREncode_CloseArrayIndefiniteLength() or
1533 * QCBOREncode_CloseMapIndefiniteLength() instead of this.
Jan Jongboom4a93a662019-07-25 08:44:58 +02001534 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001535void
1536QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
1537 const uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001538{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001539 if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001540 return;
Jan Jongboom4a93a662019-07-25 08:44:58 +02001541 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001542
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001543 /* Append the break marker (0xff for both arrays and maps) */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001544 QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001545 Nesting_Decrease(&(pMe->nesting));
Jan Jongboom4a93a662019-07-25 08:44:58 +02001546}
1547
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001548
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001549/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001550 * Public function to finish and get the encoded result. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001551 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001552QCBORError
1553QCBOREncode_Finish(QCBOREncodeContext *pMe, UsefulBufC *pEncodedCBOR)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001554{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001555 QCBORError uReturn = QCBOREncode_GetErrorState(pMe);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001556
Laurence Lundblade067035b2018-11-28 17:35:25 -08001557 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001558 goto Done;
Laurence Lundblade067035b2018-11-28 17:35:25 -08001559 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001560
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001561#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001562 if(Nesting_IsInNest(&(pMe->nesting))) {
Laurence Lundblade067035b2018-11-28 17:35:25 -08001563 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001564 goto Done;
1565 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001566#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001567
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001568 *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001569
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001570Done:
Laurence Lundblade067035b2018-11-28 17:35:25 -08001571 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001572}
1573
Laurence Lundblade0595e932018-11-02 22:22:47 +07001574
Laurence Lundblade067035b2018-11-28 17:35:25 -08001575/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001576 * Public functions to get size of the encoded result. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -08001577 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001578QCBORError
1579QCBOREncode_FinishGetSize(QCBOREncodeContext *pMe, size_t *puEncodedLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001580{
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001581 UsefulBufC Enc;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001582
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001583 QCBORError nReturn = QCBOREncode_Finish(pMe, &Enc);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001584
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001585 if(nReturn == QCBOR_SUCCESS) {
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001586 *puEncodedLen = Enc.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001587 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001588
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001589 return nReturn;
1590}