1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZCBOR_COMMON_H__
8 #define ZCBOR_COMMON_H__
9 
10 #include <stdint.h>
11 #include <stdbool.h>
12 #include <stddef.h>
13 #include <string.h>
14 #include "zcbor_tags.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 /** Convenience type that allows pointing to strings directly inside the payload
21  *  without the need to copy out.
22  */
23 struct zcbor_string {
24 	const uint8_t *value;
25 	size_t len;
26 };
27 
28 
29 /** Type representing a string fragment.
30  *
31  * Don't modify any member variables, or subsequent calls may fail.
32 **/
33 struct zcbor_string_fragment {
34 	struct zcbor_string fragment; ///! Location and length of the fragment.
35 	size_t offset;                ///! The offset in the full string at which this fragment belongs.
36 	size_t total_len;             ///! The total length of the string this fragment is a part of.
37 };
38 
39 
40 /** Size to use in struct zcbor_string_fragment when the real size is unknown. */
41 #define ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH SIZE_MAX
42 
43 #ifdef ZCBOR_VERBOSE
44 #include <zephyr/sys/printk.h>
45 #define zcbor_trace() (printk("bytes left: %zu, byte: 0x%x, elem_count: 0x%" PRIxFAST32 ", err: %d, %s:%d\n",\
46 	(size_t)state->payload_end - (size_t)state->payload, *state->payload, state->elem_count, \
47 	state->constant_state ? state->constant_state->error : 0, __FILE__, __LINE__))
48 
49 #define zcbor_print_assert(expr, ...) \
50 do { \
51 	printk("ASSERTION \n  \"" #expr \
52 		"\"\nfailed at %s:%d with message:\n  ", \
53 		__FILE__, __LINE__); \
54 	printk(__VA_ARGS__);\
55 } while(0)
56 #define zcbor_print(...) printk(__VA_ARGS__)
57 #else
58 #define zcbor_trace() ((void)state)
59 #define zcbor_print_assert(...)
60 #define zcbor_print(...)
61 #endif
62 
63 #ifdef ZCBOR_ASSERTS
64 #define zcbor_assert(expr, ...) \
65 do { \
66 	if (!(expr)) { \
67 		zcbor_print_assert(expr, __VA_ARGS__); \
68 		ZCBOR_FAIL(); \
69 	} \
70 } while(0)
71 #define zcbor_assert_state(expr, ...) \
72 do { \
73 	if (!(expr)) { \
74 		zcbor_print_assert(expr, __VA_ARGS__); \
75 		ZCBOR_ERR(ZCBOR_ERR_ASSERTION); \
76 	} \
77 } while(0)
78 #else
79 #define zcbor_assert(expr, ...)
80 #define zcbor_assert_state(expr, ...)
81 #endif
82 
83 #ifndef MIN
84 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
85 #endif
86 
87 #ifndef ZCBOR_ARRAY_SIZE
88 #define ZCBOR_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
89 #endif
90 
91 #if SIZE_MAX <= UINT64_MAX
92 /** The ZCBOR_SUPPORTS_SIZE_T will be defined if processing of size_t type variables directly
93  * with zcbor_size_ functions is supported.
94 **/
95 #define ZCBOR_SUPPORTS_SIZE_T
96 #else
97 #warning "zcbor: Unsupported size_t encoding size"
98 #endif
99 
100 struct zcbor_state_constant;
101 
102 typedef struct {
103 union {
104 	uint8_t *payload_mut;
105 	uint8_t const *payload; /**< The current place in the payload. Will be
106 	                             updated when an element is correctly
107 	                             processed. */
108 };
109 	uint8_t const *payload_bak; /**< Temporary backup of payload. */
110 	size_t elem_count; /**< The current element is part of a LIST or a MAP,
111 	                        and this keeps count of how many elements are
112 	                        expected. This will be checked before processing
113 	                        and decremented if the element is correctly
114 	                        processed. */
115 	uint8_t const *payload_end; /**< The end of the payload. This will be
116 	                                 checked against payload before
117 	                                 processing each element. */
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 payload_moved; /**< Is set to true while the state is stored as a backup
122 	                         if @ref zcbor_update_state is called, since that function
123 	                         updates the payload_end of all backed-up states. */
124 	struct zcbor_state_constant *constant_state; /**< The part of the state that is
125 	                                                  not backed up and duplicated. */
126 } zcbor_state_t;
127 
128 struct zcbor_state_constant {
129 	zcbor_state_t *backup_list;
130 	size_t current_backup;
131 	size_t num_backups;
132 	int error;
133 #ifdef ZCBOR_STOP_ON_ERROR
134 	bool stop_on_error;
135 #endif
136 };
137 
138 /** Function pointer type used with zcbor_multi_decode.
139  *
140  * This type is compatible with all decoding functions here and in the generated
141  * code, except for zcbor_multi_decode.
142  */
143 typedef bool(zcbor_encoder_t)(zcbor_state_t *, const void *);
144 typedef bool(zcbor_decoder_t)(zcbor_state_t *, void *);
145 
146 /** Enumeration representing the major types available in CBOR.
147  *
148  * The major type is represented in the 3 first bits of the header byte.
149  */
150 typedef enum
151 {
152 	ZCBOR_MAJOR_TYPE_PINT   = 0, ///! Positive Integer
153 	ZCBOR_MAJOR_TYPE_NINT   = 1, ///! Negative Integer
154 	ZCBOR_MAJOR_TYPE_BSTR   = 2, ///! Byte String
155 	ZCBOR_MAJOR_TYPE_TSTR   = 3, ///! Text String
156 	ZCBOR_MAJOR_TYPE_LIST   = 4, ///! List
157 	ZCBOR_MAJOR_TYPE_MAP    = 5, ///! Map
158 	ZCBOR_MAJOR_TYPE_TAG    = 6, ///! Semantic Tag
159 	ZCBOR_MAJOR_TYPE_SIMPLE = 7, ///! Simple values and floats
160 } zcbor_major_type_t;
161 
162 
163 /** Convenience macro for failing out of a decoding/encoding function.
164 */
165 #define ZCBOR_FAIL() \
166 do {\
167 	zcbor_trace(); \
168 	return false; \
169 } while(0)
170 
171 #define ZCBOR_FAIL_IF(expr) \
172 do {\
173 	if (expr) { \
174 		ZCBOR_FAIL(); \
175 	} \
176 } while(0)
177 
178 #define ZCBOR_ERR(err) \
179 do { \
180 	zcbor_error(state, err); \
181 	ZCBOR_FAIL(); \
182 } while(0)
183 
184 #define ZCBOR_ERR_IF(expr, err) \
185 do {\
186 	if (expr) { \
187 		ZCBOR_ERR(err); \
188 	} \
189 } while(0)
190 
191 #define ZCBOR_CHECK_PAYLOAD() \
192 	ZCBOR_ERR_IF(state->payload >= state->payload_end, ZCBOR_ERR_NO_PAYLOAD)
193 
194 #ifdef ZCBOR_STOP_ON_ERROR
195 #define ZCBOR_CHECK_ERROR()  \
196 do { \
197 	if (!zcbor_check_error(state)) { \
198 		ZCBOR_FAIL(); \
199 	} \
200 } while(0)
201 #else
202 #define ZCBOR_CHECK_ERROR()
203 #endif
204 
205 #define ZCBOR_VALUE_IN_HEADER 23 ///! Values below this are encoded directly in the header.
206 #define ZCBOR_VALUE_IS_1_BYTE 24 ///! The next 1 byte contains the value.
207 #define ZCBOR_VALUE_IS_2_BYTES 25 ///! The next 2 bytes contain the value.
208 #define ZCBOR_VALUE_IS_4_BYTES 26 ///! The next 4 bytes contain the value.
209 #define ZCBOR_VALUE_IS_8_BYTES 27 ///! The next 8 bytes contain the value.
210 #define ZCBOR_VALUE_IS_INDEFINITE_LENGTH 31 ///! The list or map has indefinite length, and will instead be terminated by a 0xFF token.
211 
212 #define ZCBOR_BOOL_TO_SIMPLE ((uint8_t)20) ///! In CBOR, false/true have the values 20/21
213 
214 #define ZCBOR_FLAG_RESTORE 1UL ///! Restore from the backup. Overwrite the current state with the state from the backup.
215 #define ZCBOR_FLAG_CONSUME 2UL ///! Consume the backup. Remove the backup from the stack of backups.
216 #define ZCBOR_FLAG_TRANSFER_PAYLOAD 4UL ///! Keep the pre-restore payload after restoring.
217 
218 #define ZCBOR_SUCCESS 0
219 #define ZCBOR_ERR_NO_BACKUP_MEM 1
220 #define ZCBOR_ERR_NO_BACKUP_ACTIVE 2
221 #define ZCBOR_ERR_LOW_ELEM_COUNT 3
222 #define ZCBOR_ERR_HIGH_ELEM_COUNT 4
223 #define ZCBOR_ERR_INT_SIZE 5
224 #define ZCBOR_ERR_FLOAT_SIZE 6
225 #define ZCBOR_ERR_ADDITIONAL_INVAL 7 ///! > 27
226 #define ZCBOR_ERR_NO_PAYLOAD 8
227 #define ZCBOR_ERR_PAYLOAD_NOT_CONSUMED 9
228 #define ZCBOR_ERR_WRONG_TYPE 10
229 #define ZCBOR_ERR_WRONG_VALUE 11
230 #define ZCBOR_ERR_WRONG_RANGE 12
231 #define ZCBOR_ERR_ITERATIONS 13
232 #define ZCBOR_ERR_ASSERTION 14
233 #define ZCBOR_ERR_UNKNOWN 31
234 
235 /** The largest possible elem_count. */
236 #ifdef UINT_FAST32_MAX
237 #define ZCBOR_MAX_ELEM_COUNT UINT_FAST32_MAX
238 #else
239 #define ZCBOR_MAX_ELEM_COUNT ((size_t)(-1L))
240 #endif
241 
242 /** Initial value for elem_count for when it just needs to be large. */
243 #define ZCBOR_LARGE_ELEM_COUNT (ZCBOR_MAX_ELEM_COUNT - 16)
244 
245 
246 /** Take a backup of the current state. Overwrite the current elem_count. */
247 bool zcbor_new_backup(zcbor_state_t *state, size_t new_elem_count);
248 
249 /** Consult the most recent backup. In doing so, check whether elem_count is
250  *  less than or equal to max_elem_count.
251  *  Also, take action based on the flags (See ZCBOR_FLAG_*).
252  */
253 bool zcbor_process_backup(zcbor_state_t *state, uint32_t flags, size_t max_elem_count);
254 
255 /** Convenience function for starting encoding/decoding of a union.
256  *
257  *  That is, for attempting to encode, or especially decode, multiple options.
258  *  Makes a new backup.
259  */
260 bool zcbor_union_start_code(zcbor_state_t *state);
261 
262 /** Convenience function before encoding/decoding one element of a union.
263  *
264  *  Call this before attempting each option.
265  *  Restores the backup, without consuming it.
266  */
267 bool zcbor_union_elem_code(zcbor_state_t *state);
268 
269 /** Convenience function before encoding/decoding one element of a union.
270  *
271  *  Consumes the backup without restoring it.
272  */
273 bool zcbor_union_end_code(zcbor_state_t *state);
274 
275 /** Initialize a state with backups.
276  *  As long as n_states is more than 1, one of the states in the array is used
277  *  as a struct zcbor_state_constant object.
278  *  If there is no struct zcbor_state_constant (n_states == 1), error codes are
279  *  not available.
280  *  This means that you get a state with (n_states - 2) backups.
281  *  payload, payload_len, and elem_count are used to initialize the first state.
282  *  in the array, which is the state that can be passed to cbor functions.
283  */
284 void zcbor_new_state(zcbor_state_t *state_array, size_t n_states,
285 		const uint8_t *payload, size_t payload_len, size_t elem_count);
286 
287 #ifdef ZCBOR_STOP_ON_ERROR
288 /** Check stored error and fail if present, but only if stop_on_error is true. */
zcbor_check_error(const zcbor_state_t * state)289 static inline bool zcbor_check_error(const zcbor_state_t *state)
290 {
291 	struct zcbor_state_constant  *cs = state->constant_state;
292 	return !(cs && cs->stop_on_error && cs->error);
293 }
294 #endif
295 
296 /** Return the current error state, replacing it with SUCCESS. */
zcbor_pop_error(zcbor_state_t * state)297 static inline int zcbor_pop_error(zcbor_state_t *state)
298 {
299 	if (!state->constant_state) {
300 		return ZCBOR_SUCCESS;
301 	}
302 	int err = state->constant_state->error;
303 
304 	state->constant_state->error = ZCBOR_SUCCESS;
305 	return err;
306 }
307 
308 /** Look at current error state without altering it */
zcbor_peek_error(const zcbor_state_t * state)309 static inline int zcbor_peek_error(const zcbor_state_t *state)
310 {
311 	if (!state->constant_state) {
312 		return ZCBOR_SUCCESS;
313 	} else {
314 		return state->constant_state->error;
315 	}
316 }
317 
318 /** Write the provided error to the error state. */
zcbor_error(zcbor_state_t * state,int err)319 static inline void zcbor_error(zcbor_state_t *state, int err)
320 {
321 #ifdef ZCBOR_STOP_ON_ERROR
322 	if (zcbor_check_error(state))
323 #endif
324 	{
325 		if (state->constant_state) {
326 			state->constant_state->error = err;
327 		}
328 	}
329 }
330 
331 /** Whether the current payload is exhausted. */
zcbor_payload_at_end(const zcbor_state_t * state)332 static inline bool zcbor_payload_at_end(const zcbor_state_t *state)
333 {
334 	return (state->payload == state->payload_end);
335 }
336 
337 /** Update the current payload pointer (and payload_end).
338  *
339  *  For use when the payload is divided into multiple chunks.
340  *
341  *  This function also updates all backups to the new payload_end.
342  *  This sets a flag so that @ref zcbor_process_backup fails if a backup is
343  *  processed with the flag @ref ZCBOR_FLAG_RESTORE, but without the flag
344  *  @ref ZCBOR_FLAG_TRANSFER_PAYLOAD since this would cause an invalid state.
345  *
346  *  @param[inout]  state              The current state, will be updated with
347  *                                    the new payload pointer.
348  *  @param[in]     payload            The new payload chunk.
349  *  @param[in]     payload_len        The length of the new payload chunk.
350  */
351 void zcbor_update_state(zcbor_state_t *state,
352 		const uint8_t *payload, size_t payload_len);
353 
354 /** Check that the provided fragments are complete and in the right order.
355  *
356  *  If the total length is not known, the total_len can have the value
357  *  @ref ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH. If so, all fragments will be
358  *  updated with the actual total length.
359  *
360  *  @param[in]  fragments      An array of string fragments. Cannot be NULL.
361  *  @param[in]  num_fragments  The number of fragments in @p fragments.
362  *
363  *  @retval  true   If the fragments are in the right order, and there are no
364  *                  fragments missing.
365  *  @retval  false  If not all fragments have the same total_len, or gaps are
366  *                  found, or if any fragment value is NULL.
367  */
368 bool zcbor_validate_string_fragments(struct zcbor_string_fragment *fragments,
369 		size_t num_fragments);
370 
371 /** Assemble the fragments into a single string.
372  *
373  *  The fragments are copied in the order they appear, without regard for
374  *  offset or total_len. To ensure that the fragments are correct, first
375  *  validate with @ref zcbor_validate_string_fragments.
376  *
377  *  @param[in]     fragments      An array of string fragments. Cannot be NULL.
378  *  @param[in]     num_fragments  The number of fragments in @p fragments.
379  *  @param[out]    result         The buffer to place the assembled string into.
380  *  @param[inout]  result_len     In: The length of the @p result.
381  *                                Out: The length of the assembled string.
382  *
383  *  @retval  true   On success.
384  *  @retval  false  If the assembled string would be larger than the buffer.
385  *                  The buffer might still be written to.
386  */
387 bool zcbor_splice_string_fragments(struct zcbor_string_fragment *fragments,
388 		size_t num_fragments, uint8_t *result, size_t *result_len);
389 
390 /** Compare two struct zcbor_string instances.
391  *
392  *  @param[in] str1  A string
393  *  @param[in] str2  A string to compare to @p str1
394  *
395  *  @retval true   if the strings are identical
396  *  @retval false  if length or contents don't match, or one one or both strings is NULL.
397  */
398 bool zcbor_compare_strings(const struct zcbor_string *str1,
399 		const struct zcbor_string *str2);
400 
401 /** Calculate the length of a CBOR string, list, or map header.
402  *
403  *  This can be used to find the start of the CBOR object when you have a
404  *  pointer to the start of the contents. The function assumes that the header
405  *  will be the shortest it can be.
406  *
407  *  @param[in] num_elems  The number of elements in the string, list, or map.
408  *
409  *  @return  The length of the header in bytes (1-9).
410  */
411 size_t zcbor_header_len(size_t num_elems);
412 
413 /** Find whether the state is at the end of a list or map.
414  */
415 bool zcbor_array_at_end(zcbor_state_t *state);
416 
417 
418 #ifdef __cplusplus
419 }
420 #endif
421 
422 #endif /* ZCBOR_COMMON_H__ */
423