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