mcuboot/boot/boot_serial/src/cbor_decode.h

235 lines
9.1 KiB
C

/*
* This file has been copied from the cddl-gen submodule.
* Commit 9f77837f9950da1633d22abf6181a830521a6688
*/
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef CBOR_DECODE_H__
#define CBOR_DECODE_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "cbor_common.h"
/** The cbor_decode library provides functions for decoding CBOR data elements.
*
* This library is primarily meant to be called from code generated by
* $CDDL_GEN_BASE/cddl_gen/cddl_gen.py script, or its equivalent cddl_gen
* command line executable.
*
* Some details to notice about this library:
* - Integers are all 32 bits (uint32_t). This means that CBOR's 64 bit values
* are not supported, even when the code is running on a 64 bit architecture.
* This applies to integer types, as well as lengths for other types.
* - Strings are kept in the container type cbor_string_type_t, which is a
* pointer and a length.
* - When a function returns false, it only means that decoding that particular
* value failed. If a value is allowed to take multiple different values,
* another decoding function can be called if the first fails.
* - There is some type casting going on under the hood to make the code
* generator friendly. See especially the processor_t type which is compatible
* with all functions except multi_decode, but the compiler doesn't "know"
* this because they are defined with different pointer types. It also means
* any usage of multi_decode must be made with care for function types.
*
*
* CBOR's format is described well on Wikipedia
* - https://en.wikipedia.org/wiki/CBOR
* but here's a synopsis:
*
* Encoded CBOR data elements look like this.
*
* | Header | Value | Payload |
* | 1 byte | 0, 1, 2, 4, or 8 bytes | 0 - 2^64-1 bytes/elements |
* | 3 bits | 5 bits |
* | Major | Additional|
* | Type | info |
*
* The available major types can be seen in @ref cbor_major_type_t.
*
* For all types, Values 0-23 are encoded directly in the "Additional info",
* meaning that the "Value" field is 0 bytes long. If "Additional info" is 24,
* 25, 26, or 27, the "Value" field is 1, 2, 4, or 8 bytes long, respectively.
*
* Major types PINT, NINT, TAG, and PRIM elements have no payload, only Value.
* PINT: Interpret the Value as a positive integer.
* NINT: Interpret the Value as a positive integer, then multiply by -1 and
* subtract 1.
* TAG: The Value says something about the next non-tag element.
* See https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
* PRIM: Different Values mean different things:
* 20: "false"
* 21: "true"
* 22: "null"
* 23: "undefined"
* >=0x10000: Interpret as IEEE 754 float with given precision
*
* For BSTR, TSTR, LIST, and MAP, the Value describes the length of the payload.
* For BSTR and TSTR, the length is in bytes, for LIST, the length is in number
* of elements, and for MAP, the length is in number of key/value element pairs.
*
* For LIST and MAP, sub elements are regular CBOR elements with their own
* Header, Value and Payload. LISTs and MAPs can be recursively encoded.
*
* The additional info means slightly different things for different major
* types.
*/
/** Decode a PINT/NINT into a int32_t.
*
* @param[inout] state The current state of the decoding.
* @param[out] result Where to place the decoded value.
*
* @retval true If the value was decoded correctly.
* @retval false If the value has the wrong type, the payload overflowed, the
* element count was exhausted, or the value was larger than can
* fit in the result variable.
*/
bool intx32_decode(cbor_state_t *state, int32_t *result);
/** Expect a PINT/NINT with a certain value. Uses intx32_decode internally.
*
* @param[inout] state The current state of the decoding.
* @param[in] result The expected value
*
* @retval true If the result was decoded correctly and has the expected value.
* @retval false If intx32_decode failed or the result doesn't have the
* expected value.
*/
bool intx32_expect(cbor_state_t *state, int32_t result);
/** Decode a PINT. */
bool uintx32_decode(cbor_state_t *state, uint32_t *result);
bool uintx32_expect(cbor_state_t *state, uint32_t result);
bool uintx32_expect_union(cbor_state_t *state, uint32_t result);
/** Decode and consume a BSTR header.
*
* The rest of the string can be decoded as CBOR.
* A state backup is created to keep track of the element count.
*
* @retval true Header decoded correctly
* @retval false Header decoded incorrectly, or backup failed.
*/
bool bstrx_cbor_start_decode(cbor_state_t *state, cbor_string_type_t *result);
/** Finalize decoding a CBOR-encoded bstr.
*
* Restore element count from backup.
*/
bool bstrx_cbor_end_decode(cbor_state_t *state);
/** Decode and consume a BSTR */
bool bstrx_decode(cbor_state_t *state, cbor_string_type_t *result);
bool bstrx_expect(cbor_state_t *state, cbor_string_type_t *result);
/** Decode and consume a TSTR */
bool tstrx_decode(cbor_state_t *state, cbor_string_type_t *result);
bool tstrx_expect(cbor_state_t *state, cbor_string_type_t *result);
/** Decode and consume a LIST header.
*
* The contents of the list can be decoded via subsequent function calls.
* A state backup is created to keep track of the element count.
*
* @retval true Header decoded correctly
* @retval false Header decoded incorrectly, or backup failed.
*/
bool list_start_decode(cbor_state_t *state);
/** Decode and consume a MAP header. */
bool map_start_decode(cbor_state_t *state);
/** Finalize decoding a LIST
*
* Check that the list had the correct number of elements, and restore previous
* element count from backup.
*
* @retval true Everything ok.
* @retval false Element count not correct.
*/
bool list_end_decode(cbor_state_t *state);
/** Finalize decoding a MAP */
bool map_end_decode(cbor_state_t *state);
/** Decode a "nil" primitive value. */
bool nilx_expect(cbor_state_t *state, void *result);
/** Decode a boolean primitive value. */
bool boolx_decode(cbor_state_t *state, bool *result);
bool boolx_expect(cbor_state_t *state, bool result);
/** Decode a float */
bool float_decode(cbor_state_t *state, double *result);
bool float_expect(cbor_state_t *state, double *result);
/** Skip a single element, regardless of type and value. */
bool any_decode(cbor_state_t *state, void *result);
/** Decode a tag. */
bool tag_decode(cbor_state_t *state, uint32_t *result);
bool tag_expect(cbor_state_t *state, uint32_t result);
/** Decode 0 or more elements with the same type and constraints.
*
* @details This must not necessarily decode all elements in a list. E.g. if
* the list contains 3 INTS between 0 and 100 followed by 0 to 2 BSTRs
* with length 8, that could be done with:
*
* @code{c}
* uint32_t int_min = 0;
* uint32_t int_max = 100;
* uint32_t bstr_size = 8;
* uint32_t ints[3];
* cbor_string_type_t bstrs[2];
* bool res;
*
* res = list_start_encode(state, 3, 5);
* // check res
* res = multi_encode(3, 3, &num_encode, uintx32_encode, state,
* ints, &int_min, &int_max, 4);
* // check res
* res = multi_encode(0, 2, &num_encode, strx_encode, state,
* bstrs, &bstr_size, &bstr_size,
* sizeof(cbor_string_type_t));
* // check res
* res = list_end_encode(state, 3, 5);
* // check res
* @endcode
*
* @param[in] min_decode The minimum acceptable number of elements.
* @param[in] max_decode The maximum acceptable number of elements.
* @param[out] num_decode The actual number of elements.
* @param[in] decoder The decoder function to call under the hood. This
* function will be called with the provided arguments
* repeatedly until the function fails (returns false)
* or until it has been called @p max_decode times.
* result is moved @p result_len bytes for each call
* to @p decoder, i.e. @p result refers to an array
* of result variables.
* @param[out] result Where to place the decoded values. Must be an array
* of length at least @p max_decode.
* @param[in] result_len The length of the result variables. Must be the
* length matching the elements of @p result.
*
* @retval true If at least @p min_decode variables were correctly decoded.
* @retval false If @p decoder failed before having decoded @p min_decode
* values.
*/
bool multi_decode(uint32_t min_decode, uint32_t max_decode, uint32_t *num_decode,
cbor_decoder_t decoder, cbor_state_t *state, void *result,
uint32_t result_len);
bool present_decode(uint32_t *present,
cbor_decoder_t decoder,
cbor_state_t *state,
void *result);
#endif /* CBOR_DECODE_H__ */