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