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/buffer_sizes.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 #include "edhoc/int_encode_decode.h"
22 
23 #include "common/crypto_wrapper.h"
24 #include "common/oscore_edhoc_error.h"
25 #include "common/memcpy_s.h"
26 
27 /**
28  * @brief 			Xors two arrays.
29  *
30  * @param[in] in1		An input array.
31  * @param[in] in2 		An input array.
32  * @param[out] out 		The result of the xor operation.
33  * @retval			Ok or error code.
34  */
xor_arrays(const struct byte_array * in1,const struct byte_array * in2,struct byte_array * out)35 static inline enum err xor_arrays(const struct byte_array *in1,
36 				  const struct byte_array *in2,
37 				  struct byte_array *out)
38 {
39 	if (in1->len != in2->len) {
40 		return xor_error;
41 	}
42 	for (uint32_t i = 0; i < in1->len; i++) {
43 		out->ptr[i] = in1->ptr[i] ^ in2->ptr[i];
44 	}
45 	return ok;
46 }
47 
48 /**
49  * @brief 			Encrypts a plaintext or decrypts a ciphertext.
50  *
51  * @param ctxt 			CIPHERTEXT2, CIPHERTEXT3 or CIPHERTEXT4.
52  * @param op 			ENCRYPT or DECRYPT.
53  * @param[in] in 		Ciphertext or plaintext.
54  * @param[in] key 		The key used of encryption/decryption.
55  * @param[in] nonce 		AEAD nonce.
56  * @param[in] aad 		Additional authenticated data for AEAD.
57  * @param[out] out 		The result.
58  * @param[out] tag 		AEAD authentication tag.
59  * @return 			Ok or error code.
60  */
ciphertext_encrypt_decrypt(enum ciphertext ctxt,enum aes_operation op,const struct byte_array * in,const struct byte_array * key,struct byte_array * nonce,const struct byte_array * aad,struct byte_array * out,struct byte_array * tag)61 static enum err ciphertext_encrypt_decrypt(
62 	enum ciphertext ctxt, enum aes_operation op,
63 	const struct byte_array *in, const struct byte_array *key,
64 	struct byte_array *nonce, const struct byte_array *aad,
65 	struct byte_array *out, struct byte_array *tag)
66 {
67 	if (ctxt == CIPHERTEXT2) {
68 		xor_arrays(in, key, out);
69 	} else {
70 		PRINT_ARRAY("in", in->ptr, in->len);
71 		TRY(aead(op, in, key, nonce, aad, out, tag));
72 	}
73 	return ok;
74 }
75 
76 /**
77  * @brief 			Computes the key stream for ciphertext 2 and
78  * 				the key and IV for ciphertext 3 and 4.
79  *
80  * @param ctxt 			CIPHERTEXT2, CIPHERTEXT3 or CIPHERTEXT4.
81  * @param edhoc_hash 		The EDHOC hash algorithm.
82  * @param prk 			Pseudorandom key.
83  * @param th 			Transcript hash.
84  * @param[out] key 		The generated key/key stream.
85  * @param[out] iv 		The generated iv.
86  * @return 			Ok or error code.
87  */
key_gen(enum ciphertext ctxt,enum hash_alg edhoc_hash,struct byte_array * prk,struct byte_array * th,struct byte_array * key,struct byte_array * iv)88 static enum err key_gen(enum ciphertext ctxt, enum hash_alg edhoc_hash,
89 			struct byte_array *prk, struct byte_array *th,
90 			struct byte_array *key, struct byte_array *iv)
91 {
92 	switch (ctxt) {
93 	case CIPHERTEXT2:
94 		TRY(edhoc_kdf(edhoc_hash, prk, KEYSTREAM_2, th, key));
95 		PRINT_ARRAY("KEYSTREAM_2", key->ptr, key->len);
96 		break;
97 
98 	case CIPHERTEXT3:
99 		TRY(edhoc_kdf(edhoc_hash, prk, K_3, th, key));
100 
101 		PRINT_ARRAY("K_3", key->ptr, key->len);
102 
103 		TRY(edhoc_kdf(edhoc_hash, prk, IV_3, th, iv));
104 		PRINT_ARRAY("IV_3", iv->ptr, iv->len);
105 		break;
106 
107 	case CIPHERTEXT4:
108 		PRINT_ARRAY("PRK_4e3m", prk->ptr, prk->len);
109 		PRINT_ARRAY("TH_4", th->ptr, th->len);
110 		TRY(edhoc_kdf(edhoc_hash, prk, K_4, th, key));
111 		PRINT_ARRAY("K_4", key->ptr, key->len);
112 		TRY(edhoc_kdf(edhoc_hash, prk, IV_4, th, iv));
113 		PRINT_ARRAY("IV_4", iv->ptr, iv->len);
114 		break;
115 	}
116 	return ok;
117 }
118 
ciphertext_decrypt_split(enum ciphertext ctxt,struct suite * suite,struct byte_array * c_r,struct byte_array * id_cred,struct byte_array * sig_or_mac,struct byte_array * ead,struct byte_array * prk,struct byte_array * th,struct byte_array * ciphertext,struct byte_array * plaintext)119 enum err ciphertext_decrypt_split(
120 	enum ciphertext ctxt, struct suite *suite, struct byte_array *c_r,
121 	struct byte_array *id_cred, struct byte_array *sig_or_mac,
122 	struct byte_array *ead, struct byte_array *prk, struct byte_array *th,
123 	struct byte_array *ciphertext, struct byte_array *plaintext)
124 {
125 	/*generate key and iv (no iv in for ciphertext 2)*/
126 	uint32_t key_len;
127 	if (ctxt == CIPHERTEXT2) {
128 		key_len = ciphertext->len;
129 	} else {
130 		key_len = get_aead_key_len(suite->edhoc_aead);
131 	}
132 
133 	BYTE_ARRAY_NEW(key, CIPHERTEXT2_SIZE, key_len);
134 	BYTE_ARRAY_NEW(iv, AEAD_IV_SIZE, get_aead_iv_len(suite->edhoc_aead));
135 
136 	TRY(key_gen(ctxt, suite->edhoc_hash, prk, th, &key, &iv));
137 
138 	/*Associated data*/
139 	BYTE_ARRAY_NEW(associated_data, AAD_SIZE, AAD_SIZE);
140 	TRY(associated_data_encode(th, &associated_data));
141 
142 	PRINT_ARRAY("associated_data", associated_data.ptr,
143 		    associated_data.len);
144 
145 	uint32_t tag_len = get_aead_mac_len(suite->edhoc_aead);
146 	if (ctxt != CIPHERTEXT2) {
147 		if (plaintext->len < tag_len) {
148 			return error_message_received;
149 		}
150 		plaintext->len -= tag_len;
151 	}
152 	struct byte_array tag = BYTE_ARRAY_INIT(ciphertext->ptr, tag_len);
153 	TRY(ciphertext_encrypt_decrypt(ctxt, DECRYPT, ciphertext, &key, &iv,
154 				       &associated_data, plaintext, &tag));
155 
156 	PRINT_ARRAY("plaintext", plaintext->ptr, plaintext->len);
157 
158 	if (ctxt == CIPHERTEXT4 && plaintext->len != 0) {
159 		TRY(decode_bstr(plaintext, ead));
160 		PRINT_ARRAY("EAD_4", ead->ptr, ead->len);
161 	} else if (ctxt == CIPHERTEXT4 && plaintext->len == 0) {
162 		ead->ptr = NULL;
163 		ead->len = 0;
164 		PRINT_MSG("No EAD_4\n");
165 	} else {
166 		if (ctxt == CIPHERTEXT2) {
167 			TRY(plaintext_split(plaintext, c_r, id_cred, sig_or_mac,
168 					    ead));
169 			PRINT_ARRAY("C_R (raw)", c_r->ptr, c_r->len);
170 		} else {
171 			TRY(plaintext_split(plaintext, NULL, id_cred,
172 					    sig_or_mac, ead));
173 		}
174 		PRINT_ARRAY("ID_CRED", id_cred->ptr, id_cred->len);
175 		PRINT_ARRAY("sign_or_mac", sig_or_mac->ptr, sig_or_mac->len);
176 		if (ead->len) {
177 			PRINT_ARRAY("ead", ead->ptr, ead->len);
178 		}
179 	}
180 
181 	return ok;
182 }
183 
ciphertext_gen(enum ciphertext ctxt,struct suite * suite,const struct byte_array * c_r,const struct byte_array * id_cred,struct byte_array * signature_or_mac,const struct byte_array * ead,struct byte_array * prk,struct byte_array * th,struct byte_array * ciphertext,struct byte_array * plaintext)184 enum err ciphertext_gen(enum ciphertext ctxt, struct suite *suite,
185 			const struct byte_array *c_r,
186 			const struct byte_array *id_cred,
187 			struct byte_array *signature_or_mac,
188 			const struct byte_array *ead, struct byte_array *prk,
189 			struct byte_array *th, struct byte_array *ciphertext,
190 			struct byte_array *plaintext)
191 {
192 	BYTE_ARRAY_NEW(signature_or_mac_enc, AS_BSTR_SIZE(SIG_OR_MAC_SIZE),
193 		       AS_BSTR_SIZE(signature_or_mac->len));
194 
195 	TRY(encode_bstr(signature_or_mac, &signature_or_mac_enc));
196 
197 	uint32_t ptxt_buf_capacity = plaintext->len;
198 	plaintext->len = 0;
199 	if (ctxt == CIPHERTEXT2) {
200 		if (c_x_is_encoded_int(c_r)) {
201 			TRY(byte_array_append(plaintext, c_r,
202 					      ptxt_buf_capacity));
203 		} else {
204 			BYTE_ARRAY_NEW(c_r_enc, AS_BSTR_SIZE(C_I_SIZE),
205 				       AS_BSTR_SIZE(c_r->len));
206 			TRY(encode_bstr(c_r, &c_r_enc));
207 			TRY(byte_array_append(plaintext, &c_r_enc,
208 					      ptxt_buf_capacity));
209 		}
210 	}
211 
212 	if (ctxt != CIPHERTEXT4) {
213 		BYTE_ARRAY_NEW(kid, KID_SIZE, KID_SIZE);
214 		TRY(id_cred2kid(id_cred, &kid));
215 
216 		PRINT_ARRAY("kid", kid.ptr, kid.len);
217 
218 		if (kid.len != 0) {
219 			/*id_cred_x is a KID*/
220 			TRY(byte_array_append(plaintext, &kid,
221 					      ptxt_buf_capacity));
222 		} else {
223 			/*id_cred_x is NOT a KID*/
224 			TRY(byte_array_append(plaintext, id_cred,
225 					      ptxt_buf_capacity));
226 		}
227 		TRY(byte_array_append(plaintext, &signature_or_mac_enc,
228 				      ptxt_buf_capacity));
229 	} else {
230 		plaintext->len = 0;
231 	}
232 	if (ead->len > 0) {
233 		TRY(byte_array_append(plaintext, ead, ptxt_buf_capacity));
234 	}
235 
236 	PRINT_ARRAY("plaintext", plaintext->ptr, plaintext->len);
237 
238 	/*generate key and iv (no iv in for ciphertext 2)*/
239 	uint32_t key_len;
240 	if (ctxt == CIPHERTEXT2) {
241 		key_len = plaintext->len;
242 	} else {
243 		key_len = get_aead_key_len(suite->edhoc_aead);
244 	}
245 
246 	BYTE_ARRAY_NEW(key, CIPHERTEXT2_SIZE, key_len);
247 	BYTE_ARRAY_NEW(iv, AEAD_IV_SIZE, get_aead_iv_len(suite->edhoc_aead));
248 
249 	TRY(key_gen(ctxt, suite->edhoc_hash, prk, th, &key, &iv));
250 
251 	/*encrypt*/
252 	BYTE_ARRAY_NEW(aad, AAD_SIZE, AAD_SIZE);
253 	BYTE_ARRAY_NEW(tag, MAC_SIZE, get_aead_mac_len(suite->edhoc_aead));
254 
255 	if (ctxt != CIPHERTEXT2) {
256 		/*Associated data*/
257 		TRY(associated_data_encode(th, &aad));
258 		PRINT_ARRAY("aad_data", aad.ptr, aad.len);
259 	} else {
260 		tag.len = 0;
261 	}
262 
263 	ciphertext->len = plaintext->len;
264 
265 	TRY(ciphertext_encrypt_decrypt(ctxt, ENCRYPT, plaintext, &key, &iv,
266 				       &aad, ciphertext, &tag));
267 	ciphertext->len += tag.len;
268 
269 	PRINT_ARRAY("ciphertext_2/3/4", ciphertext->ptr, ciphertext->len);
270 	return ok;
271 }
272