blob: 024d65bbbe9e50ac38bfe26cfa5bb68fb887e06a [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 Lundbladed6e13022023-11-26 10:14:02 -07003 Copyright (c) 2018-2023, 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 Lundbladeb69cad72018-09-13 11:09:01 -070038
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080039/**
40 * @file qcbor_encode.c
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080041 *
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080042 * The entire implementation of the QCBOR encoder.
43 */
44
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080047 * == Nesting Tracking ==
48 *
49 * The following functions and data type QCBORTrackNesting implement
50 * the nesting management for encoding.
51 *
52 * CBOR's two nesting types, arrays and maps, are tracked here. There
53 * is a limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and
54 * maps that can be nested in one encoding so the encoding context
55 * stays small enough to fit on the stack.
56 *
57 * When an array/map is opened, pCurrentNesting points to the element
58 * in pArrays that records the type, start position and accumulates a
59 * count of the number of items added. When closed the start position
60 * is used to go back and fill in the type and number of items in the
61 * array/map.
62 *
63 * Encoded output can be a CBOR Sequence (RFC 8742) in which case
64 * there is no top-level array or map. It starts out with a string,
65 * integer or other non-aggregate type. It may have an array or map
66 * other than at the start, in which case that nesting is tracked
67 * here.
68 *
69 * QCBOR has a special feature to allow constructing byte string
70 * wrapped CBOR directly into the output buffer, so no extra buffer is
71 * needed for byte string wrapping. This is implemented as nesting
72 * with the type CBOR_MAJOR_TYPE_BYTE_STRING and is tracked here. Byte
73 * string wrapped CBOR is used by COSE for data that is to be hashed.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070074 */
Laurence Lundblade274ddef2022-05-17 09:12:23 -070075static inline void
76Nesting_Init(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070077{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080078 /* Assumes pNesting has been zeroed. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070079 pNesting->pCurrentNesting = &pNesting->pArrays[0];
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080080 /* Implied CBOR array at the top nesting level. This is never
81 * returned, but makes the item count work correctly.
82 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070083 pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY;
84}
85
Laurence Lundblade274ddef2022-05-17 09:12:23 -070086static inline uint8_t
87Nesting_Increase(QCBORTrackNesting *pNesting,
88 uint8_t uMajorType,
89 uint32_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070090{
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070091 if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) {
Laurence Lundblade29497c02020-07-11 15:44:03 -070092 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070093 } else {
94 pNesting->pCurrentNesting++;
95 pNesting->pCurrentNesting->uCount = 0;
96 pNesting->pCurrentNesting->uStart = uPos;
97 pNesting->pCurrentNesting->uMajorType = uMajorType;
Laurence Lundblade29497c02020-07-11 15:44:03 -070098 return QCBOR_SUCCESS;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100}
101
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700102static inline void
103Nesting_Decrease(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104{
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700105 if(pNesting->pCurrentNesting > &pNesting->pArrays[0]) {
106 pNesting->pCurrentNesting--;
107 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700108}
109
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700110static inline uint8_t
111Nesting_Increment(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700112{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800113#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -0800114 if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700115 return QCBOR_ERR_ARRAY_TOO_LONG;
116 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800117#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800118
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700119 pNesting->pCurrentNesting->uCount++;
Laurence Lundblade2c40ab82018-12-30 14:20:29 -0800120
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700121 return QCBOR_SUCCESS;
122}
123
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700124static inline void
125Nesting_Decrement(QCBORTrackNesting *pNesting)
Laurence Lundblade8d3b8552021-06-10 11:11:54 -0700126{
127 /* No error check for going below 0 here needed because this
128 * is only used by QCBOREncode_CancelBstrWrap() and it checks
129 * the nesting level before calling this. */
130 pNesting->pCurrentNesting->uCount--;
131}
132
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700133static inline uint16_t
134Nesting_GetCount(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700135{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800136 /* The nesting count recorded is always the actual number of
137 * individual data items in the array or map. For arrays CBOR uses
138 * the actual item count. For maps, CBOR uses the number of pairs.
139 * This function returns the number needed for the CBOR encoding,
140 * so it divides the number of items by two for maps to get the
141 * number of pairs.
142 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800143 if(pNesting->pCurrentNesting->uMajorType == CBOR_MAJOR_TYPE_MAP) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800144 /* Cast back to uint16_t after integer promotion from bit shift */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800145 return (uint16_t)(pNesting->pCurrentNesting->uCount >> 1);
146 } else {
147 return pNesting->pCurrentNesting->uCount;
148 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700149}
150
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700151static inline uint32_t
152Nesting_GetStartPos(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153{
154 return pNesting->pCurrentNesting->uStart;
155}
156
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800157#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700158static inline uint8_t
159Nesting_GetMajorType(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700160{
161 return pNesting->pCurrentNesting->uMajorType;
162}
163
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700164static inline bool
165Nesting_IsInNest(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700166{
Laurence Lundbladeee851742020-01-08 08:37:05 -0800167 return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? false : true;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700168}
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800169#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700170
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700171
172
173
174/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800175 * == Major CBOR Types ==
176 *
177 * Encoding of the major CBOR types is by these functions:
178 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800179 * CBOR Major Type Public Function
180 * 0 QCBOREncode_AddUInt64()
181 * 0, 1 QCBOREncode_AddUInt64(), QCBOREncode_AddInt64()
182 * 2, 3 QCBOREncode_AddBuffer()
183 * 4, 5 QCBOREncode_OpenMapOrArray(), QCBOREncode_CloseMapOrArray(),
184 * QCBOREncode_OpenMapOrArrayIndefiniteLength(),
185 * QCBOREncode_CloseMapOrArrayIndefiniteLength()
186 * 6 QCBOREncode_AddTag()
187 * 7 QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
188 * QCBOREncode_AddDoubleNoPreferred(),
189 * QCBOREncode_AddFloatNoPreferred(), QCBOREncode_AddType7()
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800190 *
191 * Additionally, encoding of decimal fractions and bigfloats is by
192 * QCBOREncode_AddExponentAndMantissa() and byte strings that wrap
193 * encoded CBOR are handled by QCBOREncode_OpenMapOrArray() and
194 * QCBOREncode_CloseBstrWrap2().
195 *
196 *
197 * == Error Tracking Plan ==
198 *
199 * Errors are tracked internally and not returned until
200 * QCBOREncode_Finish() or QCBOREncode_GetErrorState() is called. The
201 * CBOR errors are in me->uError. UsefulOutBuf also tracks whether
202 * the buffer is full or not in its context. Once either of these
203 * errors is set they are never cleared. Only QCBOREncode_Init()
204 * resets them. Or said another way, they must never be cleared or
205 * we'll tell the caller all is good when it is not.
206 *
207 * Only one error code is reported by QCBOREncode_Finish() even if
208 * there are multiple errors. The last one set wins. The caller might
209 * have to fix one error to reveal the next one they have to fix.
210 * This is OK.
211 *
212 * The buffer full error tracked by UsefulBuf is only pulled out of
213 * UsefulBuf in QCBOREncode_Finish() so it is the one that usually
214 * wins. UsefulBuf will never go off the end of the buffer even if it
215 * is called again and again when full.
216 *
217 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS disables about half of the error
218 * checks here to reduce code size by about 150 bytes leaving only the
219 * checks for size to avoid buffer overflow. If the calling code is
220 * completely correct, checks are completely unnecessary. For
221 * example, there is no need to check that all the opens are matched
222 * by a close.
223 *
224 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS also disables the check for more
225 * than QCBOR_MAX_ITEMS_IN_ARRAY in an array. Since
226 * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,535) it is very unlikely
227 * to be reached. If it is reached, the count will wrap around to zero
228 * and CBOR that is not well formed will be produced, but there will
229 * be no buffers overrun and new security issues in the code.
230 *
231 * The 8 errors returned here fall into three categories:
232 *
233 * Sizes
234 * QCBOR_ERR_BUFFER_TOO_LARGE -- Encoded output exceeded UINT32_MAX
235 * QCBOR_ERR_BUFFER_TOO_SMALL -- Output buffer too small
236 * QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Nesting > QCBOR_MAX_ARRAY_NESTING1
237 * QCBOR_ERR_ARRAY_TOO_LONG -- Too many items added to an array/map [1]
238 *
239 * Nesting constructed incorrectly
240 * QCBOR_ERR_TOO_MANY_CLOSES -- More close calls than opens [1]
241 * QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open [1]
242 * QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes [1]
243 *
244 * Would generate not-well-formed CBOR
245 * QCBOR_ERR_ENCODE_UNSUPPORTED -- Simple type between 24 and 31 [1]
246 *
247 * [1] indicated disabled by QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700248 */
249
250
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800252 Public function for initialization. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700253 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700254void QCBOREncode_Init(QCBOREncodeContext *me, UsefulBuf Storage)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700255{
256 memset(me, 0, sizeof(QCBOREncodeContext));
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -0800257 UsefulOutBuf_Init(&(me->OutBuf), Storage);
258 Nesting_Init(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700259}
260
261
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000262/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800263 * Public function to encode a CBOR head. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700264 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000265UsefulBufC QCBOREncode_EncodeHead(UsefulBuf buffer,
266 uint8_t uMajorType,
267 uint8_t uMinLen,
268 uint64_t uArgument)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700269{
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800270 /*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800271 * == Description of the CBOR Head ==
272 *
273 * The head of a CBOR data item
274 * +---+-----+ +--------+ +--------+ +--------+ +--------+
275 * |M T| A R G U M E N T . . . |
276 * +---+-----+ +--------+ +--------+ +--------+ ... +--------+
277 *
278 * Every CBOR data item has a "head". It is made up of the "major
279 * type" and the "argument".
280 *
281 * The major type indicates whether the data item is an integer,
282 * string, array or such. It is encoded in 3 bits giving it a range
283 * from 0 to 7. 0 indicates the major type is a positive integer,
284 * 1 a negative integer, 2 a byte string and so on.
285 *
286 * These 3 bits are the first part of the "initial byte" in a data
287 * item. Every data item has an initial byte, and some only have
288 * the initial byte.
289 *
290 * The argument is essentially a number between 0 and UINT64_MAX
291 * (18446744073709551615). This number is interpreted to mean
292 * different things for the different major types. For major type
293 * 0, a positive integer, it is value of the data item. For major
294 * type 2, a byte string, it is the length in bytes of the byte
295 * string. For major type 4, an array, it is the number of data
296 * items in the array.
297 *
298 * Special encoding is used so that the argument values less than
299 * 24 can be encoded very compactly in the same byte as the major
300 * type is encoded. When the lower 5 bits of the initial byte have
301 * a value less than 24, then that is the value of the argument.
302 *
303 * If the lower 5 bits of the initial byte are less than 24, then
304 * they are the value of the argument. This allows integer values 0
305 * - 23 to be CBOR encoded in just one byte.
306 *
307 * When the value of lower 5 bits are 24, 25, 26, or 27 the
308 * argument is encoded in 1, 2, 4 or 8 bytes following the initial
309 * byte in network byte order (bit endian). The cases when it is
310 * 28, 29 and 30 are reserved for future use. The value 31 is a
311 * special indicator for indefinite length strings, arrays and
312 * maps.
313 *
314 * The lower 5 bits are called the "additional information."
315 *
316 * Thus the CBOR head may be 1, 2, 3, 5 or 9 bytes long.
317 *
318 * It is legal in CBOR to encode the argument using any of these
319 * lengths even if it could be encoded in a shorter length. For
320 * example it is legal to encode a data item representing the
321 * positive integer 0 in 9 bytes even though it could be encoded in
322 * only 0. This is legal to allow for for very simple code or even
323 * hardware-only implementations that just output a register
324 * directly.
325 *
326 * CBOR defines preferred encoding as the encoding of the argument
327 * in the smallest number of bytes needed to encode it.
328 *
329 * This function takes the major type and argument as inputs and
330 * outputs the encoded CBOR head for them. It does conversion to
331 * network byte order. It implements CBOR preferred encoding,
332 * outputting the shortest representation of the argument.
333 *
334 * == Endian Conversion ==
335 *
336 * This code does endian conversion without hton() or knowing the
337 * endianness of the machine by using masks and shifts. This avoids
338 * the dependency on hton() and the mess of figuring out how to
339 * find the machine's endianness.
340 *
341 * This is a good efficient implementation on little-endian
342 * machines. A faster and smaller implementation is possible on
343 * big-endian machines because CBOR/network byte order is
344 * big-endian. However big-endian machines are uncommon.
345 *
346 * On x86, this is about 150 bytes instead of 500 bytes for the
347 * original, more formal unoptimized code.
348 *
349 * This also does the CBOR preferred shortest encoding for integers
350 * and is called to do endian conversion for floats.
351 *
352 * It works backwards from the least significant byte to the most
353 * significant byte.
354 *
355 * == Floating Point ==
356 *
357 * When the major type is 7 and the 5 lower bits have the values
358 * 25, 26 or 27, the argument is a floating-point number that is
359 * half, single or double-precision. Note that it is not the
360 * conversion from a floating-point value to an integer value like
361 * converting 0x00 to 0.00, it is the interpretation of the bits in
362 * the argument as an IEEE 754 float-point number.
363 *
364 * Floating-point numbers must be converted to network byte
365 * order. That is accomplished here by exactly the same code that
366 * converts integer arguments to network byte order.
367 *
368 * There is preferred encoding for floating-point numbers in CBOR,
369 * but it is very different than for integers and it is not
370 * implemented here. Half-precision is preferred to
371 * single-precision which is preferred to double-precision only if
372 * the conversion can be performed without loss of precision. Zero
373 * and infinity can always be converted to half-precision, without
374 * loss but 3.141592653589 cannot.
375 *
376 * The way this function knows to not do preferred encoding on the
377 * argument passed here when it is a floating point number is the
378 * uMinLen parameter. It should be 2, 4 or 8 for half, single and
379 * double precision floating point values. This prevents and the
380 * incorrect removal of leading zeros when encoding arguments that
381 * are floating-point numbers.
382 *
383 * == Use of Type int and Static Analyzers ==
384 *
385 * The type int is used here for several variables because of the
386 * way integer promotion works in C for variables that are uint8_t
387 * or uint16_t. The basic rule is that they will always be promoted
388 * to int if they will fit. These integer variables here need only
389 * hold values less than 255 so they will always fit into an int.
390 *
391 * Most of values stored are never negative, so one might think
392 * that unsigned int would be more correct than int. However the C
393 * integer promotion rules only promote to unsigned int if the
394 * result won't fit into an int even if the promotion is for an
395 * unsigned variable like uint8_t.
396 *
397 * By declaring these int, there are few implicit conversions and
398 * fewer casts needed. Code size is reduced a little. It makes
399 * static analyzers happier.
400 *
401 * Note also that declaring these uint8_t won't stop integer wrap
402 * around if the code is wrong. It won't make the code more
403 * correct.
404 *
405 * https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
406 * https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
407 *
408 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800409 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800410
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800411 /* The buffer must have room for the largest CBOR HEAD + one
412 * extra. The one extra is needed for this code to work as it does
413 * a pre-decrement.
414 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000415 if(buffer.len < QCBOR_HEAD_BUFFER_SIZE) {
416 return NULLUsefulBufC;
417 }
418
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800419 /* Pointer to last valid byte in the buffer */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000420 uint8_t * const pBufferEnd = &((uint8_t *)buffer.ptr)[QCBOR_HEAD_BUFFER_SIZE-1];
421
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800422 /* Point to the last byte and work backwards */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000423 uint8_t *pByte = pBufferEnd;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800424 /* The 5 bits in the initial byte that are not the major type */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800425 int nAdditionalInfo;
Laurence Lundblade2c40ab82018-12-30 14:20:29 -0800426
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800427 if(uMajorType > QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800428 /* Special case for start & end of indefinite length */
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800429 uMajorType = uMajorType - QCBOR_INDEFINITE_LEN_TYPE_MODIFIER;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800430 /* This takes advantage of design of CBOR where additional info
431 * is 31 for both opening and closing indefinite length
432 * maps and arrays.
433 */
434 #if CBOR_SIMPLE_BREAK != LEN_IS_INDEFINITE
435 #error additional info for opening array not the same as for closing
436 #endif
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800437 nAdditionalInfo = CBOR_SIMPLE_BREAK;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800438
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000439 } else if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800440 /* Simple case where argument is < 24 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000441 nAdditionalInfo = (int)uArgument;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800442
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800443 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800444 /* This encodes the argument in 1,2,4 or 8 bytes. The outer loop
445 * runs once for 1 byte and 4 times for 8 bytes. The inner loop
446 * runs 1, 2 or 4 times depending on outer loop counter. This
447 * works backwards shifting 8 bits off the argument being
448 * encoded at a time until all bits from uArgument have been
449 * encoded and the minimum encoding size is reached. Minimum
450 * encoding size is for floating-point numbers that have some
451 * zero-value bytes that must be output.
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800452 */
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800453 static const uint8_t aIterate[] = {1,1,2,4};
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000454
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800455 /* uMinLen passed in is unsigned, but goes negative in the loop
456 * so it must be converted to a signed value.
457 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000458 int nMinLen = (int)uMinLen;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800459 int i;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000460 for(i = 0; uArgument || nMinLen > 0; i++) {
461 const int nIterations = (int)aIterate[i];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800462 for(int j = 0; j < nIterations; j++) {
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000463 *--pByte = (uint8_t)(uArgument & 0xff);
464 uArgument = uArgument >> 8;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800465 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800466 nMinLen -= nIterations;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800467 }
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800468
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800469 nAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700470 }
Laurence Lundbladef970f1d2018-12-14 01:44:23 -0800471
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800472 /* This expression integer-promotes to type int. The code above in
473 * function guarantees that nAdditionalInfo will never be larger
474 * than 0x1f. The caller may pass in a too-large uMajor type. The
475 * conversion to unint8_t will cause an integer wrap around and
476 * incorrect CBOR will be generated, but no security issue will
477 * occur.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800478 */
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800479 const int nInitialByte = (uMajorType << 5) + nAdditionalInfo;
480 *--pByte = (uint8_t)nInitialByte;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800481
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000482#ifdef EXTRA_ENCODE_HEAD_CHECK
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800483 /* This is a sanity check that can be turned on to verify the
484 * pointer math in this function is not going wrong. Turn it on and
485 * run the whole test suite to perform the check.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800486 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000487 if(pBufferEnd - pByte > 9 || pBufferEnd - pByte < 1 || pByte < (uint8_t *)buffer.ptr) {
488 return NULLUsefulBufC;
489 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800490#endif /* EXTRA_ENCODE_HEAD_CHECK */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800491
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800492 /* Length will not go negative because the loops run for at most 8 decrements
493 * of pByte, only one other decrement is made, and the array is sized
494 * for this.
495 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000496 return (UsefulBufC){pByte, (size_t)(pBufferEnd - pByte)};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700497}
498
499
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000500/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800501 * @brief Append the CBOR head, the major type and argument
502 *
503 * @param me Encoder context.
504 * @param uMajorType Major type to insert.
505 * @param uArgument The argument (an integer value or a length).
506 * @param uMinLen The minimum number of bytes for encoding the CBOR argument.
507 *
508 * This formats the CBOR "head" and appends it to the output.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000509 */
510static void AppendCBORHead(QCBOREncodeContext *me, uint8_t uMajorType, uint64_t uArgument, uint8_t uMinLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700511{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800512 /* A stack buffer large enough for a CBOR head */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000513 UsefulBuf_MAKE_STACK_UB (pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
514
515 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
516 uMajorType,
517 uMinLen,
518 uArgument);
519
520 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800521 * save object code. It is very clear that pBufferForEncodedHead is
522 * the correct size. If EncodedHead == NULLUsefulBufC then
523 * UsefulOutBuf_AppendUsefulBuf() will do nothing so there is no
524 * security hole introduced.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000525 */
526
527 UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), EncodedHead);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528}
529
530
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000531/**
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700532 * @brief Check for errors when decreasing nesting.
533 *
534 * @param pMe QCBOR encoding context.
535 * @param uMajorType The major type of the nesting.
536 *
537 * Check that there is no previous error, that there is actually some
538 * nesting and that the major type of the opening of the nesting
539 * matches the major type of the nesting being closed.
540 *
541 * This is called when closing maps, arrays, byte string wrapping and
542 * open/close of byte strings.
543 */
544bool
545CheckDecreaseNesting(QCBOREncodeContext *pMe, uint8_t uMajorType)
546{
547#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
548 if(pMe->uError != QCBOR_SUCCESS) {
549 return true;
550 }
551
552 if(!Nesting_IsInNest(&(pMe->nesting))) {
553 pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
554 return true;
555 }
556
557 if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
558 pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
559 return true;
560 }
561
562#else
563 /* None of these checks are performed if the encode guards are
564 * turned off as they all relate to correct calling.
565 *
566 * Turning off all these checks does not turn off any checking for
567 * buffer overflows or pointer issues.
568 */
569
570 (void)uMajorType;
571 (void)pMe;
572#endif
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700573
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700574 return false;
575}
576
577
578/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800579 * @brief Insert the CBOR head for a map, array or wrapped bstr
580 *
581 * @param me QCBOR encoding context.
582 * @param uMajorType One of CBOR_MAJOR_TYPE_XXXX.
583 * @param uLen The length of the data item.
584 *
585 * When an array, map or bstr was opened, nothing was done but note
586 * the position. This function goes back to that position and inserts
587 * the CBOR Head with the major type and length.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000588 */
589static void InsertCBORHead(QCBOREncodeContext *me, uint8_t uMajorType, size_t uLen)
590{
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700591 if(CheckDecreaseNesting(me, uMajorType)) {
592 return;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000593 }
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700594
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600595 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
596 uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
597 }
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800598
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700599 /* A stack buffer large enough for a CBOR head (9 bytes) */
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800600 UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800601
602 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
603 uMajorType,
604 0,
605 uLen);
606
607 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800608 * save object code. It is very clear that pBufferForEncodedHead is
609 * the correct size. If EncodedHead == NULLUsefulBufC then
610 * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
Laurence Lundblade9e2f7082021-05-17 02:10:48 -0700611 * security hole introduced.
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800612 */
613 UsefulOutBuf_InsertUsefulBuf(&(me->OutBuf),
614 EncodedHead,
615 Nesting_GetStartPos(&(me->nesting)));
616
617 Nesting_Decrease(&(me->nesting));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000618}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700619
Laurence Lundblade241705e2018-12-30 18:56:14 -0800620
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800621/**
622 * @brief Increment item counter for maps and arrays.
623 *
624 * @param pMe QCBOR encoding context.
625 *
626 * This is mostly a separate function to make code more readable and
627 * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800628 */
629static inline void IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
630{
631#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
632 if(pMe->uError == QCBOR_SUCCESS) {
633 pMe->uError = Nesting_Increment(&(pMe->nesting));
634 }
635#else
636 (void)Nesting_Increment(&(pMe->nesting));
637#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
638}
639
640
641/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800642 * Public functions for adding unsigned integers. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700643 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800644void QCBOREncode_AddUInt64(QCBOREncodeContext *me, uint64_t uValue)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800646 AppendCBORHead(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue, 0);
647
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800648 IncrementMapOrArrayCount(me);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649}
650
Laurence Lundblade56230d12018-11-01 11:14:51 +0700651
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652/*
Laurence Lundblade7c077562024-01-29 21:49:13 -0700653 * Public functions for adding negative integers. See qcbor/qcbor_encode.h
654 */
655void QCBOREncode_AddNegativeUInt64(QCBOREncodeContext *pMe, const uint64_t uValue)
656{
657 AppendCBORHead(pMe, CBOR_MAJOR_TYPE_NEGATIVE_INT, uValue, 0);
658
659 IncrementMapOrArrayCount(pMe);
660}
661
662
663/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800664 * Public functions for adding signed integers. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -0800665 */
666void QCBOREncode_AddInt64(QCBOREncodeContext *me, int64_t nNum)
667{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800668 uint8_t uMajorType;
669 uint64_t uValue;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800670
671 if(nNum < 0) {
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700672 /* In CBOR -1 encodes as 0x00 with major type negative int.
673 * First add one as a signed integer because that will not
Laurence Lundblade7c077562024-01-29 21:49:13 -0700674 * overflow. Then change the sign as needed for encoding (the
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700675 * opposite order, changing the sign and subtracting, can cause
Laurence Lundblade7c077562024-01-29 21:49:13 -0700676 * an overflow when encoding INT64_MIN). */
Laurence Lundblade9c5c0ef2022-12-23 17:56:27 -0700677 int64_t nTmp = nNum + 1;
678 uValue = (uint64_t)-nTmp;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800679 uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
680 } else {
681 uValue = (uint64_t)nNum;
682 uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
683 }
684 AppendCBORHead(me, uMajorType, uValue, 0);
685
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800686 IncrementMapOrArrayCount(me);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800687}
688
689
690/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800691 * Semi-private function. It is exposed to user of the interface, but
692 * one of its inline wrappers will usually be called instead of this.
693 *
694 * See qcbor/qcbor_encode.h
695 *
696 * This does the work of adding actual strings bytes to the CBOR
697 * output (as opposed to adding numbers and opening / closing
698 * aggregate types).
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800699
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800700 * There are four use cases:
701 * CBOR_MAJOR_TYPE_BYTE_STRING -- Byte strings
702 * CBOR_MAJOR_TYPE_TEXT_STRING -- Text strings
703 * CBOR_MAJOR_NONE_TYPE_RAW -- Already-encoded CBOR
704 * CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY -- Special case
705 *
706 * The first two add the head plus the actual bytes. The third just
707 * adds the bytes as the heas is presumed to be in the bytes. The
708 * fourth just adds the head for the very special case of
709 * QCBOREncode_AddBytesLenOnly().
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800711void QCBOREncode_AddBuffer(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC Bytes)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700712{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800713 /* If it is not Raw CBOR, add the type and the length */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800714 if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
715 uint8_t uRealMajorType = uMajorType;
716 if(uRealMajorType == CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
717 uRealMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
718 }
719 AppendCBORHead(me, uRealMajorType, Bytes.len, 0);
720 }
721
722 if(uMajorType != CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800723 /* Actually add the bytes */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800724 UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes);
725 }
726
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800727 IncrementMapOrArrayCount(me);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700728}
729
Laurence Lundbladecafcfe12018-10-31 21:59:50 +0700730
Laurence Lundblade55a24832018-10-30 04:35:08 +0700731/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800732 * Public functions for adding a tag. See qcbor/qcbor_encode.h
Laurence Lundblade55a24832018-10-30 04:35:08 +0700733 */
734void QCBOREncode_AddTag(QCBOREncodeContext *me, uint64_t uTag)
735{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800736 AppendCBORHead(me, CBOR_MAJOR_TYPE_TAG, uTag, 0);
Laurence Lundblade55a24832018-10-30 04:35:08 +0700737}
738
739
Laurence Lundblade56230d12018-11-01 11:14:51 +0700740/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800741 * Semi-private function. It is exposed to user of the interface, but
742 * one of its inline wrappers will usually be called instead of this.
743 *
744 * See header qcbor/qcbor_encode.h
Laurence Lundblade56230d12018-11-01 11:14:51 +0700745 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000746void QCBOREncode_AddType7(QCBOREncodeContext *me, uint8_t uMinLen, uint64_t uNum)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700747{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800748#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade487930f2018-11-30 11:01:45 -0800749 if(me->uError == QCBOR_SUCCESS) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700750 if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700751 me->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800752 return;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700753 }
Laurence Lundblade487930f2018-11-30 11:01:45 -0800754 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800755#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
756
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800757 /* AppendCBORHead() does endian swapping for the float / double */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800758 AppendCBORHead(me, CBOR_MAJOR_TYPE_SIMPLE, uNum, uMinLen);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800759
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800760 IncrementMapOrArrayCount(me);
Laurence Lundblade55a24832018-10-30 04:35:08 +0700761}
762
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200764#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700765/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800766 * Public functions for adding a double. See qcbor/qcbor_encode.h
767 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700768void QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *me, double dNum)
769{
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700770 QCBOREncode_AddType7(me,
771 sizeof(uint64_t),
772 UsefulBufUtil_CopyDoubleToUint64(dNum));
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700773}
774
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700775
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700776/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800777 * Public functions for adding a double. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700778 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800779void QCBOREncode_AddDouble(QCBOREncodeContext *me, double dNum)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700780{
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700781#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700782 const IEEE754_union uNum = IEEE754_DoubleToSmaller(dNum, true);
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700783
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700784 QCBOREncode_AddType7(me, (uint8_t)uNum.uSize, uNum.uValue);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800785#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700786 QCBOREncode_AddDoubleNoPreferred(me, dNum);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800787#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700788}
Laurence Lundblade9682a532020-06-06 18:33:04 -0700789
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700790
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700791/*
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700792 * Public functions for adding a double. See qcbor/qcbor_encode.h
793 */
794void QCBOREncode_AddDoubleDeterministic(QCBOREncodeContext *me, double dNum)
795{
796 if(dNum <= (double)UINT64_MAX && dNum >= 0) {
797 uint64_t uNum = (uint64_t)dNum;
798 if((double)uNum == dNum) {
799 QCBOREncode_AddUInt64(me, uNum);
800 return;
801 }
802 /* Fall through */
803 } else if(dNum >= (double)INT64_MIN && dNum < 0) {
804 int64_t nNum = (int64_t)dNum;
805 if((double)nNum == dNum) {
806 QCBOREncode_AddInt64(me, nNum);
807 return;
808 }
809 /* Fall through */
810 }
811 //const IEEE754_union uNum = IEEE754_DoubleToSmallest(dNum);
812
813 //QCBOREncode_AddType7(me, uNum.uSize, uNum.uValue);
814}
815
816
817/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800818 * Public functions for adding a float. See qcbor/qcbor_encode.h
819 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700820void QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *me, float fNum)
821{
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700822 QCBOREncode_AddType7(me,
823 sizeof(uint32_t),
824 UsefulBufUtil_CopyFloatToUint32(fNum));
Laurence Lundblade9682a532020-06-06 18:33:04 -0700825}
826
827
828/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800829 * Public functions for adding a float. See qcbor/qcbor_encode.h
Laurence Lundblade9682a532020-06-06 18:33:04 -0700830 */
831void QCBOREncode_AddFloat(QCBOREncodeContext *me, float fNum)
832{
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700833#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700834 const IEEE754_union uNum = IEEE754_SingleToHalf(fNum);
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700835
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700836 QCBOREncode_AddType7(me, (uint8_t)uNum.uSize, uNum.uValue);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800837#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700838 QCBOREncode_AddFloatNoPreferred(me, fNum);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800839#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800840}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200841#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800842
843
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -0700844#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade59289e52019-12-30 13:44:37 -0800845/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800846 * Semi-public function. It is exposed to the user of the interface,
847 * but one of the inline wrappers will usually be called rather than
848 * this.
849 *
850 * See qcbor/qcbor_encode.h
851 *
852 * Improvement: create another version of this that only takes a big
853 * number mantissa and converts the output to a type 0 or 1 integer
854 * when mantissa is small enough.
Laurence Lundblade59289e52019-12-30 13:44:37 -0800855 */
856void QCBOREncode_AddExponentAndMantissa(QCBOREncodeContext *pMe,
857 uint64_t uTag,
858 UsefulBufC BigNumMantissa,
859 bool bBigNumIsNegative,
860 int64_t nMantissa,
861 int64_t nExponent)
862{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800863 /* This is for encoding either a big float or a decimal fraction,
864 * both of which are an array of two items, an exponent and a
865 * mantissa. The difference between the two is that the exponent
866 * is base-2 for big floats and base-10 for decimal fractions, but
867 * that has no effect on the code here.
Laurence Lundbladeee851742020-01-08 08:37:05 -0800868 */
Laurence Lundbladeae66d3f2020-09-14 18:12:08 -0700869 if(uTag != CBOR_TAG_INVALID64) {
870 QCBOREncode_AddTag(pMe, uTag);
871 }
Laurence Lundblade59289e52019-12-30 13:44:37 -0800872 QCBOREncode_OpenArray(pMe);
873 QCBOREncode_AddInt64(pMe, nExponent);
874 if(!UsefulBuf_IsNULLC(BigNumMantissa)) {
875 if(bBigNumIsNegative) {
876 QCBOREncode_AddNegativeBignum(pMe, BigNumMantissa);
877 } else {
878 QCBOREncode_AddPositiveBignum(pMe, BigNumMantissa);
879 }
880 } else {
881 QCBOREncode_AddInt64(pMe, nMantissa);
882 }
883 QCBOREncode_CloseArray(pMe);
884}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -0700885#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -0800886
887
Laurence Lundblade067035b2018-11-28 17:35:25 -0800888/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800889 * Semi-public function. It is exposed to the user of the interface,
890 * but one of the inline wrappers will usually be called rather than
891 * this.
892 *
893 * See qcbor/qcbor_encode.h
Laurence Lundblade274ddef2022-05-17 09:12:23 -0700894 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800895void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType)
896{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800897 /* Add one item to the nesting level we are in for the new map or array */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800898 IncrementMapOrArrayCount(me);
Laurence Lundbladed39cd392019-01-11 18:17:38 -0800899
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800900 /* The offset where the length of an array or map will get written
901 * is stored in a uint32_t, not a size_t to keep stack usage
902 * smaller. This checks to be sure there is no wrap around when
903 * recording the offset. Note that on 64-bit machines CBOR larger
904 * than 4GB can be encoded as long as no array/map offsets occur
905 * past the 4GB mark, but the public interface says that the
906 * maximum is 4GB to keep the discussion simpler.
907 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800908 size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
Laurence Lundbladed39cd392019-01-11 18:17:38 -0800909
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800910 /* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
911 * code can run on a 32-bit machine and tests can pass on a 32-bit
912 * machine. If it was exactly UINT32_MAX, then this code would not
913 * compile or run on a 32-bit machine and an #ifdef or some machine
914 * size detection would be needed reducing portability.
915 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800916 if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
917 me->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
918
919 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800920 /* Increase nesting level because this is a map or array. Cast
921 * from size_t to uin32_t is safe because of check above.
922 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800923 me->uError = Nesting_Increase(&(me->nesting), uMajorType, (uint32_t)uEndPosition);
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -0800924 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925}
926
Laurence Lundblade59289e52019-12-30 13:44:37 -0800927
Jan Jongboom4a93a662019-07-25 08:44:58 +0200928/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800929 * Semi-public function. It is exposed to the user of the interface,
930 * but one of the inline wrappers will usually be called rather than
931 * this.
932 *
933 * See qcbor/qcbor_encode.h
934 */
Jan Jongboom4a93a662019-07-25 08:44:58 +0200935void QCBOREncode_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *me, uint8_t uMajorType)
936{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800937 /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000938 AppendCBORHead(me, uMajorType, 0, 0);
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800939
940 /* Call the definite-length opener just to do the bookkeeping for
941 * nesting. It will record the position of the opening item in the
942 * encoded output but this is not used when closing this open.
943 */
Jan Jongboom4a93a662019-07-25 08:44:58 +0200944 QCBOREncode_OpenMapOrArray(me, uMajorType);
945}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946
Laurence Lundbladeee851742020-01-08 08:37:05 -0800947
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700948/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800949 * Public functions for closing arrays and maps. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700950 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000951void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType)
Laurence Lundbladea954db92018-09-28 19:27:31 -0700952{
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000953 InsertCBORHead(me, uMajorType, Nesting_GetCount(&(me->nesting)));
954}
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700957
958/**
959 * @brief Decode a CBOR item head.
960 *
961 * @param[in] pUInBuf UsefulInputBuf to read from.
962 * @param[out] pnMajorType Major type of decoded head.
963 * @param[out] puArgument Argument of decoded head.
964 * @param[out] pnAdditionalInfo Additional info from decoded head.
965 *
966 * @return SUCCESS if a head was decoded
967 * HIT_END if there were not enough bytes to decode a head
968 * UNSUPPORTED if the decoded item is not one that is supported
969 *
970 * This is copied from qcbor_decode.c rather than referenced. This
971 * makes the core decoder 60 bytes smaller because it gets inlined.
972 * It would not get inlined if it was referenced. It is important to
973 * make the core decoder as small as possible. The copy here does make
974 * map sorting 200 bytes bigger, but map sorting is rarely used in
975 * environments that need small object code. It would also make
976 * qcbor_encode.c depend on qcbor_decode.c
977 *
978 * This is also super stable and tested. It implements the very
979 * well-defined part of CBOR that will never change. So this won't
980 * change.
981 */
982static QCBORError
983QCBOREncodePriv_DecodeHead(UsefulInputBuf *pUInBuf,
984 int *pnMajorType,
985 uint64_t *puArgument,
986 int *pnAdditionalInfo)
987{
988 QCBORError uReturn;
989
990 /* Get the initial byte that every CBOR data item has and break it
991 * down. */
992 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
993 const int nTmpMajorType = nInitialByte >> 5;
994 const int nAdditionalInfo = nInitialByte & 0x1f;
995
996 /* Where the argument accumulates */
997 uint64_t uArgument;
998
999 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
1000 /* Need to get 1,2,4 or 8 additional argument bytes. Map
1001 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
1002 */
1003 static const uint8_t aIterate[] = {1,2,4,8};
1004
1005 /* Loop getting all the bytes in the argument */
1006 uArgument = 0;
1007 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
1008 /* This shift and add gives the endian conversion. */
1009 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
1010 }
1011 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
1012 /* The reserved and thus-far unused additional info values */
1013 uReturn = QCBOR_ERR_UNSUPPORTED;
1014 goto Done;
1015 } else {
1016 /* Less than 24, additional info is argument or 31, an
1017 * indefinite-length. No more bytes to get.
1018 */
1019 uArgument = (uint64_t)nAdditionalInfo;
1020 }
1021
1022 if(UsefulInputBuf_GetError(pUInBuf)) {
1023 uReturn = QCBOR_ERR_HIT_END;
1024 goto Done;
1025 }
1026
1027 /* All successful if arrived here. */
1028 uReturn = QCBOR_SUCCESS;
1029 *pnMajorType = nTmpMajorType;
1030 *puArgument = uArgument;
1031 *pnAdditionalInfo = nAdditionalInfo;
1032
1033Done:
1034 return uReturn;
1035}
1036
1037
1038/**
1039 * @brief Consume the next item from a UsefulInputBuf.
1040 *
1041 * @param[in] pInBuf UsefulInputBuf from which to consume item.
1042 *
1043 * Recursive, but stack usage is light and encoding depth limit
1044 */
1045static QCBORError
1046QCBOREncodePriv_ConsumeNext(UsefulInputBuf *pInBuf)
1047{
1048 int nMajor;
1049 uint64_t uArgument;
1050 int nAdditional;
1051 uint16_t uItemCount;
1052 uint16_t uMul;
1053 uint16_t i;
1054 QCBORError uCBORError;
1055
1056 uCBORError = QCBOREncodePriv_DecodeHead(pInBuf, &nMajor, &uArgument, &nAdditional);
1057 if(uCBORError != QCBOR_SUCCESS) {
1058 return uCBORError;
1059 }
1060
1061 uMul = 1;
1062
1063 switch(nMajor) {
1064 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1065 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1066 break;
1067
1068 case CBOR_MAJOR_TYPE_SIMPLE:
1069 return uArgument == CBOR_SIMPLE_BREAK ? 1 : 0;
1070 break;
1071
1072 case CBOR_MAJOR_TYPE_BYTE_STRING:
1073 case CBOR_MAJOR_TYPE_TEXT_STRING:
1074 if(nAdditional == LEN_IS_INDEFINITE) {
1075 /* Segments of indefinite length */
1076 while(QCBOREncodePriv_ConsumeNext(pInBuf) == 0);
1077 }
1078 (void)UsefulInputBuf_GetBytes(pInBuf, uArgument);
1079 break;
1080
1081 case CBOR_MAJOR_TYPE_TAG:
1082 QCBOREncodePriv_ConsumeNext(pInBuf);
1083 break;
1084
1085 case CBOR_MAJOR_TYPE_MAP:
1086 uMul = 2;
1087 /* Fallthrough */
1088 case CBOR_MAJOR_TYPE_ARRAY:
1089 uItemCount = (uint16_t)uArgument * uMul;
1090 if(nAdditional == LEN_IS_INDEFINITE) {
1091 uItemCount = UINT16_MAX;
1092 }
1093 for(i = uItemCount; i > 0; i--) {
1094 if(QCBOREncodePriv_ConsumeNext(pInBuf)) {
1095 /* End of indefinite length */
1096 break;
1097 }
1098 }
1099 break;
1100 }
1101
1102 return QCBOR_SUCCESS;
1103}
1104
1105
1106/**
1107 * @brief Decoded next item to get its length.
1108 *
1109 * Decode the next item in map no matter what type it is. It works
1110 * recursively when an item is a map or array It returns offset just
1111 * past the item decoded or zero there are no more items in the output
1112 * buffer.
1113 *
1114 * This doesn't distinguish between end of the input and an error
1115 * because it is used to decode stuff we encoded into a buffer, not
1116 * stuff that came in from outside. We still want a check for safety
1117 * in case of bugs here, but it is OK to report end of input on error.
1118 */
1119static uint32_t
1120QCBOREncodePriv_DecodeNextInMap(QCBOREncodeContext *pMe, uint32_t uStart)
1121{
1122 UsefulInputBuf InBuf;
1123 UsefulBufC EncodedMapBytes;
1124 QCBORError uCBORError;
1125
1126 EncodedMapBytes = UsefulOutBuf_OutUBufOffset(&(pMe->OutBuf), uStart);
1127 if(UsefulBuf_IsNULLC(EncodedMapBytes)) {
1128 return 0;
1129 }
1130
1131 UsefulInputBuf_Init(&InBuf, EncodedMapBytes);
1132
1133 /* This is always used on maps, so consume two, the label and the value */
1134 uCBORError = QCBOREncodePriv_ConsumeNext(&InBuf);
1135 if(uCBORError) {
1136 return 0;
1137 }
1138 uCBORError = QCBOREncodePriv_ConsumeNext(&InBuf);
1139 if(uCBORError) {
1140 return 0;
1141 }
1142
1143 /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
1144 return (uint32_t)UsefulInputBuf_Tell(&InBuf);
1145}
1146
1147
1148/**
1149 * @brief Sort items lexographically by encoded labels.
1150 *
1151 * @param[in] pMe Encoding context.
1152 * @param[in] uStart Offset in outbuf of first item for sorting.
1153 *
1154 * This reaches into the UsefulOutBuf in the encoding context and
1155 * sorts encoded CBOR items. The byte offset start of the items is at
1156 * @c uStart and it goes to the end of valid bytes in the
1157 * UsefulOutBuf.
1158 */
1159static void
1160QCBOREncodePriv_SortMap(QCBOREncodeContext *pMe, uint32_t uStart)
1161{
1162 bool bSwapped;
1163 int nComparison;
1164 uint32_t uLen2;
1165 uint32_t uLen1;
1166 uint32_t uStart1;
1167 uint32_t uStart2;
1168
1169 if(pMe->uError != QCBOR_SUCCESS) {
1170 return;
1171 }
1172
1173 /* Bubble sort because the sizes of all the items are not the
1174 * same. It works with adjacent pairs so the swap is not too
1175 * difficult even though sizes are different.
1176 *
1177 * While bubble sort is n-squared, it seems OK here because n will
1178 * usually be small and the comparison and swap functions aren't
1179 * too CPU intensive.
1180 *
1181 * Another approach would be to have an array of offsets to the
1182 * items. However this requires memory allocation and the swap
1183 * operation for quick sort or such is complicated because the item
1184 * sizes are not the same and overlap may occur in the bytes being
1185 * swapped.
1186 */
1187 do {
1188 uLen1 = QCBOREncodePriv_DecodeNextInMap(pMe, uStart);
1189 if(uLen1 == 0) {
1190 /* It's an empty map. Nothing to do. */
1191 break;
1192 }
1193 uStart1 = uStart;
1194 uStart2 = uStart1 + uLen1;
1195 bSwapped = false;
1196
1197 while(1) {
1198 uLen2 = QCBOREncodePriv_DecodeNextInMap(pMe, uStart2);
1199 if(uLen2 == 0) {
1200 break;
1201 }
1202
1203 nComparison = UsefulOutBuf_Compare(&(pMe->OutBuf), uStart1, uStart2);
1204 if(nComparison < 0) {
1205 UsefulOutBuf_Swap(&(pMe->OutBuf), uStart1, uStart2, uStart2 + uLen2);
1206 uStart1 = uStart1 + uLen2;
1207 bSwapped = true;
1208 } else {
1209 uStart1 = uStart2;
1210 }
1211 uStart2 = uStart2 + uLen2;
1212 }
1213 } while(bSwapped);
1214}
1215
1216
1217/*
1218 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1219 */
1220void QCBOREncode_CloseAndSortMap(QCBOREncodeContext *pMe)
1221{
1222 uint32_t uStart;
1223
1224 /* The Header for the map we are about to sort hasn't been
1225 * inserted yet, so uStart is the position of the first item
1226 * and the end out the UsefulOutBuf data is the end of the
1227 * items we are about to sort.
1228 */
1229 uStart = Nesting_GetStartPos(&(pMe->nesting));
1230 QCBOREncodePriv_SortMap(pMe, uStart);
1231
1232 QCBOREncode_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
1233}
1234
1235
1236/*
1237 * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
1238 */
1239void QCBOREncode_CloseAndSortMapIndef(QCBOREncodeContext *pMe)
1240{
1241 uint32_t uStart;
1242
1243 uStart = Nesting_GetStartPos(&(pMe->nesting));
1244 QCBOREncodePriv_SortMap(pMe, uStart);
1245
1246 QCBOREncode_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
1247}
1248
1249
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001250/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001251 * Public functions for closing bstr wrapping. See qcbor/qcbor_encode.h
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001252 */
1253void QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *me, bool bIncludeCBORHead, UsefulBufC *pWrappedCBOR)
1254{
1255 const size_t uInsertPosition = Nesting_GetStartPos(&(me->nesting));
1256 const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001257
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001258 /* This subtraction can't go negative because the UsefulOutBuf
1259 * always only grows and never shrinks. UsefulOutBut itself also
1260 * has defenses such that it won't write where it should not even
1261 * if given incorrect input lengths.
1262 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001263 const size_t uBstrLen = uEndPosition - uInsertPosition;
1264
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001265 /* Actually insert */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001266 InsertCBORHead(me, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
1267
1268 if(pWrappedCBOR) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001269 /* Return pointer and length to the enclosed encoded CBOR. The
1270 * intended use is for it to be hashed (e.g., SHA-256) in a COSE
1271 * implementation. This must be used right away, as the pointer
1272 * and length go invalid on any subsequent calls to this
1273 * function because there might be calls to
1274 * InsertEncodedTypeAndNumber() that slides data to the right.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001275 */
1276 size_t uStartOfNew = uInsertPosition;
1277 if(!bIncludeCBORHead) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001278 /* Skip over the CBOR head to just get the inserted bstr */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001279 const size_t uNewEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
1280 uStartOfNew += uNewEndPosition - uEndPosition;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001281 }
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +00001282 const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(me->OutBuf));
1283 *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uStartOfNew);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001284 }
1285}
1286
Laurence Lundbladeee851742020-01-08 08:37:05 -08001287
Jan Jongboom4a93a662019-07-25 08:44:58 +02001288/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001289 * Public function for canceling a bstr wrap. See qcbor/qcbor_encode.h
1290 */
1291void QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pMe)
1292{
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001293 if(CheckDecreaseNesting(pMe, CBOR_MAJOR_TYPE_BYTE_STRING)) {
1294 return;
1295 }
1296
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001297#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001298 const size_t uCurrent = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
1299 if(pMe->nesting.pCurrentNesting->uStart != uCurrent) {
1300 pMe->uError = QCBOR_ERR_CANNOT_CANCEL;
1301 return;
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001302 }
1303 /* QCBOREncode_CancelBstrWrap() can't correctly undo
1304 * QCBOREncode_BstrWrapInMap() or QCBOREncode_BstrWrapInMapN(). It
1305 * can't undo the labels they add. It also doesn't catch the error
1306 * of using it this way. QCBOREncode_CancelBstrWrap() is used
1307 * infrequently and the the result is incorrect CBOR, not a
1308 * security hole, so no extra code or state is added to handle this
1309 * condition.
1310 */
1311#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
1312
1313 Nesting_Decrease(&(pMe->nesting));
1314 Nesting_Decrement(&(pMe->nesting));
1315}
1316
1317
1318/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001319 * Public function for opening a byte string. See qcbor/qcbor_encode.h
1320 */
1321void QCBOREncode_OpenBytes(QCBOREncodeContext *pMe, UsefulBuf *pPlace)
1322{
1323 *pPlace = UsefulOutBuf_GetOutPlace(&(pMe->OutBuf));
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001324#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Paul Liétar79789772022-07-26 20:33:18 +01001325 // TODO: is this right?
1326 uint8_t uMajorType = Nesting_GetMajorType(&(pMe->nesting));
1327 if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
1328 pMe->uError = QCBOR_ERR_OPEN_BYTE_STRING;
1329 return;
1330 }
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001331#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
1332
Paul Liétar79789772022-07-26 20:33:18 +01001333 QCBOREncode_OpenMapOrArray(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR);
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001334}
1335
1336
1337/*
1338 * Public function for closing a byte string. See qcbor/qcbor_encode.h
1339 */
1340void QCBOREncode_CloseBytes(QCBOREncodeContext *pMe, const size_t uAmount)
1341{
1342 UsefulOutBuf_Advance(&(pMe->OutBuf), uAmount);
1343 if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
1344 /* Advance too far. Normal off-end error handling in effect here. */
1345 return;
1346 }
1347
1348 InsertCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
1349}
1350
1351
1352/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001353 * Public function for closing arrays and maps. See qcbor/qcbor_encode.h
Jan Jongboom4a93a662019-07-25 08:44:58 +02001354 */
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001355void QCBOREncode_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe, uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +02001356{
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001357 if(CheckDecreaseNesting(pMe, uMajorType)) {
1358 return;
Jan Jongboom4a93a662019-07-25 08:44:58 +02001359 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001360
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001361 /* Append the break marker (0xff for both arrays and maps) */
Laurence Lundblade274ddef2022-05-17 09:12:23 -07001362 AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
1363 Nesting_Decrease(&(pMe->nesting));
Jan Jongboom4a93a662019-07-25 08:44:58 +02001364}
1365
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001366
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001367/*
Laurence Lundblade8d3b8552021-06-10 11:11:54 -07001368 * Public function to finish and get the encoded result. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001369 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001370QCBORError QCBOREncode_Finish(QCBOREncodeContext *me, UsefulBufC *pEncodedCBOR)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001371{
Laurence Lundbladef607a2a2019-07-05 21:25:25 -07001372 QCBORError uReturn = QCBOREncode_GetErrorState(me);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001373
Laurence Lundblade067035b2018-11-28 17:35:25 -08001374 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001375 goto Done;
Laurence Lundblade067035b2018-11-28 17:35:25 -08001376 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001377
Laurence Lundbladedaefdec2020-11-02 20:22:03 -08001378#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -08001379 if(Nesting_IsInNest(&(me->nesting))) {
Laurence Lundblade067035b2018-11-28 17:35:25 -08001380 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001381 goto Done;
1382 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001383#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001384
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001385 *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(me->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001386
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001387Done:
Laurence Lundblade067035b2018-11-28 17:35:25 -08001388 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001389}
1390
Laurence Lundblade0595e932018-11-02 22:22:47 +07001391
Laurence Lundblade067035b2018-11-28 17:35:25 -08001392/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -08001393 * Public functions to get size of the encoded result. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -08001394 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001395QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *me, size_t *puEncodedLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001396{
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001397 UsefulBufC Enc;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001398
Laurence Lundblade30816f22018-11-10 13:40:22 +07001399 QCBORError nReturn = QCBOREncode_Finish(me, &Enc);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001400
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001401 if(nReturn == QCBOR_SUCCESS) {
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001402 *puEncodedLen = Enc.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001403 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001404
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001405 return nReturn;
1406}