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