1 /*
2  *  t_cose_sign1_verify.h
3  *
4  * Copyright 2019, Laurence Lundblade
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * See BSD-3-Clause license in README.md
9  */
10 
11 
12 #ifndef __T_COSE_SIGN1_VERIFY_H__
13 #define __T_COSE_SIGN1_VERIFY_H__
14 
15 #include <stdint.h>
16 #include "q_useful_buf.h"
17 #include "t_cose_common.h"
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * \file t_cose_sign1_verify.h
25  *
26  * \brief Verify a COSE_Sign1 Message
27  *
28  * This verifies a \c COSE_Sign1 message in compliance with [COSE (RFC 8152)]
29  * (https://tools.ietf.org/html/rfc8152). A \c COSE_Sign1 message is a CBOR
30  * encoded binary blob that contains header parameters, a payload and a
31  * signature. Usually the signature is made with an EC signing
32  * algorithm like ECDSA.
33  *
34  * This implementation is intended to be small and portable to
35  * different OS's and platforms. Its dependencies are:
36  * - [QCBOR](https://github.com/laurencelundblade/QCBOR)
37  * - <stdint.h>, <string.h>, <stddef.h>
38  * - Hash functions like SHA-256
39  * - Signing functions like ECDSA
40  *
41  * There is a cryptographic adaptation layer defined in
42  * t_cose_crypto.h.  An implementation can be made of the functions in
43  * it for different cryptographic libraries. This means that different
44  * integrations with different cryptographic libraries may support
45  * only signing with a particular set of algorithms. Integration with
46  * [OpenSSL](https://www.openssl.org) is supported.  Key ID look up
47  * also varies by different cryptographic library integrations.
48  *
49  * See t_cose_common.h for preprocessor defines to reduce object code
50  * and stack use by disabling features.
51  */
52 
53 
54 /**
55  * Context for signature verification.  It is about 24 bytes on a
56  * 64-bit machine and 12 bytes on a 32-bit machine.
57  */
58 struct t_cose_sign1_verify_ctx {
59     /* Private data structure */
60     struct t_cose_key     verification_key;
61     int32_t               option_flags;
62 };
63 
64 
65 /**
66  * \brief Initialize for \c COSE_Sign1 message verification.
67  *
68  * \param[in,out]  context       The context to initialize.
69  * \param[in]      option_flags  Options controlling the verification.
70  *
71  * This must be called before using the verification context.
72  */
73 static void
74 t_cose_sign1_verify_init(struct t_cose_sign1_verify_ctx *context,
75                          int32_t                         option_flags);
76 
77 
78 /**
79  * \brief Set key for \c COSE_Sign1 message verification.
80  *
81  * \param[in] verification_key  The verification key to use.
82  *
83  * There are four main ways that the verification key is found and
84  * supplied to t_cose so that t_cose_sign1_verify() succeeds.
85  *
86  * -# Look up by kid parameter and set by t_cose_sign1_set_verification_key()
87  * -# Look up by other and set by t_cose_sign1_set_verification_key()
88  * -# Determination by kid that short circuit signing is used (test only)
89  * -# Look up by kid parameter in cryptographic adaptation  layer
90  *
91  * Note that there is no means where certificates, like X.509
92  * certificates, are provided in the COSE parameters. Perhaps there
93  * will be in the future but that is not in common use or supported by
94  * this implementation.
95  *
96  * To use 1 it is necessary to call t_cose_sign1_verify_init() and
97  * t_cose_sign1_verify() twice.  The first time
98  * t_cose_sign1_verify_init() is called, give the \ref
99  * T_COSE_OPT_DECODE_ONLY option.  Then call t_cose_sign1_verify() and
100  * the kid will be returned in \c parameters. The caller finds the kid on
101  * their own. Then call this to set the key. Last call
102  * t_cose_sign1_verify(), again without the \ref T_COSE_OPT_DECODE_ONLY
103  * option.
104  *
105  * To use 2 the key is somehow determined without the kid and
106  * t_cose_sign1_set_verification_key() is called with it. Then
107  * t_cose_sign1_verify() is called. Note that this implementation
108  * cannot return non-standard header parameters, at least not yet.
109  *
110  * To use 3, initialize with \ref T_COSE_OPT_ALLOW_SHORT_CIRCUIT.  No
111  * call to t_cose_sign1_set_verification_key() is necessary. If you do
112  * call t_cose_sign1_set_verification_key(), the kid for short circuit
113  * signing will be recognized and the set key will be ignored.
114  *
115  * To use 4, first be sure that the cryptographic adapter supports
116  * look up by kid.  There's no API to determine this, so it is
117  * probably determined by other system documentation (aka source
118  * code).  In this mode, all that is necessary is to call
119  * t_cose_sign1_verify().
120  *
121  * 3 always works no matter what is done in the cryptographic
122  * adaptation layer because it never calls out to it. The OpenSSL
123  * adaptor supports 1 and 2.
124  */
125 static void
126 t_cose_sign1_set_verification_key(struct t_cose_sign1_verify_ctx *context,
127                                   struct t_cose_key               verification_key);
128 
129 
130 /**
131  * \brief Verify a COSE_Sign1
132  *
133  * \param[in] sign1         Pointer and length of CBOR encoded \c COSE_Sign1
134  *                          message that is to be verified.
135  * \param[out] payload      Pointer and length of the payload.
136  * \param[out] parameters   Place to return parsed parameters. Maybe be \c NULL.
137  *
138  * \return This returns one of the error codes defined by \ref t_cose_err_t.
139  *
140  * See t_cose_sign1_set_verification_key() for discussion on where
141  * the verification key comes from.
142  *
143  * Verification involves the following steps.
144  *
145  * - The CBOR-format COSE_Sign1 structure is parsed. It makes sure \c sign1
146  * is valid CBOR and follows the required structure for \c COSE_Sign1.
147  *
148  * - The protected header parameters are parsed, particular the algorithm id.
149  *
150  * - The unprotected headers parameters are parsed, particularly the kid.
151  *
152  * - The payload is identified. The internals of the payload are not parsed.
153  *
154  * - The expected hash, the "to-be-signed" bytes are computed. The hash
155  * algorithm to use comes from the signing algorithm. If the algorithm is
156  * not known or not supported this will error out.
157  *
158  * - Finally, the signature verification is performed.
159  *
160  * If it is successful, the pointer to the CBOR-encoded payload is
161  * returned. The parameters are returned if requested. All pointers
162  * returned are to memory in the \c sign1 passed in.
163  *
164  * Note that this only handles standard COSE header parameters. There are no
165  * facilities for custom header parameters, even though they are allowed by
166  * the COSE standard.
167  *
168  * This will recognize the special key ID for short-circuit signing
169  * and verify it if the \ref T_COSE_OPT_ALLOW_SHORT_CIRCUIT is set.
170  *
171  * Indefinite length CBOR strings are not supported by this
172  * implementation.  \ref T_COSE_ERR_SIGN1_FORMAT will be returned if
173  * they are in the input \c COSE_Sign1 messages. For example, if the
174  * payload is an indefinite length byte string, this error will be
175  * returned.
176  */
177 enum t_cose_err_t t_cose_sign1_verify(struct t_cose_sign1_verify_ctx *context,
178                                       struct q_useful_buf_c           sign1,
179                                       struct q_useful_buf_c          *payload,
180                                       struct t_cose_parameters       *parameters);
181 
182 
183 
184 
185 /* ------------------------------------------------------------------------
186  * Inline implementations of public functions defined above.
187  */
188 static inline void
t_cose_sign1_verify_init(struct t_cose_sign1_verify_ctx * me,int32_t option_flags)189 t_cose_sign1_verify_init(struct t_cose_sign1_verify_ctx *me,
190                          int32_t                option_flags)
191 {
192     me->option_flags = option_flags;
193     me->verification_key = T_COSE_NULL_KEY;
194 }
195 
196 
197 static inline void
t_cose_sign1_set_verification_key(struct t_cose_sign1_verify_ctx * me,struct t_cose_key verification_key)198 t_cose_sign1_set_verification_key(struct t_cose_sign1_verify_ctx *me,
199                                   struct t_cose_key               verification_key)
200 {
201     me->verification_key = verification_key;
202 }
203 #endif /* __T_COSE_SIGN1_VERIFY_H__ */
204