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.h"
15
16 #include "edhoc/cert.h"
17 #include "edhoc/signature_or_mac_msg.h"
18 #include "edhoc/retrieve_cred.h"
19
20 #include "common/crypto_wrapper.h"
21 #include "common/oscore_edhoc_error.h"
22 #include "common/print_util.h"
23 #include "common/memcpy_s.h"
24
25 #include "cbor/edhoc_decode_id_cred_x.h"
26
27 /**
28 * @brief This function verifies a certificate and copies it to the cred
29 * buffer. It also extracts the public key contained in the
30 * certificate.
31 *
32 * @param static_dh_auth type of the key contained in the certificate --
33 * signature key or static DH key.
34 * @param cred_array array containing credentials
35 * @param cred_num number of credentials
36 * @param label map label of id_cred_x
37 * @param cert the certificate
38 * @param cert_len length of the certificate
39 * @param cred cred buffer
40 * @param cred_len length of cred
41 * @param pk public key buffer
42 * @param pk_len length of pk
43 * @param g static DH public key buffer
44 * @param g_len length of g
45 * @return enum err
46 */
47 static inline enum err
verify_cert2cred(bool static_dh_auth,struct other_party_cred * cred_array,uint16_t cred_num,enum id_cred_x_label label,const uint8_t * cert,uint32_t cert_len,uint8_t * cred,uint32_t * cred_len,uint8_t * pk,uint32_t * pk_len,uint8_t * g,uint32_t * g_len)48 verify_cert2cred(bool static_dh_auth, struct other_party_cred *cred_array,
49 uint16_t cred_num, enum id_cred_x_label label,
50 const uint8_t *cert, uint32_t cert_len, uint8_t *cred,
51 uint32_t *cred_len, uint8_t *pk, uint32_t *pk_len, uint8_t *g,
52 uint32_t *g_len)
53 {
54 PRINT_ARRAY("ID_CRED_x contains a certificate", cert, cert_len);
55 TRY(encode_byte_string(cert, cert_len, cred, cred_len));
56
57 bool verified = false;
58 switch (label) {
59 /* for now we transfer a single certificate, therefore bag and chain are the same */
60 case x5bag:
61 case x5chain:
62 if (static_dh_auth) {
63 *pk_len = 0;
64 TRY(cert_x509_verify(cert, cert_len, cred_array,
65 cred_num, g, g_len, &verified));
66 } else {
67 *g_len = 0;
68 TRY(cert_x509_verify(cert, cert_len, cred_array,
69 cred_num, pk, pk_len, &verified));
70 }
71 break;
72 case c5b:
73 case c5c:
74 if (static_dh_auth) {
75 *pk_len = 0;
76 TRY(cert_c509_verify(cert, cert_len, cred_array,
77 cred_num, g, g_len, &verified));
78 } else {
79 *g_len = 0;
80 TRY(cert_c509_verify(cert, cert_len, cred_array,
81 cred_num, pk, pk_len, &verified));
82 }
83 break;
84 break;
85
86 default:
87 break;
88 }
89
90 if (verified) {
91 PRINT_MSG("Certificate verification successful!\n");
92 return ok;
93 } else {
94 return certificate_authentication_failed;
95 }
96 }
97
get_local_cred(bool static_dh_auth,struct other_party_cred * cred_array,uint16_t cred_num,uint8_t * id_cred,uint32_t id_cred_len,uint8_t * cred,uint32_t * cred_len,uint8_t * pk,uint32_t * pk_len,uint8_t * g,uint32_t * g_len)98 static enum err get_local_cred(bool static_dh_auth,
99 struct other_party_cred *cred_array,
100 uint16_t cred_num, uint8_t *id_cred,
101 uint32_t id_cred_len, uint8_t *cred,
102 uint32_t *cred_len, uint8_t *pk,
103 uint32_t *pk_len, uint8_t *g, uint32_t *g_len)
104 {
105 for (uint16_t i = 0; i < cred_num; i++) {
106 if ((cred_array[i].id_cred.len == id_cred_len) &&
107 (0 ==
108 memcmp(cred_array[i].id_cred.ptr, id_cred, id_cred_len))) {
109 /*retrieve CRED_x*/
110 TRY(_memcpy_s(cred, *cred_len, cred_array[i].cred.ptr,
111 cred_array[i].cred.len));
112 *cred_len = cred_array[i].cred.len;
113
114 /*retrieve PK*/
115 if (static_dh_auth) {
116 *pk_len = 0;
117 if (cred_array[i].g.len == 65) {
118 /*decompressed P256 DH pk*/
119 g[0] = 0x2;
120 TRY(_memcpy_s(&g[1], *g_len - 1,
121 &cred_array[i].g.ptr[1],
122 32));
123 *g_len = 33;
124
125 } else {
126 TRY(_memcpy_s(g, *g_len,
127 cred_array[i].g.ptr,
128 cred_array[i].g.len));
129 *g_len = cred_array[i].g.len;
130 }
131
132 } else {
133 *g_len = 0;
134 TRY(_memcpy_s(pk, *pk_len, cred_array[i].pk.ptr,
135 cred_array[i].pk.len));
136 *pk_len = cred_array[i].pk.len;
137 }
138 return ok;
139 }
140 }
141
142 return credential_not_found;
143 }
144
retrieve_cred(bool static_dh_auth,struct other_party_cred * cred_array,uint16_t cred_num,uint8_t * id_cred,uint32_t id_cred_len,uint8_t * cred,uint32_t * cred_len,uint8_t * pk,uint32_t * pk_len,uint8_t * g,uint32_t * g_len)145 enum err retrieve_cred(bool static_dh_auth, struct other_party_cred *cred_array,
146 uint16_t cred_num, uint8_t *id_cred,
147 uint32_t id_cred_len, uint8_t *cred, uint32_t *cred_len,
148 uint8_t *pk, uint32_t *pk_len, uint8_t *g,
149 uint32_t *g_len)
150 {
151 size_t decode_len = 0;
152 struct id_cred_x_map map;
153
154 TRY_EXPECT(cbor_decode_id_cred_x_map(id_cred, id_cred_len, &map,
155 &decode_len),
156 true);
157 /*the cred should be locally available on the device if
158 kid, x5u, x5t, c5u, c5t is used*/
159 if ((map._id_cred_x_map_kid_present != 0) ||
160 (map._id_cred_x_map_x5u_present != 0) ||
161 (map._id_cred_x_map_x5t_present != 0) ||
162 (map._id_cred_x_map_c5u_present != 0) ||
163 (map._id_cred_x_map_c5t_present != 0)) {
164 TRY(get_local_cred(static_dh_auth, cred_array, cred_num,
165 id_cred, id_cred_len, cred, cred_len, pk,
166 pk_len, g, g_len));
167 return ok;
168 }
169 /*x5chain*/
170 else if (map._id_cred_x_map_x5chain_present != 0) {
171 TRY(verify_cert2cred(
172 static_dh_auth, cred_array, cred_num, x5chain,
173 map._id_cred_x_map_x5chain._id_cred_x_map_x5chain.value,
174 (uint32_t) map._id_cred_x_map_x5chain._id_cred_x_map_x5chain.len,
175 cred, cred_len, pk, pk_len, g, g_len));
176 return ok;
177 }
178 /*x5bag*/
179 else if (map._id_cred_x_map_x5bag_present != 0) {
180 TRY(verify_cert2cred(
181 static_dh_auth, cred_array, cred_num, x5bag,
182 map._id_cred_x_map_x5bag._id_cred_x_map_x5bag.value,
183 (uint32_t) map._id_cred_x_map_x5bag._id_cred_x_map_x5bag.len, cred,
184 cred_len, pk, pk_len, g, g_len));
185 return ok;
186 }
187 /*c5c*/
188 else if (map._id_cred_x_map_c5c_present != 0) {
189 TRY(verify_cert2cred(
190 static_dh_auth, cred_array, cred_num, c5c,
191 map._id_cred_x_map_c5c._id_cred_x_map_c5c.value,
192 (uint32_t) map._id_cred_x_map_c5c._id_cred_x_map_c5c.len, cred,
193 cred_len, pk, pk_len, g, g_len));
194 return ok;
195 }
196 /*c5b*/
197 else if (map._id_cred_x_map_c5b_present != 0) {
198 TRY(verify_cert2cred(
199 static_dh_auth, cred_array, cred_num, c5b,
200 map._id_cred_x_map_c5b._id_cred_x_map_c5b.value,
201 (uint32_t) map._id_cred_x_map_c5b._id_cred_x_map_c5b.len, cred,
202 cred_len, pk, pk_len, g, g_len));
203 return ok;
204 }
205
206 return credential_not_found;
207 }
208