1 /*
2  * attest_token.h
3  *
4  * Copyright (c) 2018-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 #ifndef __ATTEST_TOKEN_H__
13 #define __ATTEST_TOKEN_H__
14 
15 #include <stdint.h>
16 #include "qcbor/qcbor.h"
17 #ifdef SYMMETRIC_INITIAL_ATTESTATION
18 #include "t_cose_mac0_sign.h"
19 #else
20 #include "t_cose_sign1_sign.h"
21 #endif
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 /**
28  * \file attest_token.h
29  *
30  * \brief Attestation Token Creation Interface
31  *
32  * The context and functions here are the way to create an attestation
33  * token. The steps are roughly:
34  *
35  *   -# Create and initialize an attest_token_encode_ctx indicating the
36  *   options, key and such using attest_token_encode_start().
37  *
38  *   -# Use various add methods to fill in the payload with claims. The
39  *   encoding context can also be borrowed for more rich payloads.
40  *
41  *   -# Call attest_token_encode_finish() to create the signature and finish
42  *   formatting the COSE signed output.
43  */
44 
45 /**
46  Error codes returned from attestation token creation.
47  */
48 enum attest_token_err_t {
49     /** Success */
50     ATTEST_TOKEN_ERR_SUCCESS = 0,
51     /** The buffer passed in to receive the output is too small. */
52     ATTEST_TOKEN_ERR_TOO_SMALL,
53     /** Something went wrong formatting the CBOR, most likely the
54      payload has maps or arrays that are not closed. */
55     ATTEST_TOKEN_ERR_CBOR_FORMATTING,
56     /** A general, unspecific error when creating or decoding the
57         token. */
58     ATTEST_TOKEN_ERR_GENERAL,
59     /** A hash function that is needed to make the token is not
60         available. */
61     ATTEST_TOKEN_ERR_HASH_UNAVAILABLE,
62     /** CBOR Syntax not well-formed -- a CBOR syntax error. */
63     ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED,
64     /** Bad CBOR structure, for example not a map when was is
65         required. */
66     ATTEST_TOKEN_ERR_CBOR_STRUCTURE,
67     /** Bad CBOR type, for example an not a text string, when a text
68         string is required. */
69     ATTEST_TOKEN_ERR_CBOR_TYPE,
70     /** Integer too large, for example an \c int32_t is required, but
71         value only fits in \c int64_t */
72     ATTEST_TOKEN_ERR_INTEGER_VALUE,
73     /** Something is wrong with the COSE message structure, missing
74         headers or such. */
75     ATTEST_TOKEN_ERR_COSE_FORMAT,
76     /** COSE signature or authentication tag is invalid, data
77         is corrupted. */
78     ATTEST_TOKEN_ERR_COSE_VALIDATION,
79     /** The signing algorithm is not supported. */
80     ATTEST_TOKEN_ERR_UNSUPPORTED_SIG_ALG,
81     /** Out of memory. */
82     ATTEST_TOKEN_ERR_INSUFFICIENT_MEMORY,
83     /** Tampering detected in cryptographic function. */
84     ATTEST_TOKEN_ERR_TAMPERING_DETECTED,
85     /** Signing key is not found or of wrong type. */
86     ATTEST_TOKEN_ERR_SIGNING_KEY,
87     /** Verification key is not found or of wrong type. */
88     ATTEST_TOKEN_ERR_VERIFICATION_KEY,
89     /** No token was given or validated */
90     ATTEST_TOKEN_ERR_NO_VALID_TOKEN,
91     /** Data item with label wasn't found. */
92     ATTEST_TOKEN_ERR_NOT_FOUND,
93     /** SW Components absence not correctly indicated. */
94     ATTEST_TOKEN_ERR_SW_COMPONENTS_MISSING
95 };
96 
97 /**
98  * Request that the claims internally generated not be added to the
99  * token.  This is a test mode that results in a static token that
100  * never changes. Only the nonce is included. The nonce is under
101  * the callers control unlike the other claims.
102  */
103 #define TOKEN_OPT_OMIT_CLAIMS        0x40000000
104 
105 /**
106  * A special test mode where a proper signature is not produced. In
107  * its place there is a concatenation of hashes of the payload to be
108  * the same size as the signature. This works and can be used to
109  * verify all of the SW stack except the public signature part. The
110  * token has no security value in this mode because anyone can
111  * replicate it. */
112 #define TOKEN_OPT_SHORT_CIRCUIT_SIGN 0x80000000
113 
114 /**
115  * The context for creating an attestation token.  The caller of
116  * attest_token_encode must create one of these and pass it to the functions
117  * here. It is small enough that it can go on the stack. It is most of
118  * the memory needed to create a token except the output buffer and
119  * any memory requirements for the cryptographic operations.
120  *
121  * The structure is opaque for the caller.
122  *
123  * This is roughly 148 + 8 + 32 = 188 bytes
124  */
125 struct attest_token_encode_ctx {
126     /* Private data structure */
127     QCBOREncodeContext           cbor_enc_ctx;
128     uint32_t                     opt_flags;
129     int32_t                      key_select;
130 #ifdef SYMMETRIC_INITIAL_ATTESTATION
131     struct t_cose_mac0_sign_ctx  mac_ctx;
132 #else
133     struct t_cose_sign1_sign_ctx signer_ctx;
134 #endif
135 };
136 
137 /**
138  * \brief Initialize a token creation context.
139  *
140  * \param[in] me          The token creation context to be initialized.
141  * \param[in] opt_flags   Flags to select different custom options,
142  *                        for example \ref TOKEN_OPT_OMIT_CLAIMS.
143  * \param[in] key_select  Selects which attestation key to sign with.
144  * \param[in] cose_alg_id The algorithm to sign with. The IDs are
145  *                        defined in [COSE (RFC 8152)]
146  *                        (https://tools.ietf.org/html/rfc8152) or
147  *                        in the [IANA COSE Registry]
148  *                        (https://www.iana.org/assignments/cose/cose.xhtml).
149  * \param[out] out_buffer The output buffer to write the encoded token into.
150  *
151  * \return one of the \ref attest_token_err_t errors.
152  *
153  * The size of the buffer in \c out_buffer->len
154  * determines the size of the token that can be created. It must be
155  * able to hold the final encoded and signed token. The data encoding
156  * overhead is just that of CBOR. The signing overhead depends on the
157  * signing key size. It is about 150 bytes for 256-bit ECDSA.
158  *
159  * If \c out_buffer->ptr is \c NULL and \c out_buffer_ptr->len is
160  * large like \c UINT32_MAX no token will be created but the length of
161  * the token that would be created will be in \c completed_token as
162  * returned by attest_token_encode_finish(). None of the cryptographic
163  * functions run during this, but the sizes of what they would output
164  * is taken into account.
165  */
166 enum attest_token_err_t
167 attest_token_encode_start(struct attest_token_encode_ctx *me,
168                           uint32_t opt_flags,
169                           int32_t key_select,
170                           int32_t cose_alg_id,
171                           const struct q_useful_buf *out_buffer);
172 
173 /**
174  * \brief Get a copy of the CBOR encoding context
175  *
176  * \param[in] me     Token creation context.
177  *
178  * \return The CBOR encoding context
179  *
180  * Allows the caller to encode CBOR right into the output buffer using
181  * any of the \c QCBOREncode_AddXXXX() methods. Anything added here
182  * will be part of the payload that gets hashed. This can be used to
183  * make complex CBOR structures. All open arrays and maps must be
184  * close before calling any other \c attest_token_encode methods.  \c
185  * QCBOREncode_Finish() should not be closed on this context.
186  */
187 QCBOREncodeContext *
188 attest_token_encode_borrow_cbor_cntxt(struct attest_token_encode_ctx *me);
189 
190 /**
191  * \brief Add a 64-bit signed integer claim
192  *
193  * \param[in] me     Token creation context.
194  * \param[in] label  Integer label for claim.
195  * \param[in] value  The integer claim data.
196  */
197 void attest_token_encode_add_integer(struct attest_token_encode_ctx *me,
198                                      int32_t label,
199                                      int64_t value);
200 
201 /**
202  * \brief Add a binary string claim
203  *
204  * \param[in] me     Token creation context.
205  * \param[in] label  Integer label for claim.
206  * \param[in] value  The binary claim data.
207  */
208 void attest_token_encode_add_bstr(struct attest_token_encode_ctx *me,
209                                   int32_t label,
210                                   const struct q_useful_buf_c *value);
211 
212 /**
213  * \brief Add a text string claim
214  *
215  * \param[in] me     Token creation context.
216  * \param[in] label  Integer label for claim.
217  * \param[in] value  The text claim data.
218  */
219 void attest_token_encode_add_tstr(struct attest_token_encode_ctx *me,
220                                   int32_t label,
221                                   const struct q_useful_buf_c *value);
222 
223 /**
224  * \brief Add some already-encoded CBOR to payload
225  *
226  * \param[in] me       Token creation context.
227  * \param[in] label    Integer label for claim.
228  * \param[in] encoded  The already-encoded CBOR.
229  *
230  * Encoded CBOR must be a full map or full array or a non-aggregate
231  * type. It cannot be a partial map or array. It can be nested maps
232  * and arrays, but they must all be complete.
233  */
234 void attest_token_encode_add_cbor(struct attest_token_encode_ctx *me,
235                                   int32_t label,
236                                   const struct q_useful_buf_c *encoded);
237 
238 /**
239  * \brief Finish the token, complete the signing and get the result
240  *
241  * \param[in] me                Token Creation Context.
242  * \param[out] completed_token  Pointer and length to completed token.
243  *
244  * \return one of the \ref attest_token_err_t errors.
245  *
246  * This completes the token after the payload has been added. When
247  * this is called the signing algorithm is run and the final
248  * formatting of the token is completed.
249  */
250 enum attest_token_err_t
251 attest_token_encode_finish(struct attest_token_encode_ctx *me,
252                            struct q_useful_buf_c *completed_token);
253 
254 #ifdef __cplusplus
255 }
256 #endif
257 
258 #endif /* __ATTEST_TOKEN_H__ */
259