1 /*
2  * This file has been copied from the zcbor library.
3  * Commit zcbor 0.8.1
4  */
5 
6 /*
7  * Copyright (c) 2020 Nordic Semiconductor ASA
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #ifndef ZCBOR_COMMON_H__
13 #define ZCBOR_COMMON_H__
14 
15 #include <stdint.h>
16 #include <stdbool.h>
17 #include <stddef.h>
18 #include <string.h>
19 #include "zcbor_tags.h"
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 #define ZCBOR_STRINGIFY_PRE(x) #x
26 #define ZCBOR_STRINGIFY(s) ZCBOR_STRINGIFY_PRE(s)
27 
28 #define ZCBOR_VERSION_MAJOR 0
29 #define ZCBOR_VERSION_MINOR 8
30 #define ZCBOR_VERSION_BUGFIX 1
31 
32 /** The version string with dots and not prefix. */
33 #define ZCBOR_VERSION_STR   ZCBOR_STRINGIFY(ZCBOR_VERSION_MAJOR) \
34 			"." ZCBOR_STRINGIFY(ZCBOR_VERSION_MINOR) \
35 			"." ZCBOR_STRINGIFY(ZCBOR_VERSION_BUGFIX)
36 
37 /** Monotonically increasing integer representing the version. */
38 #define ZCBOR_VERSION    ((ZCBOR_VERSION_MAJOR << 24) \
39 			+ (ZCBOR_VERSION_MINOR << 16) \
40 			+ (ZCBOR_VERSION_BUGFIX << 8))
41 
42 /** Convenience type that allows pointing to strings directly inside the payload
43  *  without the need to copy out.
44  */
45 struct zcbor_string {
46 	const uint8_t *value;
47 	size_t len;
48 };
49 
50 
51 /** Type representing a string fragment.
52  *
53  * Don't modify any member variables, or subsequent calls may fail.
54 **/
55 struct zcbor_string_fragment {
56 	struct zcbor_string fragment; ///! Location and length of the fragment.
57 	size_t offset;                ///! The offset in the full string at which this fragment belongs.
58 	size_t total_len;             ///! The total length of the string this fragment is a part of.
59 };
60 
61 
62 /** Size to use in struct zcbor_string_fragment when the real size is unknown. */
63 #define ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH SIZE_MAX
64 
65 #ifndef MIN
66 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
67 #endif
68 
69 #ifndef MAX
70 #define MAX(a, b) (((a) < (b)) ? (b) : (a))
71 #endif
72 
73 #ifndef ZCBOR_ARRAY_SIZE
74 #define ZCBOR_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
75 #endif
76 
77 /* Endian-dependent offset of smaller integer in a bigger one. */
78 #ifdef ZCBOR_BIG_ENDIAN
79 #define ZCBOR_ECPY_OFFS(dst_len, src_len) ((dst_len) - (src_len))
80 #else
81 #define ZCBOR_ECPY_OFFS(dst_len, src_len) (0)
82 #endif /* ZCBOR_BIG_ENDIAN */
83 
84 #if SIZE_MAX <= UINT64_MAX
85 /** The ZCBOR_SUPPORTS_SIZE_T will be defined if processing of size_t type variables directly
86  * with zcbor_size_ functions is supported.
87 **/
88 #define ZCBOR_SUPPORTS_SIZE_T
89 #else
90 #warning "zcbor: Unsupported size_t encoding size"
91 #endif
92 
93 struct zcbor_state_constant;
94 
95 /** The zcbor_state_t structure is used for both encoding and decoding. */
96 typedef struct {
97 union {
98 	uint8_t *payload_mut;
99 	uint8_t const *payload; /**< The current place in the payload. Will be
100 	                             updated when an element is correctly
101 	                             processed. */
102 };
103 	uint8_t const *payload_bak; /**< Temporary backup of payload. */
104 	size_t elem_count; /**< The current element is part of a LIST or a MAP,
105 	                        and this keeps count of how many elements are
106 	                        expected. This will be checked before processing
107 	                        and decremented if the element is correctly
108 	                        processed. */
109 	uint8_t const *payload_end; /**< The end of the payload. This will be
110 	                                 checked against payload before
111 	                                 processing each element. */
112 	bool payload_moved; /**< Is set to true while the state is stored as a backup
113 	                         if @ref zcbor_update_state is called, since that function
114 	                         updates the payload_end of all backed-up states. */
115 
116 /* This is the "decode state", the part of zcbor_state_t that is only used by zcbor_decode.c. */
117 struct {
118 	bool indefinite_length_array; /**< Is set to true if the decoder is currently
119 	                                   decoding the contents of an indefinite-
120 	                                   length array. */
121 	bool counting_map_elems; /**< Is set to true while the number of elements of the
122 	                              current map are being counted. */
123 #ifdef ZCBOR_MAP_SMART_SEARCH
124 	uint8_t *map_search_elem_state; /**< Optional flags to use when searching unordered
125 	                                     maps. If this is not NULL and map_elem_count
126 	                                     is non-zero, this consists of one flag per element
127 	                                     in the current map. The n-th bit can be set to 0
128 	                                     to indicate that the n-th element in the
129 	                                     map should not be searched. These are manipulated
130 	                                     via zcbor_elem_processed() or
131 	                                     zcbor_unordered_map_search(), and should not be
132 	                                     manipulated directly. */
133 #else
134 	size_t map_elems_processed; /**< The number of elements of an unordered map
135 	                                 that have been processed. */
136 #endif
137 	size_t map_elem_count; /**< Number of elements in the current unordered map.
138 	                            This also serves as the number of bits (not bytes)
139 	                            in the map_search_elem_state array (when applicable). */
140 } decode_state;
141 	struct zcbor_state_constant *constant_state; /**< The part of the state that is
142 	                                                  not backed up and duplicated. */
143 } zcbor_state_t;
144 
145 struct zcbor_state_constant {
146 	zcbor_state_t *backup_list;
147 	size_t current_backup;
148 	size_t num_backups;
149 	int error;
150 #ifdef ZCBOR_STOP_ON_ERROR
151 	bool stop_on_error;
152 #endif
153 	bool manually_process_elem; /**< Whether an (unordered map) element should be automatically
154 	                                 marked as processed when found via @ref zcbor_search_map_key. */
155 #ifdef ZCBOR_MAP_SMART_SEARCH
156 	uint8_t *map_search_elem_state_end; /**< The end of the @ref map_search_elem_state buffer. */
157 #endif
158 };
159 
160 /** Function pointer type used with zcbor_multi_decode.
161  *
162  * This type is compatible with all decoding functions here and in the generated
163  * code, except for zcbor_multi_decode.
164  */
165 typedef bool(zcbor_encoder_t)(zcbor_state_t *, const void *);
166 typedef bool(zcbor_decoder_t)(zcbor_state_t *, void *);
167 
168 /** Enumeration representing the major types available in CBOR.
169  *
170  * The major type is represented in the 3 first bits of the header byte.
171  */
172 typedef enum
173 {
174 	ZCBOR_MAJOR_TYPE_PINT   = 0, ///! Positive Integer
175 	ZCBOR_MAJOR_TYPE_NINT   = 1, ///! Negative Integer
176 	ZCBOR_MAJOR_TYPE_BSTR   = 2, ///! Byte String
177 	ZCBOR_MAJOR_TYPE_TSTR   = 3, ///! Text String
178 	ZCBOR_MAJOR_TYPE_LIST   = 4, ///! List
179 	ZCBOR_MAJOR_TYPE_MAP    = 5, ///! Map
180 	ZCBOR_MAJOR_TYPE_TAG    = 6, ///! Semantic Tag
181 	ZCBOR_MAJOR_TYPE_SIMPLE = 7, ///! Simple values and floats
182 } zcbor_major_type_t;
183 
184 /** Extract the major type, i.e. the first 3 bits of the header byte. */
185 #define ZCBOR_MAJOR_TYPE(header_byte) ((zcbor_major_type_t)(((header_byte) >> 5) & 0x7))
186 
187 /** Extract the additional info, i.e. the last 5 bits of the header byte. */
188 #define ZCBOR_ADDITIONAL(header_byte) ((header_byte) & 0x1F)
189 
190 /** Convenience macro for failing out of a decoding/encoding function.
191 */
192 #define ZCBOR_FAIL() \
193 do {\
194 	zcbor_log("ZCBOR_FAIL "); \
195 	zcbor_trace_file(state); \
196 	return false; \
197 } while(0)
198 
199 #define ZCBOR_FAIL_IF(expr) \
200 do {\
201 	if (expr) { \
202 		zcbor_log("ZCBOR_FAIL_IF(" #expr ") "); \
203 		ZCBOR_FAIL(); \
204 	} \
205 } while(0)
206 
207 #define ZCBOR_ERR(err) \
208 do { \
209 	zcbor_log("ZCBOR_ERR(%d) ", err); \
210 	zcbor_error(state, err); \
211 	ZCBOR_FAIL(); \
212 } while(0)
213 
214 #define ZCBOR_ERR_IF(expr, err) \
215 do {\
216 	if (expr) { \
217 		zcbor_log("ZCBOR_ERR_IF(" #expr ", %d) ", err); \
218 		ZCBOR_ERR(err); \
219 	} \
220 } while(0)
221 
222 #define ZCBOR_CHECK_PAYLOAD() \
223 	ZCBOR_ERR_IF(state->payload >= state->payload_end, ZCBOR_ERR_NO_PAYLOAD)
224 
225 #ifdef ZCBOR_STOP_ON_ERROR
226 #define ZCBOR_CHECK_ERROR()  \
227 do { \
228 	if (!zcbor_check_error(state)) { \
229 		ZCBOR_FAIL(); \
230 	} \
231 } while(0)
232 #else
233 #define ZCBOR_CHECK_ERROR()
234 #endif
235 
236 #define ZCBOR_VALUE_IN_HEADER 23 ///! Values below this are encoded directly in the header.
237 #define ZCBOR_VALUE_IS_1_BYTE 24 ///! The next 1 byte contains the value.
238 #define ZCBOR_VALUE_IS_2_BYTES 25 ///! The next 2 bytes contain the value.
239 #define ZCBOR_VALUE_IS_4_BYTES 26 ///! The next 4 bytes contain the value.
240 #define ZCBOR_VALUE_IS_8_BYTES 27 ///! The next 8 bytes contain the value.
241 #define ZCBOR_VALUE_IS_INDEFINITE_LENGTH 31 ///! The list or map has indefinite length, and will instead be terminated by a 0xFF token.
242 
243 #define ZCBOR_BOOL_TO_SIMPLE ((uint8_t)20) ///! In CBOR, false/true have the values 20/21
244 
245 #define ZCBOR_FLAG_RESTORE 1UL ///! Restore from the backup. Overwrite the current state with the state from the backup.
246 #define ZCBOR_FLAG_CONSUME 2UL ///! Consume the backup. Remove the backup from the stack of backups.
247 #define ZCBOR_FLAG_KEEP_PAYLOAD 4UL ///! Keep the pre-restore payload after restoring.
248 #define ZCBOR_FLAG_KEEP_DECODE_STATE 8UL ///! Keep the pre-restore decode state (everything only used for decoding)
249 
250 #define ZCBOR_SUCCESS 0
251 #define ZCBOR_ERR_NO_BACKUP_MEM 1
252 #define ZCBOR_ERR_NO_BACKUP_ACTIVE 2
253 #define ZCBOR_ERR_LOW_ELEM_COUNT 3
254 #define ZCBOR_ERR_HIGH_ELEM_COUNT 4
255 #define ZCBOR_ERR_INT_SIZE 5
256 #define ZCBOR_ERR_FLOAT_SIZE 6
257 #define ZCBOR_ERR_ADDITIONAL_INVAL 7 ///! > 27
258 #define ZCBOR_ERR_NO_PAYLOAD 8
259 #define ZCBOR_ERR_PAYLOAD_NOT_CONSUMED 9
260 #define ZCBOR_ERR_WRONG_TYPE 10
261 #define ZCBOR_ERR_WRONG_VALUE 11
262 #define ZCBOR_ERR_WRONG_RANGE 12
263 #define ZCBOR_ERR_ITERATIONS 13
264 #define ZCBOR_ERR_ASSERTION 14
265 #define ZCBOR_ERR_PAYLOAD_OUTDATED 15 ///! Because of a call to @ref zcbor_update_state
266 #define ZCBOR_ERR_ELEM_NOT_FOUND 16
267 #define ZCBOR_ERR_MAP_MISALIGNED 17
268 #define ZCBOR_ERR_ELEMS_NOT_PROCESSED 18
269 #define ZCBOR_ERR_NOT_AT_END 19
270 #define ZCBOR_ERR_MAP_FLAGS_NOT_AVAILABLE 20
271 #define ZCBOR_ERR_INVALID_VALUE_ENCODING 21 ///! When ZCBOR_CANONICAL is defined, and the incoming data is not encoded with minimal length.
272 #define ZCBOR_ERR_UNKNOWN 31
273 
274 /** The largest possible elem_count. */
275 #define ZCBOR_MAX_ELEM_COUNT SIZE_MAX
276 
277 /** Initial value for elem_count for when it just needs to be large. */
278 #define ZCBOR_LARGE_ELEM_COUNT (ZCBOR_MAX_ELEM_COUNT - 15)
279 
280 
281 /** Take a backup of the current state. Overwrite the current elem_count. */
282 bool zcbor_new_backup(zcbor_state_t *state, size_t new_elem_count);
283 
284 /** Consult the most recent backup. In doing so, check whether elem_count is
285  *  less than or equal to max_elem_count.
286  *  Also, take action based on the flags (See ZCBOR_FLAG_*).
287  */
288 bool zcbor_process_backup(zcbor_state_t *state, uint32_t flags, size_t max_elem_count);
289 
290 /** Convenience function for starting encoding/decoding of a union.
291  *
292  *  That is, for attempting to encode, or especially decode, multiple options.
293  *  Makes a new backup.
294  */
295 bool zcbor_union_start_code(zcbor_state_t *state);
296 
297 /** Convenience function before encoding/decoding one element of a union.
298  *
299  *  Call this before attempting each option.
300  *  Restores the backup, without consuming it.
301  */
302 bool zcbor_union_elem_code(zcbor_state_t *state);
303 
304 /** Convenience function before encoding/decoding one element of a union.
305  *
306  *  Consumes the backup without restoring it.
307  */
308 bool zcbor_union_end_code(zcbor_state_t *state);
309 
310 /** Initialize a state with backups.
311  *  As long as n_states is more than 1, one of the states in the array is used
312  *  as a struct zcbor_state_constant object.
313  *  If there is no struct zcbor_state_constant (n_states == 1), error codes are
314  *  not available.
315  *  This means that you get a state with (n_states - 2) backups.
316  *  payload, payload_len, elem_count, and elem_state are used to initialize the first state.
317  *  The elem_state is only needed for unordered maps, when ZCBOR_MAP_SMART_SEARCH is enabled.
318  *  It is ignored otherwise.
319  */
320 void zcbor_new_state(zcbor_state_t *state_array, size_t n_states,
321 		const uint8_t *payload, size_t payload_len, size_t elem_count,
322 		uint8_t *elem_state, size_t elem_state_bytes);
323 
324 /** Do boilerplate entry function procedure.
325  *  Initialize states, call function, and check the result.
326  */
327 int zcbor_entry_function(const uint8_t *payload, size_t payload_len,
328 	void *result, size_t *payload_len_out, zcbor_state_t *state, zcbor_decoder_t func,
329 	size_t n_states, size_t elem_count);
330 
331 #ifdef ZCBOR_STOP_ON_ERROR
332 /** Check stored error and fail if present, but only if stop_on_error is true.
333  *
334  * @retval true   No error found
335  * @retval false  An error was found
336  */
zcbor_check_error(const zcbor_state_t * state)337 static inline bool zcbor_check_error(const zcbor_state_t *state)
338 {
339 	struct zcbor_state_constant *cs = state->constant_state;
340 	return !(cs && cs->stop_on_error && cs->error);
341 }
342 #endif
343 
344 /** Return the current error state, replacing it with SUCCESS. */
zcbor_pop_error(zcbor_state_t * state)345 static inline int zcbor_pop_error(zcbor_state_t *state)
346 {
347 	if (!state->constant_state) {
348 		return ZCBOR_SUCCESS;
349 	}
350 	int err = state->constant_state->error;
351 
352 	state->constant_state->error = ZCBOR_SUCCESS;
353 	return err;
354 }
355 
356 /** Look at current error state without altering it */
zcbor_peek_error(const zcbor_state_t * state)357 static inline int zcbor_peek_error(const zcbor_state_t *state)
358 {
359 	if (!state->constant_state) {
360 		return ZCBOR_SUCCESS;
361 	} else {
362 		return state->constant_state->error;
363 	}
364 }
365 
366 /** Write the provided error to the error state. */
zcbor_error(zcbor_state_t * state,int err)367 static inline void zcbor_error(zcbor_state_t *state, int err)
368 {
369 #ifdef ZCBOR_STOP_ON_ERROR
370 	if (zcbor_check_error(state))
371 #endif
372 	{
373 		if (state->constant_state) {
374 			state->constant_state->error = err;
375 		}
376 	}
377 }
378 
379 /** Whether the current payload is exhausted. */
zcbor_payload_at_end(const zcbor_state_t * state)380 static inline bool zcbor_payload_at_end(const zcbor_state_t *state)
381 {
382 	return (state->payload == state->payload_end);
383 }
384 
385 /** Update the current payload pointer (and payload_end).
386  *
387  *  For use when the payload is divided into multiple chunks.
388  *
389  *  This function also updates all backups to the new payload_end.
390  *  This sets a flag so that @ref zcbor_process_backup fails if a backup is
391  *  processed with the flag @ref ZCBOR_FLAG_RESTORE, but without the flag
392  *  @ref ZCBOR_FLAG_KEEP_PAYLOAD since this would cause an invalid state.
393  *
394  *  @param[inout]  state              The current state, will be updated with
395  *                                    the new payload pointer.
396  *  @param[in]     payload            The new payload chunk.
397  *  @param[in]     payload_len        The length of the new payload chunk.
398  */
399 void zcbor_update_state(zcbor_state_t *state,
400 		const uint8_t *payload, size_t payload_len);
401 
402 /** Check that the provided fragments are complete and in the right order.
403  *
404  *  If the total length is not known, the total_len can have the value
405  *  @ref ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH. If so, all fragments will be
406  *  updated with the actual total length.
407  *
408  *  @param[in]  fragments      An array of string fragments. Cannot be NULL.
409  *  @param[in]  num_fragments  The number of fragments in @p fragments.
410  *
411  *  @retval  true   If the fragments are in the right order, and there are no
412  *                  fragments missing.
413  *  @retval  false  If not all fragments have the same total_len, or gaps are
414  *                  found, or if any fragment value is NULL.
415  */
416 bool zcbor_validate_string_fragments(struct zcbor_string_fragment *fragments,
417 		size_t num_fragments);
418 
419 /** Assemble the fragments into a single string.
420  *
421  *  The fragments are copied in the order they appear, without regard for
422  *  offset or total_len. To ensure that the fragments are correct, first
423  *  validate with @ref zcbor_validate_string_fragments.
424  *
425  *  @param[in]     fragments      An array of string fragments. Cannot be NULL.
426  *  @param[in]     num_fragments  The number of fragments in @p fragments.
427  *  @param[out]    result         The buffer to place the assembled string into.
428  *  @param[inout]  result_len     In: The length of the @p result.
429  *                                Out: The length of the assembled string.
430  *
431  *  @retval  true   On success.
432  *  @retval  false  If the assembled string would be larger than the buffer.
433  *                  The buffer might still be written to.
434  */
435 bool zcbor_splice_string_fragments(struct zcbor_string_fragment *fragments,
436 		size_t num_fragments, uint8_t *result, size_t *result_len);
437 
438 /** Compare two struct zcbor_string instances.
439  *
440  *  @param[in] str1  A string
441  *  @param[in] str2  A string to compare to @p str1
442  *
443  *  @retval true   if the strings are identical
444  *  @retval false  if length or contents don't match, or one one or both strings is NULL.
445  */
446 bool zcbor_compare_strings(const struct zcbor_string *str1,
447 		const struct zcbor_string *str2);
448 
449 /** Calculate the length of a CBOR string, list, or map header.
450  *
451  *  This can be used to find the start of the CBOR object when you have a
452  *  pointer to the start of the contents. The function assumes that the header
453  *  will be the shortest it can be.
454  *
455  *  @param[in] num_elems  The number of elements in the string, list, or map.
456  *
457  *  @return  The length of the header in bytes (1-9).
458  */
459 size_t zcbor_header_len(uint64_t value);
460 
461 /** Like @ref zcbor_header_len but for integer of any size <= 8. */
462 size_t zcbor_header_len_ptr(const void *const value, size_t value_len);
463 
464 /** Convert a float16 value to float32.
465  *
466  *  @param[in] input  The float16 value stored in a uint16_t.
467  *
468  *  @return  The resulting float32 value.
469  */
470 float zcbor_float16_to_32(uint16_t input);
471 
472 /** Convert a float32 value to float16.
473  *
474  *  @param[in] input  The float32 value.
475  *
476  *  @return  The resulting float16 value as a uint16_t.
477  */
478 uint16_t zcbor_float32_to_16(float input);
479 
480 #ifdef ZCBOR_MAP_SMART_SEARCH
zcbor_round_up(size_t x,size_t align)481 static inline size_t zcbor_round_up(size_t x, size_t align)
482 {
483 	return (((x) + (align) - 1) / (align) * (align));
484 }
485 
486 #define ZCBOR_BITS_PER_BYTE 8
487 /** Calculate the number of bytes needed to hold @p num_flags 1 bit flags
488  */
zcbor_flags_to_bytes(size_t num_flags)489 static inline size_t zcbor_flags_to_bytes(size_t num_flags)
490 {
491 	return zcbor_round_up(num_flags, ZCBOR_BITS_PER_BYTE) / ZCBOR_BITS_PER_BYTE;
492 }
493 
494 /** Calculate the number of zcbor_state_t instances needed to hold @p num_flags 1 bit flags
495  */
zcbor_flags_to_states(size_t num_flags)496 static inline size_t zcbor_flags_to_states(size_t num_flags)
497 {
498 	return zcbor_round_up(num_flags, sizeof(zcbor_state_t) * ZCBOR_BITS_PER_BYTE)
499 			/ (sizeof(zcbor_state_t) * ZCBOR_BITS_PER_BYTE);
500 }
501 
502 #define ZCBOR_FLAG_STATES(n_flags) zcbor_flags_to_states(n_flags)
503 
504 #else
505 #define ZCBOR_FLAG_STATES(n_flags) 0
506 #endif
507 
508 size_t strnlen(const char *, size_t);
509 
510 #ifdef __cplusplus
511 }
512 #endif
513 
514 #endif /* ZCBOR_COMMON_H__ */
515