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