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