1 /*
2 * t_cose_parameters.h
3 *
4 * Copyright 2019, Laurence Lundblade
5 * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * See BSD-3-Clause license in README.md
10 */
11
12
13 #ifndef t_cose_parameters_h
14 #define t_cose_parameters_h
15
16 #include "q_useful_buf.h"
17 #include "t_cose_common.h"
18 #include <stdint.h>
19 #include "qcbor/qcbor.h"
20
21
22 /**
23 * \file t_cose_parameters.h
24 *
25 * \brief A list of COSE parameter labels, both integer and string.
26 *
27 * It is fixed size to avoid the complexity of memory management and
28 * because the number of parameters is assumed to be small.
29 *
30 * On a 64-bit machine it is 24 * PARAMETER_LIST_MAX which is 244
31 * bytes. That accommodates 10 string parameters and 10 integer parameters
32 * and is small enough to go on the stack.
33 *
34 * On a 32-bit machine: 16 * PARAMETER_LIST_MAX = 176
35 *
36 * This is a big consumer of stack in this implementation. Some
37 * cleverness with a union could save almost 200 bytes of stack, as
38 * this is on the stack twice.
39 */
40 struct t_cose_label_list {
41 /* Terminated by value LABEL_LIST_TERMINATOR */
42 int64_t int_labels[T_COSE_PARAMETER_LIST_MAX+1];
43 /* Terminated by a NULL_Q_USEFUL_BUF_C */
44 struct q_useful_buf_c tstr_labels[T_COSE_PARAMETER_LIST_MAX+1];
45 };
46
47
48 /*
49 * The IANA COSE Header Parameters registry lists label 0 as
50 * "reserved". This means it can be used, but only by a revision of
51 * the COSE standard if it is deemed necessary for some large and good
52 * reason. It cannot just be allocated by IANA as any normal
53 * assignment. See [IANA COSE Registry]
54 * (https://www.iana.org/assignments/cose/cose.xhtml). It is thus
55 * considered safe to use as the list terminator.
56 */
57 #define LABEL_LIST_TERMINATOR 0
58
59
60 /**
61 * A special COSE algorithm ID that indicates no COSE algorithm ID or an unset
62 * COSE algorithm ID.
63 */
64 #define T_COSE_UNSET_ALGORITHM_ID 0
65
66
67 /**
68 * \brief Clear a label list to empty.
69 *
70 * \param[in,out] list The list to clear.
71 */
72 static void
73 clear_label_list(struct t_cose_label_list *list);
74
75
76 /**
77 * \brief Indicate whether label list is clear or not.
78 *
79 * \param[in,out] list The list to check.
80 *
81 * \return true if the list is clear.
82 */
83 static bool
84 is_label_list_clear(const struct t_cose_label_list *list);
85
86
87 /**
88 * \brief Check the unknown parameters against the critical labels list.
89 *
90 * \param[in] critical_labels The list of critical labels.
91 * \param[in] unknown_labels The parameter labels that occurred.
92 *
93 * \retval T_COSE_SUCCESS None of the unknown labels
94 * are critical.
95 * \retval T_COSE_ERR_UNKNOWN_CRITICAL_PARAMETER At least one of the unknown
96 * labels is critical.
97 *
98 * Both lists are of parameter labels (CBOR keys). Check to see none of
99 * the parameter labels in the unknown list occur in the critical list.
100 */
101 enum t_cose_err_t
102 check_critical_labels(const struct t_cose_label_list *critical_labels,
103 const struct t_cose_label_list *unknown_labels);
104
105
106
107 /**
108 * \brief Parse the unprotected COSE header parameters.
109 *
110 * \param[in] decode_context Decode context to read the parameters from.
111 * \param[out] returned_parameters The parsed parameters.
112 *
113 * \returns The same as parse_cose_header_parameters().
114 *
115 * No parameters are mandatory. Which parameters were present or not is
116 * indicated in \c returned_parameters. It is OK for there to be no
117 * parameters at all.
118 *
119 * The first item to be read from the decode_context must be the map
120 * data item that contains the parameters.
121 */
122 enum t_cose_err_t
123 parse_unprotected_header_parameters(QCBORDecodeContext *decode_context,
124 struct t_cose_parameters *returned_parameters,
125 struct t_cose_label_list *unknown);
126
127
128 /**
129 * \brief Parse the protected header parameters.
130 *
131 * \param[in] protected_parameters Pointer and length of CBOR-encoded
132 * protected parameters to parse.
133 * \param[out] returned_parameters The parsed parameters that are returned.
134 *
135 * \retval T_COSE_SUCCESS Protected parameters were parsed.
136 * \retval T_COSE_ERR_CBOR_NOT_WELL_FORMED The CBOR formatting of the protected
137 * parameters is unparsable.
138 *
139 * This parses the contents of the protected header parameters after the bstr
140 * wrapping is removed.
141 *
142 * This will error out if the CBOR is not well-formed, the protected
143 * header parameters are not a map, the algorithm ID is not found, or the
144 * algorithm ID is larger than \c INT32_MAX or smaller than \c
145 * INT32_MIN.
146 */
147 enum t_cose_err_t
148 parse_protected_header_parameters(const struct q_useful_buf_c protected_parameters,
149 struct t_cose_parameters *returned_parameters,
150 struct t_cose_label_list *critical,
151 struct t_cose_label_list *unknown);
152
153
154 /**
155 * \brief Copy and combine protected and unprotected parameters.
156 *
157 * \param[in] protected The protected header parameters to copy.
158 * \param[in] unprotected The unprotected header parameters to copy.
159 * \param[out] returned_parameters Destination for copy.
160 *
161 * \retval T_COSE_ERR_DUPLICATE_PARAMETER If the same parameter occurs in both
162 * protected and unprotected.
163 * \retval T_COSE_SUCCESS If there were no duplicates and the
164 * copy and combine succeeded.
165 *
166 * This merges the protected and unprotected parameters. The COSE standard
167 * does not allow a parameter to be duplicated in protected and unprotected so
168 * this checks and returns an error if so.
169 */
170 enum t_cose_err_t
171 check_and_copy_parameters(const struct t_cose_parameters *protected,
172 const struct t_cose_parameters *unprotected,
173 struct t_cose_parameters *returned_parameters);
174
175
176
177 /* ------------------------------------------------------------------------
178 * Inline implementations of public functions defined above.
179 */
clear_label_list(struct t_cose_label_list * list)180 inline static void clear_label_list(struct t_cose_label_list *list)
181 {
182 memset(list, 0, sizeof(struct t_cose_label_list));
183 }
184
185
186 inline static bool
is_label_list_clear(const struct t_cose_label_list * list)187 is_label_list_clear(const struct t_cose_label_list *list)
188 {
189 return list->int_labels[0] == 0 &&
190 q_useful_buf_c_is_null_or_empty(list->tstr_labels[0]);
191 }
192
193 #endif /* t_cose_parameters_h */
194