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 <stddef.h>
13 #include <stdint.h>
14 #include <string.h>
15 
16 #include <zephyr/autoconf.h>
17 #include <zephyr/bluetooth/audio/csip.h>
18 #include <zephyr/bluetooth/crypto.h>
19 #include <zephyr/logging/log.h>
20 #include <zephyr/sys/byteorder.h>
21 #include <zephyr/sys/util.h>
22 #include <zephyr/sys/util_macro.h>
23 
24 #include "crypto/bt_crypto.h"
25 
26 #include "common/bt_str.h"
27 
28 #include "csip_crypto.h"
29 
30 LOG_MODULE_REGISTER(bt_csip_crypto, CONFIG_BT_CSIP_SET_MEMBER_CRYPTO_LOG_LEVEL);
31 
32 #define BT_CSIP_CRYPTO_PADDING_SIZE 13
33 #define BT_CSIP_PADDED_RAND_SIZE    (BT_CSIP_CRYPTO_PADDING_SIZE + BT_CSIP_CRYPTO_PRAND_SIZE)
34 #define BT_CSIP_R_MASK              BIT_MASK(24) /* r is 24 bit / 3 octet */
35 
bt_csip_sih(const uint8_t sirk[BT_CSIP_SIRK_SIZE],uint8_t r[BT_CSIP_CRYPTO_PRAND_SIZE],uint8_t out[BT_CSIP_CRYPTO_HASH_SIZE])36 int bt_csip_sih(const uint8_t sirk[BT_CSIP_SIRK_SIZE], uint8_t r[BT_CSIP_CRYPTO_PRAND_SIZE],
37 		uint8_t out[BT_CSIP_CRYPTO_HASH_SIZE])
38 {
39 	uint8_t res[BT_CSIP_PADDED_RAND_SIZE]; /* need to store 128 bit */
40 	int err;
41 
42 	if ((r[BT_CSIP_CRYPTO_PRAND_SIZE - 1] & BIT(7)) ||
43 	   ((r[BT_CSIP_CRYPTO_PRAND_SIZE - 1] & BIT(6)) == 0)) {
44 		LOG_DBG("Invalid r %s", bt_hex(r, BT_CSIP_CRYPTO_PRAND_SIZE));
45 	}
46 
47 	LOG_DBG("SIRK %s", bt_hex(sirk, BT_CSIP_SIRK_SIZE));
48 	LOG_DBG("r %s", bt_hex(r, BT_CSIP_CRYPTO_PRAND_SIZE));
49 
50 	/* r' = padding || r */
51 	(void)memset(res + BT_CSIP_CRYPTO_PRAND_SIZE, 0, BT_CSIP_CRYPTO_PADDING_SIZE);
52 	memcpy(res, r, BT_CSIP_CRYPTO_PRAND_SIZE);
53 
54 	LOG_DBG("r' %s", bt_hex(res, sizeof(res)));
55 
56 	err = bt_encrypt_le(sirk, res, res);
57 
58 	if (err != 0) {
59 		return err;
60 	}
61 
62 	/* The output of the function sih is:
63 	 *      sih(k, r) = e(k, r') mod 2^24
64 	 * The output of the security function e is then truncated to 24 bits
65 	 * by taking the least significant 24 bits of the output of e as the
66 	 * result of sih.
67 	 */
68 
69 	LOG_DBG("res %s", bt_hex(res, sizeof(res)));
70 
71 	/* Result is the lowest 3 bytes */
72 	memcpy(out, res, BT_CSIP_CRYPTO_HASH_SIZE);
73 
74 	LOG_DBG("sih %s", bt_hex(out, BT_CSIP_CRYPTO_HASH_SIZE));
75 
76 	return 0;
77 }
78 
79 /**
80  * @brief k1 derivation function
81  *
82  * The key derivation function k1 is used to derive a key. The derived key is
83  * used to encrypt and decrypt the value of the Set Identity Resolving Key
84  * characteristic.
85  *
86  * @param n      n is 0 or more bytes.
87  * @param n_size Number of bytes in @p n.
88  * @param salt   A 16-byte salt.
89  * @param p      p is 0 or more bytes.
90  * @param p_size Number of bytes in @p p.
91  * @param out    A 16-byte output buffer.
92  * @return int 0 on success, any other value indicates a failure.
93  */
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])94 static int k1(const uint8_t *n, size_t n_size,
95 	      const uint8_t salt[BT_CSIP_CRYPTO_SALT_SIZE],
96 	      const uint8_t *p, size_t p_size, uint8_t out[16])
97 {
98 	/* TODO: This is basically a duplicate of bt_mesh_k1 - Perhaps they can
99 	 * be merged
100 	 */
101 	uint8_t t[16];
102 	int err;
103 
104 	/*
105 	 * T = AES_CMAC_SALT(N)
106 	 *
107 	 * k1(N, SALT, P) = AES-CMAC_T(P)
108 	 */
109 
110 	LOG_DBG("BE: n %s", bt_hex(n, n_size));
111 	LOG_DBG("BE: salt %s", bt_hex(salt, BT_CSIP_CRYPTO_SALT_SIZE));
112 	LOG_DBG("BE: p %s", bt_hex(p, p_size));
113 
114 	err = bt_crypto_aes_cmac(salt, n, n_size, t);
115 
116 	LOG_DBG("BE: t %s", bt_hex(t, sizeof(t)));
117 
118 	if (err) {
119 		return err;
120 	}
121 
122 	err = bt_crypto_aes_cmac(t, p, p_size, out);
123 
124 	LOG_DBG("BE: out %s", bt_hex(out, 16));
125 
126 	return err;
127 }
128 
129 /**
130  * @brief s1 SALT generation function
131  *
132  * @param m      A non-zero length octet array or ASCII encoded string
133  * @param m_size Size of @p m.
134  * @param out    16-byte output buffer.
135  * @return int 0 on success, any other value indicates a failure.
136  */
s1(const uint8_t * m,size_t m_size,uint8_t out[BT_CSIP_CRYPTO_SALT_SIZE])137 static int s1(const uint8_t *m, size_t m_size,
138 	      uint8_t out[BT_CSIP_CRYPTO_SALT_SIZE])
139 {
140 	uint8_t zero[16];
141 	int err;
142 
143 	/*
144 	 * s1(M) = AES-CMAC_zero(M)
145 	 */
146 
147 	LOG_DBG("BE: m %s", bt_hex(m, m_size));
148 
149 	memset(zero, 0, sizeof(zero));
150 
151 	err = bt_crypto_aes_cmac(zero, m, m_size, out);
152 
153 	LOG_DBG("BE: out %s", bt_hex(out, 16));
154 
155 	return err;
156 }
157 
bt_csip_sef(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE],const uint8_t sirk[BT_CSIP_SIRK_SIZE],uint8_t out_sirk[BT_CSIP_SIRK_SIZE])158 int bt_csip_sef(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE], const uint8_t sirk[BT_CSIP_SIRK_SIZE],
159 		uint8_t out_sirk[BT_CSIP_SIRK_SIZE])
160 {
161 	const uint8_t m[] = {'S', 'I', 'R', 'K', 'e', 'n', 'c'};
162 	const uint8_t p[] = {'c', 's', 'i', 's'};
163 	uint8_t s1_out[BT_CSIP_CRYPTO_SALT_SIZE];
164 	uint8_t k1_out[BT_CSIP_CRYPTO_KEY_SIZE];
165 	uint8_t k1_tmp[BT_CSIP_CRYPTO_KEY_SIZE];
166 	int err;
167 
168 	/*
169 	 * sef(K, SIRK) = k1(K, s1("SIRKenc"), "csis") ^ SIRK
170 	 */
171 
172 	LOG_DBG("SIRK %s", bt_hex(sirk, BT_CSIP_SIRK_SIZE));
173 
174 	if (IS_ENABLED(CONFIG_LITTLE_ENDIAN)) {
175 		/* Swap because aes_cmac is big endian
176 		 * and we are little endian
177 		 */
178 		sys_memcpy_swap(k1_tmp, k, sizeof(k1_tmp));
179 	} else {
180 		(void)memcpy(k1_tmp, k, sizeof(k1_tmp));
181 	}
182 	LOG_DBG("BE: k %s", bt_hex(k1_tmp, sizeof(k1_tmp)));
183 
184 	err = s1(m, sizeof(m), s1_out);
185 	if (err) {
186 		return err;
187 	}
188 
189 	LOG_DBG("BE: s1 result %s", bt_hex(s1_out, sizeof(s1_out)));
190 
191 	err = k1(k1_tmp, sizeof(k1_tmp), s1_out, p, sizeof(p), k1_out);
192 	if (err) {
193 		return err;
194 	}
195 
196 	LOG_DBG("BE: k1 result %s", bt_hex(k1_out, sizeof(k1_out)));
197 
198 	if (IS_ENABLED(CONFIG_LITTLE_ENDIAN)) {
199 		/* Swap result back to little endian */
200 		sys_mem_swap(k1_out, sizeof(k1_out));
201 	}
202 
203 	mem_xor_128(out_sirk, k1_out, sirk);
204 	LOG_DBG("out %s", bt_hex(out_sirk, BT_CSIP_SIRK_SIZE));
205 
206 	return 0;
207 }
208 
bt_csip_sdf(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE],const uint8_t enc_sirk[BT_CSIP_SIRK_SIZE],uint8_t out_sirk[BT_CSIP_SIRK_SIZE])209 int bt_csip_sdf(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE], const uint8_t enc_sirk[BT_CSIP_SIRK_SIZE],
210 		uint8_t out_sirk[BT_CSIP_SIRK_SIZE])
211 {
212 	/* SIRK encryption is currently symmetric, which means that we can
213 	 * simply apply the sef function to decrypt it.
214 	 */
215 
216 	/*
217 	 * sdf(K, EncSIRK) = k1(K, s1("SIRKenc"), "csis") ^ EncSIRK
218 	 */
219 
220 	LOG_DBG("Running SDF as SEF");
221 	return bt_csip_sef(k, enc_sirk, out_sirk);
222 }
223