1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  * Copyright (c) 2017 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <errno.h>
9 #include <stdint.h>
10 #include <string.h>
11 
12 #include <zephyr/autoconf.h>
13 #include <zephyr/bluetooth/crypto.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/logging/log.h>
16 #include <zephyr/sys/byteorder.h>
17 
18 #include "common/bt_str.h"
19 
20 #define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL
21 LOG_MODULE_REGISTER(bt_aes_ccm);
22 
xor16(uint8_t * dst,const uint8_t * a,const uint8_t * b)23 static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
24 {
25 	dst[0] = a[0] ^ b[0];
26 	dst[1] = a[1] ^ b[1];
27 	dst[2] = a[2] ^ b[2];
28 	dst[3] = a[3] ^ b[3];
29 	dst[4] = a[4] ^ b[4];
30 	dst[5] = a[5] ^ b[5];
31 	dst[6] = a[6] ^ b[6];
32 	dst[7] = a[7] ^ b[7];
33 	dst[8] = a[8] ^ b[8];
34 	dst[9] = a[9] ^ b[9];
35 	dst[10] = a[10] ^ b[10];
36 	dst[11] = a[11] ^ b[11];
37 	dst[12] = a[12] ^ b[12];
38 	dst[13] = a[13] ^ b[13];
39 	dst[14] = a[14] ^ b[14];
40 	dst[15] = a[15] ^ b[15];
41 }
42 
43 /* b field is assumed to have the nonce already present in bytes 1-13 */
ccm_calculate_X0(const uint8_t key[16],const uint8_t * aad,uint8_t aad_len,size_t mic_size,uint16_t msg_len,uint8_t b[16],uint8_t X0[16])44 static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
45 			    size_t mic_size, uint16_t msg_len, uint8_t b[16],
46 			    uint8_t X0[16])
47 {
48 	int i, j, err;
49 
50 	/* X_0 = e(AppKey, flags || nonce || length) */
51 	b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;
52 
53 	sys_put_be16(msg_len, b + 14);
54 
55 	err = bt_encrypt_be(key, b, X0);
56 	if (err) {
57 		return err;
58 	}
59 
60 	/* If AAD is being used to authenticate, include it here */
61 	if (aad_len) {
62 		sys_put_be16(aad_len, b);
63 
64 		for (i = 0; i < sizeof(uint16_t); i++) {
65 			b[i] = X0[i] ^ b[i];
66 		}
67 
68 		j = 0;
69 		aad_len += sizeof(uint16_t);
70 		while (aad_len > 16) {
71 			do {
72 				b[i] = X0[i] ^ aad[j];
73 				i++, j++;
74 			} while (i < 16);
75 
76 			aad_len -= 16;
77 			i = 0;
78 
79 			err = bt_encrypt_be(key, b, X0);
80 			if (err) {
81 				return err;
82 			}
83 		}
84 
85 		for (; i < aad_len; i++, j++) {
86 			b[i] = X0[i] ^ aad[j];
87 		}
88 
89 		for (i = aad_len; i < 16; i++) {
90 			b[i] = X0[i];
91 		}
92 
93 		err = bt_encrypt_be(key, b, X0);
94 		if (err) {
95 			return err;
96 		}
97 	}
98 
99 	return 0;
100 }
101 
ccm_auth(const uint8_t key[16],uint8_t nonce[13],const uint8_t * cleartext_msg,uint16_t msg_len,const uint8_t * aad,size_t aad_len,uint8_t * mic,size_t mic_size)102 static int ccm_auth(const uint8_t key[16], uint8_t nonce[13],
103 		    const uint8_t *cleartext_msg, uint16_t msg_len, const uint8_t *aad,
104 		    size_t aad_len, uint8_t *mic, size_t mic_size)
105 {
106 	uint8_t b[16], Xn[16], s0[16];
107 	uint16_t blk_cnt, last_blk;
108 	int err, j, i;
109 
110 	last_blk = msg_len % 16;
111 	blk_cnt = (msg_len + 15) / 16;
112 	if (!last_blk) {
113 		last_blk = 16U;
114 	}
115 
116 	b[0] = 0x01;
117 	memcpy(b + 1, nonce, 13);
118 
119 	/* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
120 	sys_put_be16(0x0000, &b[14]);
121 
122 	err = bt_encrypt_be(key, b, s0);
123 	if (err) {
124 		return err;
125 	}
126 
127 	ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);
128 
129 	for (j = 0; j < blk_cnt; j++) {
130 		/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
131 		if (j + 1 == blk_cnt) {
132 			for (i = 0; i < last_blk; i++) {
133 				b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
134 			}
135 
136 			memcpy(&b[i], &Xn[i], 16 - i);
137 		} else {
138 			xor16(b, Xn, &cleartext_msg[j * 16]);
139 		}
140 
141 		err = bt_encrypt_be(key, b, Xn);
142 		if (err) {
143 			return err;
144 		}
145 	}
146 
147 	/* MIC = C_mic ^ X_1 */
148 	for (i = 0; i < mic_size; i++) {
149 		mic[i] = s0[i] ^ Xn[i];
150 	}
151 
152 	return 0;
153 }
154 
ccm_crypt(const uint8_t key[16],const uint8_t nonce[13],const uint8_t * in_msg,uint8_t * out_msg,uint16_t msg_len)155 static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
156 		     const uint8_t *in_msg, uint8_t *out_msg, uint16_t msg_len)
157 {
158 	uint8_t a_i[16], s_i[16];
159 	uint16_t last_blk, blk_cnt;
160 	size_t i, j;
161 	int err;
162 
163 	last_blk = msg_len % 16;
164 	blk_cnt = (msg_len + 15) / 16;
165 	if (!last_blk) {
166 		last_blk = 16U;
167 	}
168 
169 	a_i[0] = 0x01;
170 	memcpy(&a_i[1], nonce, 13);
171 
172 	for (j = 0; j < blk_cnt; j++) {
173 		/* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
174 		sys_put_be16(j + 1, &a_i[14]);
175 
176 		err = bt_encrypt_be(key, a_i, s_i);
177 		if (err) {
178 			return err;
179 		}
180 
181 		/* Encrypted = Payload[0-15] ^ C_1 */
182 		if (j < blk_cnt - 1) {
183 			xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
184 		} else {
185 			for (i = 0; i < last_blk; i++) {
186 				out_msg[(j * 16) + i] =
187 					in_msg[(j * 16) + i] ^ s_i[i];
188 			}
189 		}
190 	}
191 	return 0;
192 }
193 
bt_ccm_decrypt(const uint8_t key[16],uint8_t nonce[13],const uint8_t * enc_data,size_t len,const uint8_t * aad,size_t aad_len,uint8_t * plaintext,size_t mic_size)194 int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13],
195 		   const uint8_t *enc_data, size_t len, const uint8_t *aad,
196 		   size_t aad_len, uint8_t *plaintext, size_t mic_size)
197 {
198 	uint8_t mic[16];
199 
200 	if (aad_len >= 0xff00 || mic_size > sizeof(mic) || len > UINT16_MAX) {
201 		return -EINVAL;
202 	}
203 
204 	ccm_crypt(key, nonce, enc_data, plaintext, len);
205 
206 	ccm_auth(key, nonce, plaintext, len, aad, aad_len, mic, mic_size);
207 
208 	if (memcmp(mic, enc_data + len, mic_size)) {
209 		return -EBADMSG;
210 	}
211 
212 	return 0;
213 }
214 
bt_ccm_encrypt(const uint8_t key[16],uint8_t nonce[13],const uint8_t * plaintext,size_t len,const uint8_t * aad,size_t aad_len,uint8_t * enc_data,size_t mic_size)215 int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13],
216 		   const uint8_t *plaintext, size_t len, const uint8_t *aad,
217 		   size_t aad_len, uint8_t *enc_data, size_t mic_size)
218 {
219 	uint8_t *mic = enc_data + len;
220 
221 	LOG_DBG("key %s", bt_hex(key, 16));
222 	LOG_DBG("nonce %s", bt_hex(nonce, 13));
223 	LOG_DBG("msg (len %zu) %s", len, bt_hex(plaintext, len));
224 	LOG_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
225 
226 	/* Unsupported AAD size */
227 	if (aad_len >= 0xff00 || mic_size > 16 || len > UINT16_MAX) {
228 		return -EINVAL;
229 	}
230 
231 	ccm_auth(key, nonce, plaintext, len, aad, aad_len, mic, mic_size);
232 
233 	ccm_crypt(key, nonce, plaintext, enc_data, len);
234 
235 	return 0;
236 }
237