Branch data Line data Source code
1 : : /*
2 : : Copyright (c) 2021 Fraunhofer AISEC. See the COPYRIGHT
3 : : file at the top-level directory of this distribution.
4 : :
5 : : Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 : : http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 : : <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 : : option. This file may not be copied, modified, or distributed
9 : : except according to those terms.
10 : : */
11 : :
12 : : #include <string.h>
13 : :
14 : : #include "edhoc/cert.h"
15 : : #include "edhoc/bstr_encode_decode.h"
16 : : #include "edhoc/retrieve_cred.h"
17 : :
18 : : #include "common/crypto_wrapper.h"
19 : : #include "common/oscore_edhoc_error.h"
20 : : #include "common/print_util.h"
21 : : #include "common/memcpy_s.h"
22 : :
23 : : #include "cbor/edhoc_decode_id_cred_x.h"
24 : :
25 : : /**
26 : : * @brief Verifies a certificate and copies it to the cred
27 : : * buffer. It also extracts the public key
28 : : * contained in the certificate.
29 : : *
30 : : * @param static_dh_auth Type of the key contained in the certificate --
31 : : * signature key or static DH key.
32 : : * @param cred_array array containing credentials.
33 : : * @param label CBOR map label of id_cred_x.
34 : : * @param[in] cert The certificate.
35 : : * @param[in] cred Cred buffer.
36 : : * @param[in] pk Public key.
37 : : * @param[in] g Static DH public key.
38 : : * @return Ok or error code
39 : : */
40 : : static inline enum err
41 : 2 : verify_cert2cred(bool static_dh_auth, struct cred_array *cred_array,
42 : : enum id_cred_x_label label, struct const_byte_array *cert,
43 : : struct byte_array *cred, struct byte_array *pk,
44 : : struct byte_array *g)
45 : : {
46 : 2 : PRINT_ARRAY("ID_CRED_x contains a certificate", cert->ptr, cert->len);
47 [ - + ]: 2 : TRY(encode_bstr((struct byte_array *)cert, cred));
48 : :
49 : 2 : bool verified = false;
50 [ + - - ]: 2 : switch (label) {
51 : : /* for now we transfer a single certificate, therefore bag and chain are the same */
52 : 2 : case x5bag:
53 : : case x5chain:
54 [ - + ]: 2 : if (static_dh_auth) {
55 : 0 : pk->len = 0;
56 [ # # ]: 0 : TRY(cert_x509_verify(cert, cred_array, g, &verified));
57 : : } else {
58 : 2 : g->len = 0;
59 [ - + ]: 2 : TRY(cert_x509_verify(cert, cred_array, pk, &verified));
60 : : }
61 : 2 : break;
62 : 0 : case c5b:
63 : : case c5c:
64 [ # # ]: 0 : if (static_dh_auth) {
65 : 0 : pk->len = 0;
66 [ # # ]: 0 : TRY(cert_c509_verify(cert, cred_array, g, &verified));
67 : : } else {
68 : 0 : g->len = 0;
69 [ # # ]: 0 : TRY(cert_c509_verify(cert, cred_array, pk, &verified));
70 : : }
71 : 0 : break;
72 : : break;
73 : :
74 : 0 : default:
75 : 0 : break;
76 : : }
77 : :
78 [ + - ]: 2 : if (verified) {
79 : 2 : PRINT_MSG("Certificate verification successful!\n");
80 : 2 : return ok;
81 : : } else {
82 : 0 : return certificate_authentication_failed;
83 : : }
84 : : return ok;
85 : : }
86 : :
87 : : /**
88 : : * @brief Get the local cred object.
89 : : *
90 : : * @param static_dh_auth True if static DH is used for authentication.
91 : : * @param[in] cred_array An array of trust anchors
92 : : * @param[in] ID_cred The ID of the actual credential.
93 : : * @param[out] cred The retrievd credentials
94 : : * @param[out] pk The retrievd signature authentication public key
95 : : * @param[out] g The retrievd static DH authentication public key
96 : : * @return Ok or error code
97 : : */
98 : 4 : static enum err get_local_cred(bool static_dh_auth,
99 : : struct cred_array *cred_array,
100 : : struct byte_array *ID_cred,
101 : : struct byte_array *cred, struct byte_array *pk,
102 : : struct byte_array *g)
103 : : {
104 [ + - ]: 4 : for (uint32_t i = 0; i < cred_array->len; i++) {
105 [ + - ]: 4 : if ((cred_array->ptr[i].id_cred.len == ID_cred->len) &&
106 [ + - ]: 4 : (0 == memcmp(cred_array->ptr[i].id_cred.ptr, ID_cred->ptr,
107 : : ID_cred->len))) {
108 : : /*retrieve CRED_x*/
109 [ - + ]: 4 : TRY(_memcpy_s(cred->ptr, cred->len,
110 : : cred_array->ptr[i].cred.ptr,
111 : : cred_array->ptr[i].cred.len));
112 : 4 : cred->len = cred_array->ptr[i].cred.len;
113 : :
114 : : /*retrieve PK*/
115 [ - + ]: 4 : if (static_dh_auth) {
116 : 0 : pk->len = 0;
117 [ # # ]: 0 : if (cred_array->ptr[i].g.len == 65) {
118 : : /*decompressed P256 DH pk*/
119 : 0 : g->ptr[0] = 0x2;
120 [ # # ]: 0 : TRY(_memcpy_s(
121 : : &g->ptr[1], g->len - 1,
122 : : &cred_array->ptr[i].g.ptr[1],
123 : : 32));
124 : 0 : g->len = 33;
125 : :
126 : : } else {
127 [ # # ]: 0 : TRY(_memcpy_s(g->ptr, g->len,
128 : : cred_array->ptr[i].g.ptr,
129 : : cred_array->ptr[i].g.len));
130 : 0 : g->len = cred_array->ptr[i].g.len;
131 : : }
132 : :
133 : : } else {
134 : 4 : g->len = 0;
135 [ - + ]: 4 : TRY(_memcpy_s(pk->ptr, pk->len,
136 : : cred_array->ptr[i].pk.ptr,
137 : : cred_array->ptr[i].pk.len));
138 : 4 : pk->len = cred_array->ptr[i].pk.len;
139 : : }
140 : 4 : return ok;
141 : : }
142 : : }
143 : :
144 : 0 : return credential_not_found;
145 : : }
146 : :
147 : 6 : enum err retrieve_cred(bool static_dh_auth, struct cred_array *cred_array,
148 : : struct byte_array *id_cred, struct byte_array *cred,
149 : : struct byte_array *pk, struct byte_array *g)
150 : : {
151 : 6 : size_t decode_len = 0;
152 : 6 : struct id_cred_x_map map = { 0 };
153 : :
154 [ - + ]: 6 : TRY_EXPECT(cbor_decode_id_cred_x_map(id_cred->ptr, id_cred->len, &map,
155 : : &decode_len),
156 : : 0);
157 : : /*the cred should be locally available on the device if
158 : : kid, x5u, x5t, c5u, c5t is used*/
159 [ + - + - ]: 6 : if (map.id_cred_x_map_kid_present || map.id_cred_x_map_x5u_present ||
160 [ + + + - ]: 6 : map.id_cred_x_map_x5t_present || map.id_cred_x_map_c5u_present ||
161 [ - + ]: 2 : map.id_cred_x_map_c5t_present) {
162 [ - + ]: 4 : TRY(get_local_cred(static_dh_auth, cred_array, id_cred, cred,
163 : : pk, g));
164 : 4 : return ok;
165 : : }
166 : : /*x5chain*/
167 [ + - ]: 2 : else if (map.id_cred_x_map_x5chain_present) {
168 : 2 : struct const_byte_array cert = BYTE_ARRAY_INIT(
169 : : map.id_cred_x_map_x5chain.id_cred_x_map_x5chain.value,
170 : : (uint32_t)map.id_cred_x_map_x5chain
171 : : .id_cred_x_map_x5chain.len);
172 : :
173 [ - + ]: 2 : TRY(verify_cert2cred(static_dh_auth, cred_array, x5chain, &cert,
174 : : cred, pk, g));
175 : 2 : return ok;
176 : : }
177 : : /*x5bag*/
178 [ # # ]: 0 : else if (map.id_cred_x_map_x5bag_present) {
179 : 0 : struct const_byte_array cert = BYTE_ARRAY_INIT(
180 : : map.id_cred_x_map_x5bag.id_cred_x_map_x5bag.value,
181 : : (uint32_t)map.id_cred_x_map_x5bag.id_cred_x_map_x5bag
182 : : .len);
183 [ # # ]: 0 : TRY(verify_cert2cred(static_dh_auth, cred_array, x5bag, &cert,
184 : : cred, pk, g));
185 : 0 : return ok;
186 : : }
187 : : /*c5c*/
188 [ # # ]: 0 : else if (map.id_cred_x_map_c5c_present) {
189 : 0 : struct const_byte_array cert = BYTE_ARRAY_INIT(
190 : : map.id_cred_x_map_c5c.id_cred_x_map_c5c.value,
191 : : (uint32_t)map.id_cred_x_map_c5c.id_cred_x_map_c5c.len);
192 [ # # ]: 0 : TRY(verify_cert2cred(static_dh_auth, cred_array, c5c, &cert,
193 : : cred, pk, g));
194 : 0 : return ok;
195 : : }
196 : : /*c5b*/
197 [ # # ]: 0 : else if (map.id_cred_x_map_c5b_present) {
198 : 0 : struct const_byte_array cert = BYTE_ARRAY_INIT(
199 : : map.id_cred_x_map_c5b.id_cred_x_map_c5b.value,
200 : : (uint32_t)map.id_cred_x_map_c5b.id_cred_x_map_c5b.len);
201 [ # # ]: 0 : TRY(verify_cert2cred(static_dh_auth, cred_array, c5b, &cert,
202 : : cred, pk, g));
203 : 0 : return ok;
204 : : }
205 : :
206 : 0 : return credential_not_found;
207 : : }
|