blob: ea94026ae72ae19eb3dc1144f5b0a15eb397e6f5 [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 Lundblade3f1318a2021-01-04 18:26:44 -08003 Copyright (c) 2018-2021, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_encode.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070035#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080038/**
39 * @file qcbor_encode.c
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080040 *
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080041 * The entire implementation of the QCBOR encoder.
42 */
43
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080046 * == Nesting Tracking ==
47 *
48 * The following functions and data type QCBORTrackNesting implement
49 * the nesting management for encoding.
50 *
51 * CBOR's two nesting types, arrays and maps, are tracked here. There
52 * is a limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and
53 * maps that can be nested in one encoding so the encoding context
54 * stays small enough to fit on the stack.
55 *
56 * When an array/map is opened, pCurrentNesting points to the element
57 * in pArrays that records the type, start position and accumulates a
58 * count of the number of items added. When closed the start position
59 * is used to go back and fill in the type and number of items in the
60 * array/map.
61 *
62 * Encoded output can be a CBOR Sequence (RFC 8742) in which case
63 * there is no top-level array or map. It starts out with a string,
64 * integer or other non-aggregate type. It may have an array or map
65 * other than at the start, in which case that nesting is tracked
66 * here.
67 *
68 * QCBOR has a special feature to allow constructing byte string
69 * wrapped CBOR directly into the output buffer, so no extra buffer is
70 * needed for byte string wrapping. This is implemented as nesting
71 * with the type CBOR_MAJOR_TYPE_BYTE_STRING and is tracked here. Byte
72 * string wrapped CBOR is used by COSE for data that is to be hashed.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070073 */
74inline static void Nesting_Init(QCBORTrackNesting *pNesting)
75{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080076 /* Assumes pNesting has been zeroed. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070077 pNesting->pCurrentNesting = &pNesting->pArrays[0];
Laurence Lundblade1fa579b2020-11-25 00:31:37 -080078 /* Implied CBOR array at the top nesting level. This is never
79 * returned, but makes the item count work correctly.
80 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070081 pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY;
82}
83
Laurence Lundblade29497c02020-07-11 15:44:03 -070084inline static uint8_t Nesting_Increase(QCBORTrackNesting *pNesting,
Laurence Lundblade2c40ab82018-12-30 14:20:29 -080085 uint8_t uMajorType,
86 uint32_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070087{
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070088 if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) {
Laurence Lundblade29497c02020-07-11 15:44:03 -070089 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070090 } else {
91 pNesting->pCurrentNesting++;
92 pNesting->pCurrentNesting->uCount = 0;
93 pNesting->pCurrentNesting->uStart = uPos;
94 pNesting->pCurrentNesting->uMajorType = uMajorType;
Laurence Lundblade29497c02020-07-11 15:44:03 -070095 return QCBOR_SUCCESS;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070096 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070097}
98
99inline static void Nesting_Decrease(QCBORTrackNesting *pNesting)
100{
101 pNesting->pCurrentNesting--;
102}
103
Laurence Lundblade29497c02020-07-11 15:44:03 -0700104inline static uint8_t Nesting_Increment(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700105{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800106#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -0800107 if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700108 return QCBOR_ERR_ARRAY_TOO_LONG;
109 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800110#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800111
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700112 pNesting->pCurrentNesting->uCount++;
Laurence Lundblade2c40ab82018-12-30 14:20:29 -0800113
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700114 return QCBOR_SUCCESS;
115}
116
Laurence Lundblade3ff969d2021-05-28 21:32:34 -0700117inline static uint8_t Nesting_Decrement(QCBORTrackNesting *pNesting)
118{
119#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
120 if(!pNesting->pCurrentNesting->uCount) {
121 return 99; // TODO: error
122 }
123#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
124
125 pNesting->pCurrentNesting->uCount--;
126
127 return QCBOR_SUCCESS;
128}
129
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700130inline static uint16_t Nesting_GetCount(QCBORTrackNesting *pNesting)
131{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800132 /* The nesting count recorded is always the actual number of
133 * individual data items in the array or map. For arrays CBOR uses
134 * the actual item count. For maps, CBOR uses the number of pairs.
135 * This function returns the number needed for the CBOR encoding,
136 * so it divides the number of items by two for maps to get the
137 * number of pairs.
138 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800139 if(pNesting->pCurrentNesting->uMajorType == CBOR_MAJOR_TYPE_MAP) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800140 /* Cast back to uint16_t after integer promotion from bit shift */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800141 return (uint16_t)(pNesting->pCurrentNesting->uCount >> 1);
142 } else {
143 return pNesting->pCurrentNesting->uCount;
144 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700145}
146
147inline static uint32_t Nesting_GetStartPos(QCBORTrackNesting *pNesting)
148{
149 return pNesting->pCurrentNesting->uStart;
150}
151
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800152#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153inline static uint8_t Nesting_GetMajorType(QCBORTrackNesting *pNesting)
154{
155 return pNesting->pCurrentNesting->uMajorType;
156}
157
Laurence Lundbladeee851742020-01-08 08:37:05 -0800158inline static bool Nesting_IsInNest(QCBORTrackNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700159{
Laurence Lundbladeee851742020-01-08 08:37:05 -0800160 return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? false : true;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700161}
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800162#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700163
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700164
165
166
167/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800168 * == Major CBOR Types ==
169 *
170 * Encoding of the major CBOR types is by these functions:
171 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800172 * CBOR Major Type Public Function
173 * 0 QCBOREncode_AddUInt64()
174 * 0, 1 QCBOREncode_AddUInt64(), QCBOREncode_AddInt64()
175 * 2, 3 QCBOREncode_AddBuffer()
176 * 4, 5 QCBOREncode_OpenMapOrArray(), QCBOREncode_CloseMapOrArray(),
177 * QCBOREncode_OpenMapOrArrayIndefiniteLength(),
178 * QCBOREncode_CloseMapOrArrayIndefiniteLength()
179 * 6 QCBOREncode_AddTag()
180 * 7 QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
181 * QCBOREncode_AddDoubleNoPreferred(),
182 * QCBOREncode_AddFloatNoPreferred(), QCBOREncode_AddType7()
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800183 *
184 * Additionally, encoding of decimal fractions and bigfloats is by
185 * QCBOREncode_AddExponentAndMantissa() and byte strings that wrap
186 * encoded CBOR are handled by QCBOREncode_OpenMapOrArray() and
187 * QCBOREncode_CloseBstrWrap2().
188 *
189 *
190 * == Error Tracking Plan ==
191 *
192 * Errors are tracked internally and not returned until
193 * QCBOREncode_Finish() or QCBOREncode_GetErrorState() is called. The
194 * CBOR errors are in me->uError. UsefulOutBuf also tracks whether
195 * the buffer is full or not in its context. Once either of these
196 * errors is set they are never cleared. Only QCBOREncode_Init()
197 * resets them. Or said another way, they must never be cleared or
198 * we'll tell the caller all is good when it is not.
199 *
200 * Only one error code is reported by QCBOREncode_Finish() even if
201 * there are multiple errors. The last one set wins. The caller might
202 * have to fix one error to reveal the next one they have to fix.
203 * This is OK.
204 *
205 * The buffer full error tracked by UsefulBuf is only pulled out of
206 * UsefulBuf in QCBOREncode_Finish() so it is the one that usually
207 * wins. UsefulBuf will never go off the end of the buffer even if it
208 * is called again and again when full.
209 *
210 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS disables about half of the error
211 * checks here to reduce code size by about 150 bytes leaving only the
212 * checks for size to avoid buffer overflow. If the calling code is
213 * completely correct, checks are completely unnecessary. For
214 * example, there is no need to check that all the opens are matched
215 * by a close.
216 *
217 * QCBOR_DISABLE_ENCODE_USAGE_GUARDS also disables the check for more
218 * than QCBOR_MAX_ITEMS_IN_ARRAY in an array. Since
219 * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,535) it is very unlikely
220 * to be reached. If it is reached, the count will wrap around to zero
221 * and CBOR that is not well formed will be produced, but there will
222 * be no buffers overrun and new security issues in the code.
223 *
224 * The 8 errors returned here fall into three categories:
225 *
226 * Sizes
227 * QCBOR_ERR_BUFFER_TOO_LARGE -- Encoded output exceeded UINT32_MAX
228 * QCBOR_ERR_BUFFER_TOO_SMALL -- Output buffer too small
229 * QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Nesting > QCBOR_MAX_ARRAY_NESTING1
230 * QCBOR_ERR_ARRAY_TOO_LONG -- Too many items added to an array/map [1]
231 *
232 * Nesting constructed incorrectly
233 * QCBOR_ERR_TOO_MANY_CLOSES -- More close calls than opens [1]
234 * QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open [1]
235 * QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes [1]
236 *
237 * Would generate not-well-formed CBOR
238 * QCBOR_ERR_ENCODE_UNSUPPORTED -- Simple type between 24 and 31 [1]
239 *
240 * [1] indicated disabled by QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700241 */
242
243
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700244/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800245 Public function for initialization. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700246 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700247void QCBOREncode_Init(QCBOREncodeContext *me, UsefulBuf Storage)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700248{
249 memset(me, 0, sizeof(QCBOREncodeContext));
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -0800250 UsefulOutBuf_Init(&(me->OutBuf), Storage);
251 Nesting_Init(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700252}
253
254
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000255/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800256 * Public function to encode a CBOR head. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700257 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000258UsefulBufC QCBOREncode_EncodeHead(UsefulBuf buffer,
259 uint8_t uMajorType,
260 uint8_t uMinLen,
261 uint64_t uArgument)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700262{
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800263 /*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800264 * == Description of the CBOR Head ==
265 *
266 * The head of a CBOR data item
267 * +---+-----+ +--------+ +--------+ +--------+ +--------+
268 * |M T| A R G U M E N T . . . |
269 * +---+-----+ +--------+ +--------+ +--------+ ... +--------+
270 *
271 * Every CBOR data item has a "head". It is made up of the "major
272 * type" and the "argument".
273 *
274 * The major type indicates whether the data item is an integer,
275 * string, array or such. It is encoded in 3 bits giving it a range
276 * from 0 to 7. 0 indicates the major type is a positive integer,
277 * 1 a negative integer, 2 a byte string and so on.
278 *
279 * These 3 bits are the first part of the "initial byte" in a data
280 * item. Every data item has an initial byte, and some only have
281 * the initial byte.
282 *
283 * The argument is essentially a number between 0 and UINT64_MAX
284 * (18446744073709551615). This number is interpreted to mean
285 * different things for the different major types. For major type
286 * 0, a positive integer, it is value of the data item. For major
287 * type 2, a byte string, it is the length in bytes of the byte
288 * string. For major type 4, an array, it is the number of data
289 * items in the array.
290 *
291 * Special encoding is used so that the argument values less than
292 * 24 can be encoded very compactly in the same byte as the major
293 * type is encoded. When the lower 5 bits of the initial byte have
294 * a value less than 24, then that is the value of the argument.
295 *
296 * If the lower 5 bits of the initial byte are less than 24, then
297 * they are the value of the argument. This allows integer values 0
298 * - 23 to be CBOR encoded in just one byte.
299 *
300 * When the value of lower 5 bits are 24, 25, 26, or 27 the
301 * argument is encoded in 1, 2, 4 or 8 bytes following the initial
302 * byte in network byte order (bit endian). The cases when it is
303 * 28, 29 and 30 are reserved for future use. The value 31 is a
304 * special indicator for indefinite length strings, arrays and
305 * maps.
306 *
307 * The lower 5 bits are called the "additional information."
308 *
309 * Thus the CBOR head may be 1, 2, 3, 5 or 9 bytes long.
310 *
311 * It is legal in CBOR to encode the argument using any of these
312 * lengths even if it could be encoded in a shorter length. For
313 * example it is legal to encode a data item representing the
314 * positive integer 0 in 9 bytes even though it could be encoded in
315 * only 0. This is legal to allow for for very simple code or even
316 * hardware-only implementations that just output a register
317 * directly.
318 *
319 * CBOR defines preferred encoding as the encoding of the argument
320 * in the smallest number of bytes needed to encode it.
321 *
322 * This function takes the major type and argument as inputs and
323 * outputs the encoded CBOR head for them. It does conversion to
324 * network byte order. It implements CBOR preferred encoding,
325 * outputting the shortest representation of the argument.
326 *
327 * == Endian Conversion ==
328 *
329 * This code does endian conversion without hton() or knowing the
330 * endianness of the machine by using masks and shifts. This avoids
331 * the dependency on hton() and the mess of figuring out how to
332 * find the machine's endianness.
333 *
334 * This is a good efficient implementation on little-endian
335 * machines. A faster and smaller implementation is possible on
336 * big-endian machines because CBOR/network byte order is
337 * big-endian. However big-endian machines are uncommon.
338 *
339 * On x86, this is about 150 bytes instead of 500 bytes for the
340 * original, more formal unoptimized code.
341 *
342 * This also does the CBOR preferred shortest encoding for integers
343 * and is called to do endian conversion for floats.
344 *
345 * It works backwards from the least significant byte to the most
346 * significant byte.
347 *
348 * == Floating Point ==
349 *
350 * When the major type is 7 and the 5 lower bits have the values
351 * 25, 26 or 27, the argument is a floating-point number that is
352 * half, single or double-precision. Note that it is not the
353 * conversion from a floating-point value to an integer value like
354 * converting 0x00 to 0.00, it is the interpretation of the bits in
355 * the argument as an IEEE 754 float-point number.
356 *
357 * Floating-point numbers must be converted to network byte
358 * order. That is accomplished here by exactly the same code that
359 * converts integer arguments to network byte order.
360 *
361 * There is preferred encoding for floating-point numbers in CBOR,
362 * but it is very different than for integers and it is not
363 * implemented here. Half-precision is preferred to
364 * single-precision which is preferred to double-precision only if
365 * the conversion can be performed without loss of precision. Zero
366 * and infinity can always be converted to half-precision, without
367 * loss but 3.141592653589 cannot.
368 *
369 * The way this function knows to not do preferred encoding on the
370 * argument passed here when it is a floating point number is the
371 * uMinLen parameter. It should be 2, 4 or 8 for half, single and
372 * double precision floating point values. This prevents and the
373 * incorrect removal of leading zeros when encoding arguments that
374 * are floating-point numbers.
375 *
376 * == Use of Type int and Static Analyzers ==
377 *
378 * The type int is used here for several variables because of the
379 * way integer promotion works in C for variables that are uint8_t
380 * or uint16_t. The basic rule is that they will always be promoted
381 * to int if they will fit. These integer variables here need only
382 * hold values less than 255 so they will always fit into an int.
383 *
384 * Most of values stored are never negative, so one might think
385 * that unsigned int would be more correct than int. However the C
386 * integer promotion rules only promote to unsigned int if the
387 * result won't fit into an int even if the promotion is for an
388 * unsigned variable like uint8_t.
389 *
390 * By declaring these int, there are few implicit conversions and
391 * fewer casts needed. Code size is reduced a little. It makes
392 * static analyzers happier.
393 *
394 * Note also that declaring these uint8_t won't stop integer wrap
395 * around if the code is wrong. It won't make the code more
396 * correct.
397 *
398 * https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
399 * https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
400 *
401 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800402 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800403
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800404 /* The buffer must have room for the largest CBOR HEAD + one
405 * extra. The one extra is needed for this code to work as it does
406 * a pre-decrement.
407 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000408 if(buffer.len < QCBOR_HEAD_BUFFER_SIZE) {
409 return NULLUsefulBufC;
410 }
411
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800412 /* Pointer to last valid byte in the buffer */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000413 uint8_t * const pBufferEnd = &((uint8_t *)buffer.ptr)[QCBOR_HEAD_BUFFER_SIZE-1];
414
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800415 /* Point to the last byte and work backwards */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000416 uint8_t *pByte = pBufferEnd;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800417 /* The 5 bits in the initial byte that are not the major type */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800418 int nAdditionalInfo;
Laurence Lundblade2c40ab82018-12-30 14:20:29 -0800419
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800420 if(uMajorType > QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800421 /* Special case for start & end of indefinite length */
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800422 uMajorType = uMajorType - QCBOR_INDEFINITE_LEN_TYPE_MODIFIER;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800423 /* This takes advantage of design of CBOR where additional info
424 * is 31 for both opening and closing indefinite length
425 * maps and arrays.
426 */
427 #if CBOR_SIMPLE_BREAK != LEN_IS_INDEFINITE
428 #error additional info for opening array not the same as for closing
429 #endif
Laurence Lundblade8c858ab2020-11-02 19:53:49 -0800430 nAdditionalInfo = CBOR_SIMPLE_BREAK;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800431
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000432 } else if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800433 /* Simple case where argument is < 24 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000434 nAdditionalInfo = (int)uArgument;
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800435
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800436 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800437 /* This encodes the argument in 1,2,4 or 8 bytes. The outer loop
438 * runs once for 1 byte and 4 times for 8 bytes. The inner loop
439 * runs 1, 2 or 4 times depending on outer loop counter. This
440 * works backwards shifting 8 bits off the argument being
441 * encoded at a time until all bits from uArgument have been
442 * encoded and the minimum encoding size is reached. Minimum
443 * encoding size is for floating-point numbers that have some
444 * zero-value bytes that must be output.
Laurence Lundbladee9b00322018-12-30 10:33:26 -0800445 */
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800446 static const uint8_t aIterate[] = {1,1,2,4};
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000447
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800448 /* uMinLen passed in is unsigned, but goes negative in the loop
449 * so it must be converted to a signed value.
450 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000451 int nMinLen = (int)uMinLen;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800452 int i;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000453 for(i = 0; uArgument || nMinLen > 0; i++) {
454 const int nIterations = (int)aIterate[i];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800455 for(int j = 0; j < nIterations; j++) {
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000456 *--pByte = (uint8_t)(uArgument & 0xff);
457 uArgument = uArgument >> 8;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800458 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800459 nMinLen -= nIterations;
Laurence Lundblade04a859b2018-12-11 12:13:02 -0800460 }
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800461
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800462 nAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463 }
Laurence Lundbladef970f1d2018-12-14 01:44:23 -0800464
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800465 /* This expression integer-promotes to type int. The code above in
466 * function guarantees that nAdditionalInfo will never be larger
467 * than 0x1f. The caller may pass in a too-large uMajor type. The
468 * conversion to unint8_t will cause an integer wrap around and
469 * incorrect CBOR will be generated, but no security issue will
470 * occur.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800471 */
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800472 const int nInitialByte = (uMajorType << 5) + nAdditionalInfo;
473 *--pByte = (uint8_t)nInitialByte;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800474
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000475#ifdef EXTRA_ENCODE_HEAD_CHECK
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800476 /* This is a sanity check that can be turned on to verify the
477 * pointer math in this function is not going wrong. Turn it on and
478 * run the whole test suite to perform the check.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800479 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000480 if(pBufferEnd - pByte > 9 || pBufferEnd - pByte < 1 || pByte < (uint8_t *)buffer.ptr) {
481 return NULLUsefulBufC;
482 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800483#endif /* EXTRA_ENCODE_HEAD_CHECK */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800484
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800485 /* Length will not go negative because the loops run for at most 8 decrements
486 * of pByte, only one other decrement is made, and the array is sized
487 * for this.
488 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000489 return (UsefulBufC){pByte, (size_t)(pBufferEnd - pByte)};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700490}
491
492
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000493/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800494 * @brief Append the CBOR head, the major type and argument
495 *
496 * @param me Encoder context.
497 * @param uMajorType Major type to insert.
498 * @param uArgument The argument (an integer value or a length).
499 * @param uMinLen The minimum number of bytes for encoding the CBOR argument.
500 *
501 * This formats the CBOR "head" and appends it to the output.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000502 */
503static void AppendCBORHead(QCBOREncodeContext *me, uint8_t uMajorType, uint64_t uArgument, uint8_t uMinLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700504{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800505 /* A stack buffer large enough for a CBOR head */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000506 UsefulBuf_MAKE_STACK_UB (pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
507
508 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
509 uMajorType,
510 uMinLen,
511 uArgument);
512
513 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800514 * save object code. It is very clear that pBufferForEncodedHead is
515 * the correct size. If EncodedHead == NULLUsefulBufC then
516 * UsefulOutBuf_AppendUsefulBuf() will do nothing so there is no
517 * security hole introduced.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000518 */
519
520 UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), EncodedHead);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700521}
522
523
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000524/**
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800525 * @brief Insert the CBOR head for a map, array or wrapped bstr
526 *
527 * @param me QCBOR encoding context.
528 * @param uMajorType One of CBOR_MAJOR_TYPE_XXXX.
529 * @param uLen The length of the data item.
530 *
531 * When an array, map or bstr was opened, nothing was done but note
532 * the position. This function goes back to that position and inserts
533 * the CBOR Head with the major type and length.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000534 */
535static void InsertCBORHead(QCBOREncodeContext *me, uint8_t uMajorType, size_t uLen)
536{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800537#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000538 if(me->uError == QCBOR_SUCCESS) {
539 if(!Nesting_IsInNest(&(me->nesting))) {
540 me->uError = QCBOR_ERR_TOO_MANY_CLOSES;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800541 return;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000542 } else if(Nesting_GetMajorType(&(me->nesting)) != uMajorType) {
543 me->uError = QCBOR_ERR_CLOSE_MISMATCH;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800544 return;
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000545 }
546 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800547#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800548
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800549 /* A stack buffer large enough for a CBOR head */
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800550 UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800551
552 UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
553 uMajorType,
554 0,
555 uLen);
556
557 /* No check for EncodedHead == NULLUsefulBufC is performed here to
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800558 * save object code. It is very clear that pBufferForEncodedHead is
559 * the correct size. If EncodedHead == NULLUsefulBufC then
560 * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
561 * security whole introduced.
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800562 */
563 UsefulOutBuf_InsertUsefulBuf(&(me->OutBuf),
564 EncodedHead,
565 Nesting_GetStartPos(&(me->nesting)));
566
567 Nesting_Decrease(&(me->nesting));
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000568}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700569
Laurence Lundblade241705e2018-12-30 18:56:14 -0800570
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800571/**
572 * @brief Increment item counter for maps and arrays.
573 *
574 * @param pMe QCBOR encoding context.
575 *
576 * This is mostly a separate function to make code more readable and
577 * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800578 */
579static inline void IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
580{
581#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
582 if(pMe->uError == QCBOR_SUCCESS) {
583 pMe->uError = Nesting_Increment(&(pMe->nesting));
584 }
585#else
586 (void)Nesting_Increment(&(pMe->nesting));
587#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
588}
589
590
591/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800592 * Public functions for adding unsigned integers. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700593 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800594void QCBOREncode_AddUInt64(QCBOREncodeContext *me, uint64_t uValue)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700595{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800596 AppendCBORHead(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue, 0);
597
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800598 IncrementMapOrArrayCount(me);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700599}
600
Laurence Lundblade56230d12018-11-01 11:14:51 +0700601
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800603 * Public functions for adding signed integers. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -0800604 */
605void QCBOREncode_AddInt64(QCBOREncodeContext *me, int64_t nNum)
606{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800607 uint8_t uMajorType;
608 uint64_t uValue;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800609
610 if(nNum < 0) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800611 /* In CBOR -1 encodes as 0x00 with major type negative int. */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800612 uValue = (uint64_t)(-nNum - 1);
613 uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
614 } else {
615 uValue = (uint64_t)nNum;
616 uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
617 }
618 AppendCBORHead(me, uMajorType, uValue, 0);
619
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800620 IncrementMapOrArrayCount(me);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800621}
622
623
624/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800625 * Semi-private function. It is exposed to user of the interface, but
626 * one of its inline wrappers will usually be called instead of this.
627 *
628 * See qcbor/qcbor_encode.h
629 *
630 * This does the work of adding actual strings bytes to the CBOR
631 * output (as opposed to adding numbers and opening / closing
632 * aggregate types).
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800634 * There are four use cases:
635 * CBOR_MAJOR_TYPE_BYTE_STRING -- Byte strings
636 * CBOR_MAJOR_TYPE_TEXT_STRING -- Text strings
637 * CBOR_MAJOR_NONE_TYPE_RAW -- Already-encoded CBOR
638 * CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY -- Special case
639 *
640 * The first two add the head plus the actual bytes. The third just
641 * adds the bytes as the heas is presumed to be in the bytes. The
642 * fourth just adds the head for the very special case of
643 * QCBOREncode_AddBytesLenOnly().
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800645void QCBOREncode_AddBuffer(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC Bytes)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800647 /* If it is not Raw CBOR, add the type and the length */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800648 if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
649 uint8_t uRealMajorType = uMajorType;
650 if(uRealMajorType == CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
651 uRealMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
652 }
653 AppendCBORHead(me, uRealMajorType, Bytes.len, 0);
654 }
655
656 if(uMajorType != CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800657 /* Actually add the bytes */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800658 UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes);
659 }
660
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800661 IncrementMapOrArrayCount(me);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700662}
663
Laurence Lundbladecafcfe12018-10-31 21:59:50 +0700664
Laurence Lundblade55a24832018-10-30 04:35:08 +0700665/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800666 * Public functions for adding a tag. See qcbor/qcbor_encode.h
Laurence Lundblade55a24832018-10-30 04:35:08 +0700667 */
668void QCBOREncode_AddTag(QCBOREncodeContext *me, uint64_t uTag)
669{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800670 AppendCBORHead(me, CBOR_MAJOR_TYPE_TAG, uTag, 0);
Laurence Lundblade55a24832018-10-30 04:35:08 +0700671}
672
673
Laurence Lundblade56230d12018-11-01 11:14:51 +0700674/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800675 * Semi-private function. It is exposed to user of the interface, but
676 * one of its inline wrappers will usually be called instead of this.
677 *
678 * See header qcbor/qcbor_encode.h
Laurence Lundblade56230d12018-11-01 11:14:51 +0700679 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000680void QCBOREncode_AddType7(QCBOREncodeContext *me, uint8_t uMinLen, uint64_t uNum)
Laurence Lundblade55a24832018-10-30 04:35:08 +0700681{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800682#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade487930f2018-11-30 11:01:45 -0800683 if(me->uError == QCBOR_SUCCESS) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700684 if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700685 me->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800686 return;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700687 }
Laurence Lundblade487930f2018-11-30 11:01:45 -0800688 }
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800689#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
690
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800691 /* AppendCBORHead() does endian swapping for the float / double */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800692 AppendCBORHead(me, CBOR_MAJOR_TYPE_SIMPLE, uNum, uMinLen);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800693
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800694 IncrementMapOrArrayCount(me);
Laurence Lundblade55a24832018-10-30 04:35:08 +0700695}
696
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700698/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800699 * Public functions for adding a double. See qcbor/qcbor_encode.h
700 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700701void QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *me, double dNum)
702{
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700703 QCBOREncode_AddType7(me,
704 sizeof(uint64_t),
705 UsefulBufUtil_CopyDoubleToUint64(dNum));
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700706}
707
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700708
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800710 * Public functions for adding a double. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800712void QCBOREncode_AddDouble(QCBOREncodeContext *me, double dNum)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713{
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700714#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade067035b2018-11-28 17:35:25 -0800715 const IEEE754_union uNum = IEEE754_DoubleToSmallest(dNum);
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700716
Laurence Lundblade487930f2018-11-30 11:01:45 -0800717 QCBOREncode_AddType7(me, uNum.uSize, uNum.uValue);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800718#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700719 QCBOREncode_AddDoubleNoPreferred(me, dNum);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800720#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700721}
Laurence Lundblade9682a532020-06-06 18:33:04 -0700722
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700723
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700724/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800725 * Public functions for adding a float. See qcbor/qcbor_encode.h
726 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700727void QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *me, float fNum)
728{
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700729 QCBOREncode_AddType7(me,
730 sizeof(uint32_t),
731 UsefulBufUtil_CopyFloatToUint32(fNum));
Laurence Lundblade9682a532020-06-06 18:33:04 -0700732}
733
734
735/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800736 * Public functions for adding a float. See qcbor/qcbor_encode.h
Laurence Lundblade9682a532020-06-06 18:33:04 -0700737 */
738void QCBOREncode_AddFloat(QCBOREncodeContext *me, float fNum)
739{
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700740#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -0700741 const IEEE754_union uNum = IEEE754_FloatToSmallest(fNum);
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700742
Laurence Lundblade9682a532020-06-06 18:33:04 -0700743 QCBOREncode_AddType7(me, uNum.uSize, uNum.uValue);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800744#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700745 QCBOREncode_AddFloatNoPreferred(me, fNum);
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800746#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade067035b2018-11-28 17:35:25 -0800747}
748
749
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -0700750#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade59289e52019-12-30 13:44:37 -0800751/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800752 * Semi-public function. It is exposed to the user of the interface,
753 * but one of the inline wrappers will usually be called rather than
754 * this.
755 *
756 * See qcbor/qcbor_encode.h
757 *
758 * Improvement: create another version of this that only takes a big
759 * number mantissa and converts the output to a type 0 or 1 integer
760 * when mantissa is small enough.
Laurence Lundblade59289e52019-12-30 13:44:37 -0800761 */
762void QCBOREncode_AddExponentAndMantissa(QCBOREncodeContext *pMe,
763 uint64_t uTag,
764 UsefulBufC BigNumMantissa,
765 bool bBigNumIsNegative,
766 int64_t nMantissa,
767 int64_t nExponent)
768{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800769 /* This is for encoding either a big float or a decimal fraction,
770 * both of which are an array of two items, an exponent and a
771 * mantissa. The difference between the two is that the exponent
772 * is base-2 for big floats and base-10 for decimal fractions, but
773 * that has no effect on the code here.
Laurence Lundbladeee851742020-01-08 08:37:05 -0800774 */
Laurence Lundbladeae66d3f2020-09-14 18:12:08 -0700775 if(uTag != CBOR_TAG_INVALID64) {
776 QCBOREncode_AddTag(pMe, uTag);
777 }
Laurence Lundblade59289e52019-12-30 13:44:37 -0800778 QCBOREncode_OpenArray(pMe);
779 QCBOREncode_AddInt64(pMe, nExponent);
780 if(!UsefulBuf_IsNULLC(BigNumMantissa)) {
781 if(bBigNumIsNegative) {
782 QCBOREncode_AddNegativeBignum(pMe, BigNumMantissa);
783 } else {
784 QCBOREncode_AddPositiveBignum(pMe, BigNumMantissa);
785 }
786 } else {
787 QCBOREncode_AddInt64(pMe, nMantissa);
788 }
789 QCBOREncode_CloseArray(pMe);
790}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -0700791#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -0800792
793
Laurence Lundblade067035b2018-11-28 17:35:25 -0800794/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800795 * Semi-public function. It is exposed to the user of the interface,
796 * but one of the inline wrappers will usually be called rather than
797 * this.
798 *
799 * See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -0800800*/
801void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType)
802{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800803 /* Add one item to the nesting level we are in for the new map or array */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800804 IncrementMapOrArrayCount(me);
Laurence Lundbladed39cd392019-01-11 18:17:38 -0800805
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800806 /* The offset where the length of an array or map will get written
807 * is stored in a uint32_t, not a size_t to keep stack usage
808 * smaller. This checks to be sure there is no wrap around when
809 * recording the offset. Note that on 64-bit machines CBOR larger
810 * than 4GB can be encoded as long as no array/map offsets occur
811 * past the 4GB mark, but the public interface says that the
812 * maximum is 4GB to keep the discussion simpler.
813 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800814 size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
Laurence Lundbladed39cd392019-01-11 18:17:38 -0800815
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800816 /* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
817 * code can run on a 32-bit machine and tests can pass on a 32-bit
818 * machine. If it was exactly UINT32_MAX, then this code would not
819 * compile or run on a 32-bit machine and an #ifdef or some machine
820 * size detection would be needed reducing portability.
821 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800822 if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
823 me->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
824
825 } else {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800826 /* Increase nesting level because this is a map or array. Cast
827 * from size_t to uin32_t is safe because of check above.
828 */
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800829 me->uError = Nesting_Increase(&(me->nesting), uMajorType, (uint32_t)uEndPosition);
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -0800830 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831}
832
Laurence Lundblade59289e52019-12-30 13:44:37 -0800833
Jan Jongboom4a93a662019-07-25 08:44:58 +0200834/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800835 * Semi-public function. It is exposed to the user of the interface,
836 * but one of the inline wrappers will usually be called rather than
837 * this.
838 *
839 * See qcbor/qcbor_encode.h
840 */
Jan Jongboom4a93a662019-07-25 08:44:58 +0200841void QCBOREncode_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *me, uint8_t uMajorType)
842{
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800843 /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000844 AppendCBORHead(me, uMajorType, 0, 0);
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800845
846 /* Call the definite-length opener just to do the bookkeeping for
847 * nesting. It will record the position of the opening item in the
848 * encoded output but this is not used when closing this open.
849 */
Jan Jongboom4a93a662019-07-25 08:44:58 +0200850 QCBOREncode_OpenMapOrArray(me, uMajorType);
851}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700852
Laurence Lundbladeee851742020-01-08 08:37:05 -0800853
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700854/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800855 * Public functions for closing arrays and maps. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700856 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000857void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType)
Laurence Lundbladea954db92018-09-28 19:27:31 -0700858{
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000859 InsertCBORHead(me, uMajorType, Nesting_GetCount(&(me->nesting)));
860}
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800862
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000863/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800864 * Public functions for closing bstr wrapping. See qcbor/qcbor_encode.h
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000865 */
866void QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *me, bool bIncludeCBORHead, UsefulBufC *pWrappedCBOR)
867{
868 const size_t uInsertPosition = Nesting_GetStartPos(&(me->nesting));
869 const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800871 /* This subtraction can't go negative because the UsefulOutBuf
872 * always only grows and never shrinks. UsefulOutBut itself also
873 * has defenses such that it won't write where it should not even
874 * if given incorrect input lengths.
875 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000876 const size_t uBstrLen = uEndPosition - uInsertPosition;
877
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800878 /* Actually insert */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000879 InsertCBORHead(me, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
880
881 if(pWrappedCBOR) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800882 /* Return pointer and length to the enclosed encoded CBOR. The
883 * intended use is for it to be hashed (e.g., SHA-256) in a COSE
884 * implementation. This must be used right away, as the pointer
885 * and length go invalid on any subsequent calls to this
886 * function because there might be calls to
887 * InsertEncodedTypeAndNumber() that slides data to the right.
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000888 */
889 size_t uStartOfNew = uInsertPosition;
890 if(!bIncludeCBORHead) {
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800891 /* Skip over the CBOR head to just get the inserted bstr */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000892 const size_t uNewEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
893 uStartOfNew += uNewEndPosition - uEndPosition;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700894 }
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000895 const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(me->OutBuf));
896 *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uStartOfNew);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700897 }
898}
899
Laurence Lundbladeee851742020-01-08 08:37:05 -0800900
Jan Jongboom4a93a662019-07-25 08:44:58 +0200901/*
Laurence Lundblade3ff969d2021-05-28 21:32:34 -0700902 * Public function for canceling a bstr wrap. See qcbor/qcbor_encode.h
903 */
904void QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pMe)
905{
906#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
907 if(pMe->uError == QCBOR_SUCCESS) {
908 if(!Nesting_IsInNest(&(pMe->nesting))) {
909 pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
910 return;
911 } else if(Nesting_GetMajorType(&(pMe->nesting)) != CBOR_MAJOR_TYPE_BYTE_STRING) {
912 pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
913 return;
914 }
915 const size_t uCurrent = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
916 if(pMe->nesting.pCurrentNesting->uStart != uCurrent) {
917 pMe->uError = QCBOR_ERR_CANNOT_CANCEL;
918 return;
919 }
920 }
Laurence Lundblade299391c2021-06-09 21:09:18 -0700921 /* QCBOREncode_CancelBstrWrap() can't correctly undo
922 * QCBOREncode_BstrWrapInMap() or QCBOREncode_BstrWrapInMapN(). It
923 * can't undo the labels they add. It also doesn't catch the error
924 * of using it this way. QCBOREncode_CancelBstrWrap() is used
925 * infrequently and the the result is incorrect CBOR, not a
926 * security hole, so no extra code or state is added to handle this
927 * condition.
928 */
Laurence Lundblade3ff969d2021-05-28 21:32:34 -0700929#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
930
931 Nesting_Decrease(&(pMe->nesting));
932 Nesting_Decrement(&(pMe->nesting));
933}
934
935
936/*
937 * Public function for closing arrays and maps. See qcbor/qcbor_encode.h
Jan Jongboom4a93a662019-07-25 08:44:58 +0200938 */
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +0000939void QCBOREncode_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *me, uint8_t uMajorType)
Jan Jongboom4a93a662019-07-25 08:44:58 +0200940{
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800941#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Jan Jongboom4a93a662019-07-25 08:44:58 +0200942 if(me->uError == QCBOR_SUCCESS) {
943 if(!Nesting_IsInNest(&(me->nesting))) {
944 me->uError = QCBOR_ERR_TOO_MANY_CLOSES;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800945 return;
Jan Jongboom4a93a662019-07-25 08:44:58 +0200946 } else if(Nesting_GetMajorType(&(me->nesting)) != uMajorType) {
947 me->uError = QCBOR_ERR_CLOSE_MISMATCH;
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800948 return;
Jan Jongboom4a93a662019-07-25 08:44:58 +0200949 }
950 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800951#else /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800952 (void) uMajorType;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800953#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800954
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800955 /* Append the break marker (0xff for both arrays and maps) */
Laurence Lundbladed8e1c512020-11-04 23:03:44 -0800956 AppendCBORHead(me, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800957 Nesting_Decrease(&(me->nesting));
Jan Jongboom4a93a662019-07-25 08:44:58 +0200958}
959
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700960
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700961/*
Laurence Lundblade3ff969d2021-05-28 21:32:34 -0700962 * Public function to finish and get the encoded result. See qcbor/qcbor_encode.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700963 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700964QCBORError QCBOREncode_Finish(QCBOREncodeContext *me, UsefulBufC *pEncodedCBOR)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700965{
Laurence Lundbladef607a2a2019-07-05 21:25:25 -0700966 QCBORError uReturn = QCBOREncode_GetErrorState(me);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800967
Laurence Lundblade067035b2018-11-28 17:35:25 -0800968 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700969 goto Done;
Laurence Lundblade067035b2018-11-28 17:35:25 -0800970 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800971
Laurence Lundbladedaefdec2020-11-02 20:22:03 -0800972#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
Laurence Lundblade3e0a45c2020-11-05 11:12:04 -0800973 if(Nesting_IsInNest(&(me->nesting))) {
Laurence Lundblade067035b2018-11-28 17:35:25 -0800974 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700975 goto Done;
976 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800977#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800978
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700979 *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(me->OutBuf));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800980
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700981Done:
Laurence Lundblade067035b2018-11-28 17:35:25 -0800982 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700983}
984
Laurence Lundblade0595e932018-11-02 22:22:47 +0700985
Laurence Lundblade067035b2018-11-28 17:35:25 -0800986/*
Laurence Lundblade1fa579b2020-11-25 00:31:37 -0800987 * Public functions to get size of the encoded result. See qcbor/qcbor_encode.h
Laurence Lundblade067035b2018-11-28 17:35:25 -0800988 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700989QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *me, size_t *puEncodedLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700990{
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700991 UsefulBufC Enc;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade30816f22018-11-10 13:40:22 +0700993 QCBORError nReturn = QCBOREncode_Finish(me, &Enc);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800994
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700995 if(nReturn == QCBOR_SUCCESS) {
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700996 *puEncodedLen = Enc.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700997 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700999 return nReturn;
1000}