1 /*
2  * Copyright (c) 2020 Bose Corporation
3  * Copyright (c) 2021-2022 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * The static functions in this file operate on Big Endian (BE) as the
8  * underlying encryption library is BE as well. Furthermore, the sample data
9  * in the CSIS spec is also provided as BE, and logging values as BE will make
10  * it easier to compare.
11  */
12 #include "csip_crypto.h"
13 #include <zephyr/bluetooth/crypto.h>
14 #include <tinycrypt/constants.h>
15 #include <tinycrypt/utils.h>
16 #include <tinycrypt/aes.h>
17 #include <tinycrypt/cmac_mode.h>
18 #include <tinycrypt/ccm_mode.h>
19 #include <zephyr/sys/byteorder.h>
20 
21 #include "common/bt_str.h"
22 
23 #include <zephyr/logging/log.h>
24 
25 LOG_MODULE_REGISTER(bt_csip_crypto, CONFIG_BT_CSIP_SET_MEMBER_CRYPTO_LOG_LEVEL);
26 
27 #define BT_CSIP_CRYPTO_PADDING_SIZE 13
28 #define BT_CSIP_PADDED_RAND_SIZE    (BT_CSIP_CRYPTO_PADDING_SIZE + BT_CSIP_CRYPTO_PRAND_SIZE)
29 #define BT_CSIP_R_MASK              BIT_MASK(24) /* r is 24 bit / 3 octet */
30 
aes_cmac(const uint8_t key[BT_CSIP_CRYPTO_KEY_SIZE],const uint8_t * in,size_t in_len,uint8_t * out)31 static int aes_cmac(const uint8_t key[BT_CSIP_CRYPTO_KEY_SIZE],
32 		    const uint8_t *in, size_t in_len, uint8_t *out)
33 {
34 	struct tc_aes_key_sched_struct sched;
35 	struct tc_cmac_struct state;
36 
37 	/* TODO: Copy of the aes_cmac from smp.c: Can we merge them? */
38 
39 	if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
40 		return -EIO;
41 	}
42 
43 	if (tc_cmac_update(&state, in, in_len) == TC_CRYPTO_FAIL) {
44 		return -EIO;
45 	}
46 
47 	if (tc_cmac_final(out, &state) == TC_CRYPTO_FAIL) {
48 		return -EIO;
49 	}
50 
51 	return 0;
52 }
53 
xor_128(const uint8_t a[16],const uint8_t b[16],uint8_t out[16])54 static void xor_128(const uint8_t a[16], const uint8_t b[16], uint8_t out[16])
55 {
56 	size_t len = 16;
57 	/* TODO: Identical to the xor_128 from smp.c: Move to util */
58 
59 	while (len--) {
60 		*out++ = *a++ ^ *b++;
61 	}
62 }
63 
bt_csip_sih(const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE],uint8_t r[BT_CSIP_CRYPTO_PRAND_SIZE],uint8_t out[BT_CSIP_CRYPTO_HASH_SIZE])64 int bt_csip_sih(const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE], uint8_t r[BT_CSIP_CRYPTO_PRAND_SIZE],
65 		uint8_t out[BT_CSIP_CRYPTO_HASH_SIZE])
66 {
67 	uint8_t res[BT_CSIP_PADDED_RAND_SIZE]; /* need to store 128 bit */
68 	int err;
69 
70 	if ((r[BT_CSIP_CRYPTO_PRAND_SIZE - 1] & BIT(7)) ||
71 	   ((r[BT_CSIP_CRYPTO_PRAND_SIZE - 1] & BIT(6)) == 0)) {
72 		LOG_DBG("Invalid r %s", bt_hex(r, BT_CSIP_CRYPTO_PRAND_SIZE));
73 	}
74 
75 	LOG_DBG("SIRK %s", bt_hex(sirk, BT_CSIP_SET_SIRK_SIZE));
76 	LOG_DBG("r %s", bt_hex(r, BT_CSIP_CRYPTO_PRAND_SIZE));
77 
78 	/* r' = padding || r */
79 	(void)memset(res + BT_CSIP_CRYPTO_PRAND_SIZE, 0, BT_CSIP_CRYPTO_PADDING_SIZE);
80 	memcpy(res, r, BT_CSIP_CRYPTO_PRAND_SIZE);
81 
82 	LOG_DBG("r' %s", bt_hex(res, sizeof(res)));
83 
84 	err = bt_encrypt_le(sirk, res, res);
85 
86 	if (err != 0) {
87 		return err;
88 	}
89 
90 	/* The output of the function sih is:
91 	 *      sih(k, r) = e(k, r') mod 2^24
92 	 * The output of the security function e is then truncated to 24 bits
93 	 * by taking the least significant 24 bits of the output of e as the
94 	 * result of sih.
95 	 */
96 
97 	LOG_DBG("res %s", bt_hex(res, sizeof(res)));
98 
99 	/* Result is the lowest 3 bytes */
100 	memcpy(out, res, BT_CSIP_CRYPTO_HASH_SIZE);
101 
102 	LOG_DBG("sih %s", bt_hex(out, BT_CSIP_CRYPTO_HASH_SIZE));
103 
104 	return 0;
105 }
106 
107 /**
108  * @brief k1 derivation function
109  *
110  * The key derivation function k1 is used to derive a key. The derived key is
111  * used to encrypt and decrypt the value of the Set Identity Resolving Key
112  * characteristic.
113  *
114  * @param n      n is 0 or more bytes.
115  * @param n_size Number of bytes in @p n.
116  * @param salt   A 16-byte salt.
117  * @param p      p is 0 or more bytes.
118  * @param p_size Number of bytes in @p p.
119  * @param out    A 16-byte output buffer.
120  * @return int 0 on success, any other value indicates a failure.
121  */
k1(const uint8_t * n,size_t n_size,const uint8_t salt[BT_CSIP_CRYPTO_SALT_SIZE],const uint8_t * p,size_t p_size,uint8_t out[16])122 static int k1(const uint8_t *n, size_t n_size,
123 	      const uint8_t salt[BT_CSIP_CRYPTO_SALT_SIZE],
124 	      const uint8_t *p, size_t p_size, uint8_t out[16])
125 {
126 	/* TODO: This is basically a duplicate of bt_mesh_k1 - Perhaps they can
127 	 * be merged
128 	 */
129 	uint8_t t[16];
130 	int err;
131 
132 	/*
133 	 * T = AES_CMAC_SALT(N)
134 	 *
135 	 * k1(N, SALT, P) = AES-CMAC_T(P)
136 	 */
137 
138 	LOG_DBG("BE: n %s", bt_hex(n, n_size));
139 	LOG_DBG("BE: salt %s", bt_hex(salt, BT_CSIP_CRYPTO_SALT_SIZE));
140 	LOG_DBG("BE: p %s", bt_hex(p, p_size));
141 
142 	err = aes_cmac(salt, n, n_size, t);
143 
144 	LOG_DBG("BE: t %s", bt_hex(t, sizeof(t)));
145 
146 	if (err) {
147 		return err;
148 	}
149 
150 	err = aes_cmac(t, p, p_size, out);
151 
152 	LOG_DBG("BE: out %s", bt_hex(out, 16));
153 
154 	return err;
155 }
156 
157 /**
158  * @brief s1 SALT generation function
159  *
160  * @param m      A non-zero length octet array or ASCII encoded string
161  * @param m_size Size of @p m.
162  * @param out    16-byte output buffer.
163  * @return int 0 on success, any other value indicates a failure.
164  */
s1(const uint8_t * m,size_t m_size,uint8_t out[BT_CSIP_CRYPTO_SALT_SIZE])165 static int s1(const uint8_t *m, size_t m_size,
166 	      uint8_t out[BT_CSIP_CRYPTO_SALT_SIZE])
167 {
168 	uint8_t zero[16];
169 	int err;
170 
171 	/*
172 	 * s1(M) = AES-CMAC_zero(M)
173 	 */
174 
175 	LOG_DBG("BE: m %s", bt_hex(m, m_size));
176 
177 	memset(zero, 0, sizeof(zero));
178 
179 	err = aes_cmac(zero, m, m_size, out);
180 
181 	LOG_DBG("BE: out %s", bt_hex(out, 16));
182 
183 	return err;
184 }
185 
bt_csip_sef(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE],const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE],uint8_t out_sirk[BT_CSIP_SET_SIRK_SIZE])186 int bt_csip_sef(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE],
187 		const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE],
188 		uint8_t out_sirk[BT_CSIP_SET_SIRK_SIZE])
189 {
190 	const uint8_t m[] = {'S', 'I', 'R', 'K', 'e', 'n', 'c'};
191 	const uint8_t p[] = {'c', 's', 'i', 's'};
192 	uint8_t s1_out[BT_CSIP_CRYPTO_SALT_SIZE];
193 	uint8_t k1_out[BT_CSIP_CRYPTO_KEY_SIZE];
194 	uint8_t k1_tmp[BT_CSIP_CRYPTO_KEY_SIZE];
195 	int err;
196 
197 	/*
198 	 * sef(K, SIRK) = k1(K, s1("SIRKenc"), "csis") ^ SIRK
199 	 */
200 
201 	LOG_DBG("SIRK %s", bt_hex(sirk, BT_CSIP_SET_SIRK_SIZE));
202 
203 	if (IS_ENABLED(CONFIG_LITTLE_ENDIAN)) {
204 		/* Swap because aes_cmac is big endian
205 		 * and we are little endian
206 		 */
207 		sys_memcpy_swap(k1_tmp, k, sizeof(k1_tmp));
208 	} else {
209 		(void)memcpy(k1_tmp, k, sizeof(k1_tmp));
210 	}
211 	LOG_DBG("BE: k %s", bt_hex(k1_tmp, sizeof(k1_tmp)));
212 
213 	err = s1(m, sizeof(m), s1_out);
214 	if (err) {
215 		return err;
216 	}
217 
218 	LOG_DBG("BE: s1 result %s", bt_hex(s1_out, sizeof(s1_out)));
219 
220 	err = k1(k1_tmp, sizeof(k1_tmp), s1_out, p, sizeof(p), k1_out);
221 	if (err) {
222 		return err;
223 	}
224 
225 	LOG_DBG("BE: k1 result %s", bt_hex(k1_out, sizeof(k1_out)));
226 
227 	if (IS_ENABLED(CONFIG_LITTLE_ENDIAN)) {
228 		/* Swap result back to little endian */
229 		sys_mem_swap(k1_out, sizeof(k1_out));
230 	}
231 
232 	xor_128(k1_out, sirk, out_sirk);
233 	LOG_DBG("out %s", bt_hex(out_sirk, BT_CSIP_SET_SIRK_SIZE));
234 
235 	return 0;
236 }
237 
bt_csip_sdf(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE],const uint8_t enc_sirk[BT_CSIP_SET_SIRK_SIZE],uint8_t out_sirk[BT_CSIP_SET_SIRK_SIZE])238 int bt_csip_sdf(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE],
239 		const uint8_t enc_sirk[BT_CSIP_SET_SIRK_SIZE],
240 		uint8_t out_sirk[BT_CSIP_SET_SIRK_SIZE])
241 {
242 	/* SIRK encryption is currently symmetric, which means that we can
243 	 * simply apply the sef function to decrypt it.
244 	 */
245 
246 	/*
247 	 * sdf(K, EncSIRK) = k1(K, s1("SIRKenc"), "csis") ^ EncSIRK
248 	 */
249 
250 	LOG_DBG("Running SDF as SEF");
251 	return bt_csip_sef(k, enc_sirk, out_sirk);
252 }
253