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 "edhoc.h"
13
14 #include "edhoc/okm.h"
15 #include "edhoc/ciphertext.h"
16 #include "edhoc/signature_or_mac_msg.h"
17 #include "edhoc/plaintext.h"
18 #include "edhoc/associated_data_encode.h"
19 #include "edhoc/suites.h"
20
21 #include "common/crypto_wrapper.h"
22 #include "common/oscore_edhoc_error.h"
23 #include "common/memcpy_s.h"
24
25 /**
26 * @brief Xors two arrays
27 *
28 * @param in1 an input array
29 * @param in2 an input array
30 * @param len the lenhgt of the arrays
31 * @param out the result
32 */
xor_arrays(const uint8_t * in1,const uint8_t * in2,uint32_t len,uint8_t * out)33 static inline void xor_arrays(const uint8_t *in1, const uint8_t *in2,
34 uint32_t len, uint8_t *out)
35 {
36 for (uint32_t i = 0; i < len; i++) {
37 out[i] = in1[i] ^ in2[i];
38 }
39 }
40
41 /**
42 * @brief Encrypts a plaintext or decrypts a cyphertext
43 *
44 * @param ctxt CIPHERTEXT2, CIPHERTEXT3 or CIPHERTEXT4
45 * @param op ENCRYPT or DECRYPT
46 * @param in ciphertext or plaintext
47 * @param in_len lenhgt of in
48 * @param key the key used of encrption/decryption
49 * @param key_len lenhgt of key
50 * @param nonce AEAD nonce
51 * @param nonce_len lenhgt of nonce
52 * @param aad additional authenticated data for AEAD
53 * @param aad_len lenhgt of aad
54 * @param out the result
55 * @param out_len lenhgt of out
56 * @param tag AEAD authentication tag
57 * @param tag_len lenhgt of tag
58 * @return enum err
59 */
ciphertext_encrypt_decrypt(enum ciphertext ctxt,enum aes_operation op,const uint8_t * in,const uint32_t in_len,const uint8_t * key,const uint32_t key_len,uint8_t * nonce,const uint32_t nonce_len,const uint8_t * aad,const uint32_t aad_len,uint8_t * out,const uint32_t out_len,uint8_t * tag,const uint32_t tag_len)60 static enum err ciphertext_encrypt_decrypt(
61 enum ciphertext ctxt, enum aes_operation op, const uint8_t *in,
62 const uint32_t in_len, const uint8_t *key, const uint32_t key_len,
63 uint8_t *nonce, const uint32_t nonce_len, const uint8_t *aad,
64 const uint32_t aad_len, uint8_t *out, const uint32_t out_len,
65 uint8_t *tag, const uint32_t tag_len)
66 {
67 if (ctxt == CIPHERTEXT2) {
68 xor_arrays(in, key, key_len, out);
69 } else {
70 PRINT_ARRAY("in", in, in_len);
71 TRY(aead(op, in, in_len, key, key_len, nonce, nonce_len, aad,
72 aad_len, out, out_len, tag, tag_len));
73 }
74 return ok;
75 }
76
77 /**
78 * @brief Computes the keystream for ciphertext 2 and the key and IV for
79 * ciphertexts 3 and 4.
80 *
81 * @param ctxt CIPHERTEXT2, CIPHERTEXT3 or CIPHERTEXT4
82 * @param edhoc_hash the hash algorithm used in the current edhoc run
83 * @param prk pseudoramdom key
84 * @param prk_len lenhgt of prk
85 * @param th thraskript hash
86 * @param th_len lenhgt of th
87 * @param key the generated key
88 * @param key_len lenhgt of key
89 * @param iv the generated iv
90 * @param iv_len lenhgt of iv
91 * @return enum err
92 */
key_gen(enum ciphertext ctxt,enum hash_alg edhoc_hash,uint8_t * prk,uint32_t prk_len,uint8_t * th,uint32_t th_len,uint8_t * key,uint32_t key_len,uint8_t * iv,uint32_t iv_len)93 static enum err key_gen(enum ciphertext ctxt, enum hash_alg edhoc_hash,
94 uint8_t *prk, uint32_t prk_len, uint8_t *th,
95 uint32_t th_len, uint8_t *key, uint32_t key_len,
96 uint8_t *iv, uint32_t iv_len)
97 {
98 switch (ctxt) {
99 case CIPHERTEXT2:
100 TRY(okm_calc(edhoc_hash, prk, prk_len, th, th_len,
101 "KEYSTREAM_2", NULL, 0, key, key_len));
102 PRINT_ARRAY("KEYSTREAM_2", key, key_len);
103 break;
104
105 case CIPHERTEXT3:
106 TRY(okm_calc(edhoc_hash, prk, prk_len, th, th_len, "K_3", NULL,
107 0, key, key_len));
108 PRINT_ARRAY("K_3", key, key_len);
109 TRY(okm_calc(edhoc_hash, prk, prk_len, th, th_len, "IV_3", NULL,
110 0, iv, iv_len));
111 PRINT_ARRAY("IV_3", iv, iv_len);
112 break;
113
114 case CIPHERTEXT4:
115 TRY(edhoc_exporter(edhoc_hash, prk, prk_len, th, th_len,
116 "EDHOC_K_4", key, key_len));
117 PRINT_ARRAY("K_4", key, key_len);
118 TRY(edhoc_exporter(edhoc_hash, prk, prk_len, th, th_len,
119 "EDHOC_IV_4", iv, iv_len));
120 PRINT_ARRAY("IV_4", iv, iv_len);
121 break;
122 }
123 return ok;
124 }
125
ciphertext_decrypt_split(enum ciphertext ctxt,struct suite * suite,uint8_t * id_cred,uint32_t * id_cred_len,uint8_t * signature_or_mac,uint32_t * signature_or_mac_len,uint8_t * ead,uint32_t * ead_len,uint8_t * prk,uint32_t prk_len,uint8_t * th,uint32_t th_len,uint8_t * ciphertext,uint32_t ciphertext_len)126 enum err ciphertext_decrypt_split(enum ciphertext ctxt, struct suite *suite,
127 uint8_t *id_cred, uint32_t *id_cred_len,
128 uint8_t *signature_or_mac,
129 uint32_t *signature_or_mac_len, uint8_t *ead,
130 uint32_t *ead_len, uint8_t *prk,
131 uint32_t prk_len, uint8_t *th,
132 uint32_t th_len, uint8_t *ciphertext,
133 uint32_t ciphertext_len)
134 {
135 /*generate key and iv (no iv in for ciphertext 2)*/
136 uint32_t key_len;
137 uint8_t key[CIPHERTEXT2_DEFAULT_SIZE];
138 if (ctxt == CIPHERTEXT2) {
139 key_len = ciphertext_len;
140 } else {
141 key_len = get_aead_key_len(suite->edhoc_aead);
142 }
143 TRY(check_buffer_size(CIPHERTEXT2_DEFAULT_SIZE, key_len));
144
145 uint32_t iv_len = get_aead_iv_len(suite->edhoc_aead);
146 TRY(check_buffer_size(AEAD_IV_DEFAULT_SIZE, iv_len));
147 uint8_t iv[AEAD_IV_DEFAULT_SIZE];
148
149 TRY(key_gen(ctxt, suite->edhoc_hash, prk, prk_len, th, th_len, key,
150 key_len, iv, iv_len));
151
152 /*Associated data*/
153 uint8_t associated_data[ASSOCIATED_DATA_DEFAULT_SIZE];
154 uint32_t associated_data_len = sizeof(associated_data);
155 TRY(associated_data_encode(th, th_len, (uint8_t *)&associated_data,
156 &associated_data_len));
157
158 PRINT_ARRAY("associated_data", associated_data, associated_data_len);
159
160 uint32_t tag_len = get_aead_mac_len(suite->edhoc_aead);
161 uint32_t plaintext_len = ciphertext_len;
162 if (ctxt != CIPHERTEXT2) {
163 plaintext_len -= tag_len;
164 }
165 TRY(check_buffer_size(PLAINTEXT_DEFAULT_SIZE, plaintext_len));
166 uint8_t plaintext[PLAINTEXT_DEFAULT_SIZE];
167 TRY(ciphertext_encrypt_decrypt(
168 ctxt, DECRYPT, ciphertext, ciphertext_len, key, key_len, iv,
169 iv_len, associated_data, associated_data_len, plaintext,
170 plaintext_len, ciphertext - tag_len, tag_len));
171
172 PRINT_ARRAY("plaintext", plaintext, plaintext_len);
173
174 if (ctxt == CIPHERTEXT4 && plaintext_len != 0) {
175 TRY(decode_byte_string(plaintext, plaintext_len, ead, ead_len));
176 PRINT_ARRAY("EAD_4", ead, *ead_len);
177 } else if (ctxt == CIPHERTEXT4 && plaintext_len == 0) {
178 ead = NULL;
179 *ead_len = 0;
180 PRINT_MSG("No EAD_4\n");
181 } else {
182 TRY(plaintext_split(plaintext, plaintext_len, id_cred,
183 id_cred_len, signature_or_mac,
184 signature_or_mac_len, ead, ead_len));
185 PRINT_ARRAY("ID_CRED", id_cred, *id_cred_len);
186 PRINT_ARRAY("sign_or_mac", signature_or_mac,
187 *signature_or_mac_len);
188 if (*ead_len) {
189 PRINT_ARRAY("ead", ead, *ead_len);
190 }
191 }
192
193 return ok;
194 }
195
ciphertext_gen(enum ciphertext ctxt,struct suite * suite,uint8_t * id_cred,uint32_t id_cred_len,uint8_t * signature_or_mac,uint32_t signature_or_mac_len,uint8_t * ead,uint32_t ead_len,uint8_t * prk,uint32_t prk_len,uint8_t * th,uint32_t th_len,uint8_t * ciphertext,uint32_t * ciphertext_len)196 enum err ciphertext_gen(enum ciphertext ctxt, struct suite *suite,
197 uint8_t *id_cred, uint32_t id_cred_len,
198 uint8_t *signature_or_mac,
199 uint32_t signature_or_mac_len, uint8_t *ead,
200 uint32_t ead_len, uint8_t *prk, uint32_t prk_len,
201 uint8_t *th, uint32_t th_len, uint8_t *ciphertext,
202 uint32_t *ciphertext_len)
203 {
204 /*Encode plaintext*/
205 uint8_t plaintext[PLAINTEXT_DEFAULT_SIZE];
206 uint32_t plaintext_len = sizeof(plaintext);
207
208 TRY(check_buffer_size(SGN_OR_MAC_DEFAULT_SIZE,
209 signature_or_mac_len + 2));
210 uint8_t signature_or_mac_enc[SGN_OR_MAC_DEFAULT_SIZE];
211 uint32_t signature_or_mac_enc_len = signature_or_mac_len + 2;
212 TRY(encode_byte_string(signature_or_mac, signature_or_mac_len,
213 signature_or_mac_enc,
214 &signature_or_mac_enc_len));
215
216 if (ctxt != CIPHERTEXT4) {
217 uint8_t kid_buf[KID_DEFAULT_SIZE];
218 uint32_t kid_len = sizeof(kid_buf);
219 TRY(id_cred2kid(id_cred, id_cred_len, kid_buf, &kid_len));
220
221 PRINT_ARRAY("kid", kid_buf, kid_len);
222
223 if (kid_len != 0) {
224 /*id_cred_x is a KID*/
225 TRY(_memcpy_s(plaintext, plaintext_len, kid_buf,
226 kid_len));
227
228 TRY(_memcpy_s(plaintext + kid_len,
229 plaintext_len - kid_len,
230 signature_or_mac_enc,
231 signature_or_mac_enc_len));
232
233 plaintext_len = signature_or_mac_enc_len + kid_len;
234 } else {
235 /*id_cred_x is NOT a KID*/
236 TRY(_memcpy_s(plaintext, plaintext_len, id_cred,
237 id_cred_len));
238
239 TRY(_memcpy_s(plaintext + id_cred_len,
240 plaintext_len - id_cred_len,
241 signature_or_mac_enc,
242 signature_or_mac_enc_len));
243
244 plaintext_len = id_cred_len + signature_or_mac_enc_len;
245 }
246 } else {
247 plaintext_len = 0;
248 }
249 if (ead_len > 0) {
250 TRY(_memcpy_s(plaintext + plaintext_len,
251 (uint32_t)sizeof(plaintext) - plaintext_len, ead,
252 ead_len));
253
254 plaintext_len += ead_len;
255 }
256
257 PRINT_ARRAY("plaintext", plaintext, plaintext_len);
258
259 /*generate key and iv (no iv in for ciphertext 2)*/
260 uint32_t key_len;
261 uint8_t key[CIPHERTEXT2_DEFAULT_SIZE];
262 if (ctxt == CIPHERTEXT2) {
263 key_len = plaintext_len;
264 } else {
265 key_len = get_aead_key_len(suite->edhoc_aead);
266 }
267 TRY(check_buffer_size(CIPHERTEXT2_DEFAULT_SIZE, key_len));
268
269 uint32_t iv_len = get_aead_iv_len(suite->edhoc_aead);
270 TRY(check_buffer_size(AEAD_IV_DEFAULT_SIZE, iv_len));
271 uint8_t iv[AEAD_IV_DEFAULT_SIZE];
272
273 TRY(key_gen(ctxt, suite->edhoc_hash, prk, prk_len, th, th_len, key,
274 key_len, iv, iv_len));
275
276 /*encrypt*/
277 uint8_t aad[ASSOCIATED_DATA_DEFAULT_SIZE];
278 uint32_t aad_len = sizeof(aad);
279 uint32_t tag_len = get_aead_mac_len(suite->edhoc_aead);
280 TRY(check_buffer_size(MAC_DEFAULT_SIZE, tag_len));
281 uint8_t tag[MAC_DEFAULT_SIZE];
282 if (ctxt != CIPHERTEXT2) {
283 /*Associated data*/
284 TRY(associated_data_encode(th, th_len, aad, &aad_len));
285 PRINT_ARRAY("aad_data", aad, aad_len);
286 } else {
287 tag_len = 0;
288 }
289
290 *ciphertext_len = plaintext_len;
291
292 TRY(ciphertext_encrypt_decrypt(ctxt, ENCRYPT, plaintext, plaintext_len,
293 key, key_len, iv, iv_len, aad, aad_len,
294 ciphertext, *ciphertext_len, tag,
295 tag_len));
296 *ciphertext_len += tag_len;
297
298 PRINT_ARRAY("ciphertext_2/3/4", ciphertext, *ciphertext_len);
299 return ok;
300 }
301