1 /* 2 * qcbor_util.h 3 * 4 * Copyright (c) 2019, Laurence Lundblade. 5 * 6 * SPDX-License-Identifier: BSD-3-Clause 7 * 8 * See BSD-3-Clause license in README.md 9 */ 10 11 #ifndef __QCBOR_UTILS_H__ 12 #define __QCBOR_UTILS_H__ 13 14 15 #include "qcbor/qcbor.h" 16 #include "q_useful_buf.h" 17 #include "attest_token.h" /* For error codes */ 18 19 #ifdef __cplusplus 20 extern "C" { 21 #endif 22 23 /** 24 *\file qcbor_util.h 25 * 26 * \brief Some utility functions for decoding CBOR with QCBOR. 27 * 28 * All functions search only for integer labeled data items. If data 29 * items labeled otherwise are present, they will be skipped over. 30 * 31 * These functions may eventually expand in to a more general and 32 * useful set of decoding utilities. 33 * 34 * \c uint_fast8_t is used for type and nest levels. They are 35 * 8-bit quantities, but making using uint8_t variables 36 * and parameters can result in bigger, slower code. 37 * \c uint_fast8_t is part of \c <stdint.h>. It is not 38 * used in structures where it is more important to keep 39 * the size smaller. 40 */ 41 42 43 /** 44 *\brief Consume a data item, particularly a map or array. 45 * 46 * \param[in] decode_context The CBOR context from which to 47 * consume the map or array. 48 * \param[in] item_to_consume The item to consume. 49 * \param[out] next_nest_level The nesting level of the item 50 * that would be consumed next. 51 * 52 * \return A \c QCBORError when there is something wrong with the 53 * encoded CBOR. 54 * 55 * If the \c item_to_consume is not a map or array this does nothing 56 * but return the \c next_nest_level (which is just copied from \c 57 * item_to_consume). If it is a map or array all subordinate items 58 * will be consumed from the \c decode_context. 59 */ 60 QCBORError 61 qcbor_util_consume_item(QCBORDecodeContext *decode_context, 62 const QCBORItem *item_to_consume, 63 uint_fast8_t *next_nest_level); 64 65 66 /** 67 * Descriptor for a single labeled item to be retrieved by 68 * qcbor_util_get_items_in_map(). An array of these is passed to 69 * qcbor_util_get_items_in_map() terminated by one of these with label 70 * 0. 71 */ 72 struct qcbor_util_items_to_get_t { 73 /** 74 * The integer label to search for. List terminated by label 0. 75 */ 76 int64_t label; 77 /** 78 * Where the retrieved item is returned. Item.uDataType is 79 * QCBOR_TYPE_NONE if not found 80 */ 81 QCBORItem item; 82 }; 83 84 85 /** 86 * \brief Search a CBOR map for multiple integer-labeled items. 87 * 88 * \param[in,out] decode_context The QCBOR decode context to 89 * consume and look through. 90 * \param[in,out] items The array of labels to search for 91 * and the places to return what was 92 * found. See \ref 93 * qcbor_util_items_to_get_t. 94 * 95 * \retval ATTEST_TOKEN_ERR_CBOR_STRUCTURE 96 * The next item in the decode context is not a map. 97 * \retval ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED 98 * The CBOR is not well-formed. 99 * \retval ATTEST_TOKEN_ERR_SUCCESS 100 * Success. This just means the map was searched, not that 101 * anything was found. The contents of \c items must be 102 * checked to see what was found. 103 * 104 * The next item from \c decode_context must be a map. This is the map 105 * that will be searched. Only items at the immediate subordinate 106 * level in the map will be checked for label matches. This will 107 * consume the all the data items in the map. 108 * 109 * Note that this cannot be used for finding maps and arrays in at map 110 * and decoding them since it consumes them and does not return their 111 * contents. qcbor_util_decode_to_labeled_item() is more useful for 112 * this. 113 * 114 * This will ignore any data items that do not have integer labels. 115 */ 116 enum attest_token_err_t 117 qcbor_util_get_items_in_map(QCBORDecodeContext *decode_context, 118 struct qcbor_util_items_to_get_t *items); 119 120 121 /** 122 * \brief Decode a map up to a particular label and stop. 123 * 124 * \param[in,out] decode_context The QCBOR decode context to 125 * consume and look through. 126 * \param[in] label The label of the item being sought. 127 * \param[out] item The item that is filled in with the 128 * when the match is found. 129 * 130 * \retval ATTEST_TOKEN_ERR_CBOR_STRUCTURE 131 * The next item in the decode context is not a map. 132 * \retval ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED 133 * The CBOR is not well-formed. 134 * \retval ATTEST_TOKEN_ERR_SUCCESS 135 * The labeled item was found. 136 * \retval ATTEST_TOKEN_ERR_NOT_FOUND 137 The entire map was consumed without finding \c label. 138 * 139 * The next item from \c decode_context must be a map. This is the map 140 * that will be searched. 141 142 * This will decode consuming data items from \c decode_context until 143 * the labeled item is found. It will consume all items in any map or 144 * array encountered before finding \c label. 145 * 146 * Typically this is used to decode to the start of a map or array. 147 * The next data item from \c decode_context will be the first item in 148 * the map or the array. 149 * 150 * This works for any CBOR data type, not just maps or arrays. 151 * 152 * This will ignore any data items that do not have integer labels. 153 **/ 154 enum attest_token_err_t 155 qcbor_util_decode_to_labeled_item(QCBORDecodeContext *decode_context, 156 int32_t label, 157 QCBORItem *item); 158 159 160 /** 161 * \brief Search a map for one particular integer labeled item. 162 * 163 * \param[in,out] decode_context The QCBOR decode context to 164 * consume and look through. 165 * \param[in] label The label of the item being sought. 166 * \param[out] item The item that is filled in when 167 * the match is found. 168 * 169 * \retval ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED 170 * CBOR was not well-formed 171 * \retval ATTEST_TOKEN_ERR_CBOR_STRUCTURE 172 * Starting item on \c decode context was not a map. 173 * \retval ATTEST_TOKEN_ERR_SUCCESS 174 * The labeled item was found and returned. 175 * \retval ATTEST_TOKEN_ERR_NOT_FOUND 176 * The entire map was consumed without finding \c label. 177 * 178 * This is qcbor_util_get_items_in_map() for just one item. 179 * 180 * This will consume the whole map. It is most useful for getting 181 * unstructured data items like integers and strings, but not good for 182 * arrays and maps. See qcbor_util_decode_to_labeled_item() for arrays 183 * and maps. 184 */ 185 enum attest_token_err_t 186 qcbor_util_get_item_in_map(QCBORDecodeContext *decode_context, 187 int32_t label, 188 QCBORItem *item); 189 190 191 /** 192 * \brief Search encoded CBOR from beginning to end for labeled item. 193 * 194 * \param[in] payload Encoded chunk of CBOR to decode. 195 * \param[in] label Integer label of item to look for. 196 * \param[in] qcbor_type One of \c QCBOR_TYPE_xxx indicating the 197 * type of the data item expected. 198 * \param[out] item Place to copy the \c QCBORItem to that 199 * describes what was found. 200 * 201 * \retval ATTEST_TOKEN_ERR_CBOR_TYPE 202 * The labeled item was found, but it didn't match \c qcbor_type. 203 * \retval ATTEST_TOKEN_ERR_SUCCESS 204 * The labeled item was found and returned. 205 * \retval ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED 206 * CBOR was not well-formed 207 * \retval ATTEST_TOKEN_ERR_CBOR_STRUCTURE 208 * A map was expected. 209 * \retval ATTEST_TOKEN_ERR_NOT_FOUND 210 * The entire map was consumed without finding \c label. 211 * 212 * This will decode the \c payload from beginning to end. If there are 213 * extra bytes at the end of it or all the maps and arrays in it are 214 * not closed this will return an error. 215 * 216 * Since this decodes the payload from start to finish to find one 217 * item, calling this multiple times to get multiple items will cause 218 * the payload to be completely decoded multiple times. This is not as 219 * efficient as qcbor_util_get_items_in_map(), but not that costly 220 * either. 221 * 222 * This uses qcbor_util_get_item_in_map() to do its work. 223 */ 224 enum attest_token_err_t 225 qcbor_util_get_top_level_item_in_map(struct q_useful_buf_c payload, 226 int32_t label, 227 uint_fast8_t qcbor_type, 228 QCBORItem *item); 229 230 231 #ifdef __cplusplus 232 } 233 #endif 234 235 #endif /* __QCBOR_UTILS_H__ */ 236