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 <stdint.h>
13 #include <stdbool.h>
14
15 #include "edhoc/retrieve_cred.h"
16 #include "edhoc/plaintext.h"
17 #include "edhoc/signature_or_mac_msg.h"
18 #include "edhoc/int_encode_decode.h"
19
20 #include "common/oscore_edhoc_error.h"
21 #include "common/memcpy_s.h"
22 #include "common/print_util.h"
23
24 #include "cbor/edhoc_decode_plaintext2.h"
25 #include "cbor/edhoc_decode_plaintext3.h"
26 #include "cbor/edhoc_encode_id_cred_x.h"
27
28 /**
29 * @brief Encodes ID_CRED_x as a CBOR map.
30 * @param label The CBOR map label.
31 * @param algo The EDHOC hash algorithm used in x5t. This
32 * parameter can take any other value when xchain
33 * or kid are used.
34 * @param id The actual credential identifier.
35 * @param id_len Length of id.
36 * @param[out] id_cred_x The encoded value.
37 * @retval Ok or error.
38 */
id_cred_x_encode(enum id_cred_x_label label,int algo,const void * id,uint32_t id_len,struct byte_array * id_cred_x)39 static enum err id_cred_x_encode(enum id_cred_x_label label, int algo,
40 const void *id, uint32_t id_len,
41 struct byte_array *id_cred_x)
42 {
43 struct id_cred_x_map map = { 0 };
44 size_t payload_len_out;
45
46 switch (label) {
47 case kid:
48 //todo update that to v15
49 map.id_cred_x_map_kid_present = true;
50 map.id_cred_x_map_kid.id_cred_x_map_kid_choice =
51 id_cred_x_map_kid_int_c;
52 map.id_cred_x_map_kid.id_cred_x_map_kid_int =
53 *((const int32_t *)id);
54 break;
55 case x5chain:
56 map.id_cred_x_map_x5chain_present = true;
57 map.id_cred_x_map_x5chain.id_cred_x_map_x5chain.value = id;
58 map.id_cred_x_map_x5chain.id_cred_x_map_x5chain.len = id_len;
59 break;
60 case x5t:
61 map.id_cred_x_map_x5t_present = true;
62 map.id_cred_x_map_x5t.id_cred_x_map_x5t_alg_choice =
63 id_cred_x_map_x5t_alg_int_c;
64 map.id_cred_x_map_x5t.id_cred_x_map_x5t_alg_int = algo;
65 map.id_cred_x_map_x5t.id_cred_x_map_x5t_hash.value = id;
66 map.id_cred_x_map_x5t.id_cred_x_map_x5t_hash.len = id_len;
67 break;
68 default:
69 break;
70 }
71
72 TRY_EXPECT(cbor_encode_id_cred_x_map(id_cred_x->ptr, id_cred_x->len,
73 &map, &payload_len_out),
74 0);
75
76 id_cred_x->len = (uint32_t)payload_len_out;
77
78 return ok;
79 }
80
plaintext2_split(struct byte_array * ptxt,struct byte_array * c_r,struct byte_array * id_cred_r,struct byte_array * sign_or_mac,struct byte_array * ead)81 static enum err plaintext2_split(struct byte_array *ptxt,
82 struct byte_array *c_r,
83 struct byte_array *id_cred_r,
84 struct byte_array *sign_or_mac,
85 struct byte_array *ead)
86 {
87 size_t decode_len = 0;
88 struct ptxt2 p;
89
90 TRY_EXPECT(cbor_decode_ptxt2(ptxt->ptr, ptxt->len, &p, &decode_len), 0);
91
92 /*decode C_R*/
93 if (p.ptxt2_C_R_choice == ptxt2_C_R_bstr_c) {
94 TRY(_memcpy_s(c_r->ptr, c_r->len, p.ptxt2_C_R_bstr.value,
95 (uint32_t)p.ptxt2_C_R_bstr.len));
96 c_r->len = (uint32_t)p.ptxt2_C_R_bstr.len;
97 } else {
98 /*provide C_R in encoded form if it was an int*/
99 /*this is how it C_R was chosen by the responder*/
100 TRY(encode_int(&p.ptxt2_C_R_int, 1, c_r));
101 }
102
103 /*ID_CRED_R*/
104 if (p.ptxt2_ID_CRED_R_choice == ptxt2_ID_CRED_R_map2_m_c) {
105 if (p.ptxt2_ID_CRED_R_map2_m.map2_x5chain_present) {
106 PRINT_MSG("ID_CRED_R is x5chain\n");
107 TRY(id_cred_x_encode(
108 x5chain, 0,
109 p.ptxt2_ID_CRED_R_map2_m.map2_x5chain
110 .map2_x5chain.value,
111 (uint32_t)p.ptxt2_ID_CRED_R_map2_m.map2_x5chain
112 .map2_x5chain.len,
113 id_cred_r));
114 }
115 if (p.ptxt2_ID_CRED_R_map2_m.map2_x5t_present) {
116 PRINT_MSG("ID_CRED_R is x5t\n");
117 TRY(id_cred_x_encode(x5t,
118 p.ptxt2_ID_CRED_R_map2_m.map2_x5t
119 .map2_x5t_alg_int,
120 p.ptxt2_ID_CRED_R_map2_m.map2_x5t
121 .map2_x5t_hash.value,
122 (uint32_t)p.ptxt2_ID_CRED_R_map2_m
123 .map2_x5t.map2_x5t_hash.len,
124 id_cred_r));
125 }
126 } else {
127 /*Note that if ID_CRED_x contains a single 'kid' parameter,
128 i.e., ID_CRED_R = { 4 : kid_x }, only the byte string kid_x
129 is conveyed in the plaintext encoded as a bstr or int*/
130 if (p.ptxt2_ID_CRED_R_choice == ptxt2_ID_CRED_R_map2_m_c) {
131 TRY(id_cred_x_encode(
132 kid, 0, p.ptxt2_ID_CRED_R_bstr.value,
133 (uint32_t)p.ptxt2_ID_CRED_R_bstr.len,
134 id_cred_r));
135
136 } else {
137 int _kid = p.ptxt2_ID_CRED_R_int;
138 TRY(id_cred_x_encode(kid, 0, &_kid, 1, id_cred_r));
139 }
140 }
141 TRY(_memcpy_s(sign_or_mac->ptr, sign_or_mac->len,
142 p.ptxt2_SGN_or_MAC_2.value,
143 (uint32_t)p.ptxt2_SGN_or_MAC_2.len));
144 sign_or_mac->len = (uint32_t)p.ptxt2_SGN_or_MAC_2.len;
145
146 if (p.ptxt2_EAD_2_present == true) {
147 TRY(_memcpy_s(ead->ptr, ead->len, p.ptxt2_EAD_2.value,
148 (uint32_t)p.ptxt2_EAD_2.len));
149 ead->len = (uint32_t)p.ptxt2_EAD_2.len;
150 } else {
151 if (ead->len) {
152 ead->len = 0;
153 }
154 }
155
156 return ok;
157 }
158
plaintext3_split(struct byte_array * ptxt,struct byte_array * id_cred_i,struct byte_array * sign_or_mac,struct byte_array * ead)159 static enum err plaintext3_split(struct byte_array *ptxt,
160 struct byte_array *id_cred_i,
161 struct byte_array *sign_or_mac,
162 struct byte_array *ead)
163 {
164 size_t decode_len = 0;
165 struct ptxt3 p;
166
167 TRY_EXPECT(cbor_decode_ptxt3(ptxt->ptr, ptxt->len, &p, &decode_len), 0);
168
169 /*ID_CRED_I*/
170 if (p.ptxt3_ID_CRED_I_choice == ptxt3_ID_CRED_I_map3_m_c) {
171 if (p.ptxt3_ID_CRED_I_map3_m.map3_x5chain_present) {
172 PRINT_MSG("ID_CRED_I is x5chain\n");
173 TRY(id_cred_x_encode(
174 x5chain, 0,
175 p.ptxt3_ID_CRED_I_map3_m.map3_x5chain
176 .map3_x5chain.value,
177 (uint32_t)p.ptxt3_ID_CRED_I_map3_m.map3_x5chain
178 .map3_x5chain.len,
179 id_cred_i));
180 }
181 if (p.ptxt3_ID_CRED_I_map3_m.map3_x5t_present) {
182 PRINT_MSG("ID_CRED_I is x5t\n");
183 TRY(id_cred_x_encode(x5t,
184 p.ptxt3_ID_CRED_I_map3_m.map3_x5t
185 .map3_x5t_alg_int,
186 p.ptxt3_ID_CRED_I_map3_m.map3_x5t
187 .map3_x5t_hash.value,
188 (uint32_t)p.ptxt3_ID_CRED_I_map3_m
189 .map3_x5t.map3_x5t_hash.len,
190 id_cred_i));
191 }
192 } else {
193 /*Note that if ID_CRED_x contains a single 'kid' parameter,
194 i.e., ID_CRED_I = { 4 : kid_x }, only the byte string kid_x
195 is conveyed in the plaintext encoded as a bstr or int*/
196 if (p.ptxt3_ID_CRED_I_choice == ptxt3_ID_CRED_I_map3_m_c) {
197 TRY(id_cred_x_encode(
198 kid, 0, p.ptxt3_ID_CRED_I_bstr.value,
199 (uint32_t)p.ptxt3_ID_CRED_I_bstr.len,
200 id_cred_i));
201
202 } else {
203 int _kid = p.ptxt3_ID_CRED_I_int;
204 TRY(id_cred_x_encode(kid, 0, &_kid, 1, id_cred_i));
205 }
206 }
207 TRY(_memcpy_s(sign_or_mac->ptr, sign_or_mac->len,
208 p.ptxt3_SGN_or_MAC_3.value,
209 (uint32_t)p.ptxt3_SGN_or_MAC_3.len));
210 sign_or_mac->len = (uint32_t)p.ptxt3_SGN_or_MAC_3.len;
211
212 if (p.ptxt3_EAD_3_present == true) {
213 TRY(_memcpy_s(ead->ptr, ead->len, p.ptxt3_EAD_3.value,
214 (uint32_t)p.ptxt3_EAD_3.len));
215 ead->len = (uint32_t)p.ptxt3_EAD_3.len;
216 } else {
217 if (ead->len) {
218 ead->len = 0;
219 }
220 }
221 return ok;
222 }
223
plaintext_split(struct byte_array * ptxt,struct byte_array * c_r,struct byte_array * id_cred_x,struct byte_array * sign_or_mac,struct byte_array * ead)224 enum err plaintext_split(struct byte_array *ptxt, struct byte_array *c_r,
225 struct byte_array *id_cred_x,
226 struct byte_array *sign_or_mac, struct byte_array *ead)
227 {
228 /*C_R is present only in plaintext 2*/
229 if (c_r != NULL) {
230 return plaintext2_split(ptxt, c_r, id_cred_x, sign_or_mac, ead);
231 } else {
232 return plaintext3_split(ptxt, id_cred_x, sign_or_mac, ead);
233 }
234 }
235