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