xref: /linux/net/bluetooth/selftest.c (revision 72ebc685bca99f466ef35600b5263d1c21c790d9)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3    BlueZ - Bluetooth protocol stack for Linux
4 
5    Copyright (C) 2014 Intel Corporation
6 
7    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
10    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
11    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
12    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 
16    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
17    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
18    SOFTWARE IS DISCLAIMED.
19 */
20 
21 #include <linux/debugfs.h>
22 
23 #include <net/bluetooth/bluetooth.h>
24 #include <net/bluetooth/hci_core.h>
25 
26 #include "ecdh_helper.h"
27 #include "smp.h"
28 #include "selftest.h"
29 
30 #if IS_ENABLED(CONFIG_BT_SELFTEST_ECDH)
31 
32 static const u8 priv_a_1[32] __initconst = {
33 	0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58,
34 	0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a,
35 	0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74,
36 	0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f,
37 };
38 static const u8 priv_b_1[32] __initconst = {
39 	0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b,
40 	0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59,
41 	0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90,
42 	0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55,
43 };
44 static const u8 pub_a_1[64] __initconst = {
45 	0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
46 	0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
47 	0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
48 	0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
49 
50 	0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
51 	0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
52 	0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
53 	0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc,
54 };
55 static const u8 pub_b_1[64] __initconst = {
56 	0x90, 0xa1, 0xaa, 0x2f, 0xb2, 0x77, 0x90, 0x55,
57 	0x9f, 0xa6, 0x15, 0x86, 0xfd, 0x8a, 0xb5, 0x47,
58 	0x00, 0x4c, 0x9e, 0xf1, 0x84, 0x22, 0x59, 0x09,
59 	0x96, 0x1d, 0xaf, 0x1f, 0xf0, 0xf0, 0xa1, 0x1e,
60 
61 	0x4a, 0x21, 0xb1, 0x15, 0xf9, 0xaf, 0x89, 0x5f,
62 	0x76, 0x36, 0x8e, 0xe2, 0x30, 0x11, 0x2d, 0x47,
63 	0x60, 0x51, 0xb8, 0x9a, 0x3a, 0x70, 0x56, 0x73,
64 	0x37, 0xad, 0x9d, 0x42, 0x3e, 0xf3, 0x55, 0x4c,
65 };
66 static const u8 dhkey_1[32] __initconst = {
67 	0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86,
68 	0xf1, 0x66, 0xf8, 0xb4, 0x13, 0x6b, 0x79, 0x99,
69 	0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
70 	0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec,
71 };
72 
73 static const u8 priv_a_2[32] __initconst = {
74 	0x63, 0x76, 0x45, 0xd0, 0xf7, 0x73, 0xac, 0xb7,
75 	0xff, 0xdd, 0x03, 0x72, 0xb9, 0x72, 0x85, 0xb4,
76 	0x41, 0xb6, 0x5d, 0x0c, 0x5d, 0x54, 0x84, 0x60,
77 	0x1a, 0xa3, 0x9a, 0x3c, 0x69, 0x16, 0xa5, 0x06,
78 };
79 static const u8 priv_b_2[32] __initconst = {
80 	0xba, 0x30, 0x55, 0x50, 0x19, 0xa2, 0xca, 0xa3,
81 	0xa5, 0x29, 0x08, 0xc6, 0xb5, 0x03, 0x88, 0x7e,
82 	0x03, 0x2b, 0x50, 0x73, 0xd4, 0x2e, 0x50, 0x97,
83 	0x64, 0xcd, 0x72, 0x0d, 0x67, 0xa0, 0x9a, 0x52,
84 };
85 static const u8 pub_a_2[64] __initconst = {
86 	0xdd, 0x78, 0x5c, 0x74, 0x03, 0x9b, 0x7e, 0x98,
87 	0xcb, 0x94, 0x87, 0x4a, 0xad, 0xfa, 0xf8, 0xd5,
88 	0x43, 0x3e, 0x5c, 0xaf, 0xea, 0xb5, 0x4c, 0xf4,
89 	0x9e, 0x80, 0x79, 0x57, 0x7b, 0xa4, 0x31, 0x2c,
90 
91 	0x4f, 0x5d, 0x71, 0x43, 0x77, 0x43, 0xf8, 0xea,
92 	0xd4, 0x3e, 0xbd, 0x17, 0x91, 0x10, 0x21, 0xd0,
93 	0x1f, 0x87, 0x43, 0x8e, 0x40, 0xe2, 0x52, 0xcd,
94 	0xbe, 0xdf, 0x98, 0x38, 0x18, 0x12, 0x95, 0x91,
95 };
96 static const u8 pub_b_2[64] __initconst = {
97 	0xcc, 0x00, 0x65, 0xe1, 0xf5, 0x6c, 0x0d, 0xcf,
98 	0xec, 0x96, 0x47, 0x20, 0x66, 0xc9, 0xdb, 0x84,
99 	0x81, 0x75, 0xa8, 0x4d, 0xc0, 0xdf, 0xc7, 0x9d,
100 	0x1b, 0x3f, 0x3d, 0xf2, 0x3f, 0xe4, 0x65, 0xf4,
101 
102 	0x79, 0xb2, 0xec, 0xd8, 0xca, 0x55, 0xa1, 0xa8,
103 	0x43, 0x4d, 0x6b, 0xca, 0x10, 0xb0, 0xc2, 0x01,
104 	0xc2, 0x33, 0x4e, 0x16, 0x24, 0xc4, 0xef, 0xee,
105 	0x99, 0xd8, 0xbb, 0xbc, 0x48, 0xd0, 0x01, 0x02,
106 };
107 static const u8 dhkey_2[32] __initconst = {
108 	0x69, 0xeb, 0x21, 0x32, 0xf2, 0xc6, 0x05, 0x41,
109 	0x60, 0x19, 0xcd, 0x5e, 0x94, 0xe1, 0xe6, 0x5f,
110 	0x33, 0x07, 0xe3, 0x38, 0x4b, 0x68, 0xe5, 0x62,
111 	0x3f, 0x88, 0x6d, 0x2f, 0x3a, 0x84, 0x85, 0xab,
112 };
113 
114 static const u8 priv_a_3[32] __initconst = {
115 	0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58,
116 	0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a,
117 	0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74,
118 	0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f,
119 };
120 static const u8 pub_a_3[64] __initconst = {
121 	0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
122 	0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
123 	0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
124 	0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
125 
126 	0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
127 	0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
128 	0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
129 	0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc,
130 };
131 static const u8 dhkey_3[32] __initconst = {
132 	0x2d, 0xab, 0x00, 0x48, 0xcb, 0xb3, 0x7b, 0xda,
133 	0x55, 0x7b, 0x8b, 0x72, 0xa8, 0x57, 0x87, 0xc3,
134 	0x87, 0x27, 0x99, 0x32, 0xfc, 0x79, 0x5f, 0xae,
135 	0x7c, 0x1c, 0xf9, 0x49, 0xe6, 0xd7, 0xaa, 0x70,
136 };
137 
138 static int __init test_ecdh_sample(struct crypto_kpp *tfm, const u8 priv_a[32],
139 				   const u8 priv_b[32], const u8 pub_a[64],
140 				   const u8 pub_b[64], const u8 dhkey[32])
141 {
142 	u8 *tmp, *dhkey_a, *dhkey_b;
143 	int ret;
144 
145 	tmp = kmalloc(64, GFP_KERNEL);
146 	if (!tmp)
147 		return -EINVAL;
148 
149 	dhkey_a = &tmp[0];
150 	dhkey_b = &tmp[32];
151 
152 	ret = set_ecdh_privkey(tfm, priv_a);
153 	if (ret)
154 		goto out;
155 
156 	ret = compute_ecdh_secret(tfm, pub_b, dhkey_a);
157 	if (ret)
158 		goto out;
159 
160 	if (memcmp(dhkey_a, dhkey, 32)) {
161 		ret = -EINVAL;
162 		goto out;
163 	}
164 
165 	ret = set_ecdh_privkey(tfm, priv_b);
166 	if (ret)
167 		goto out;
168 
169 	ret = compute_ecdh_secret(tfm, pub_a, dhkey_b);
170 	if (ret)
171 		goto out;
172 
173 	if (memcmp(dhkey_b, dhkey, 32))
174 		ret = -EINVAL;
175 	/* fall through*/
176 out:
177 	kfree(tmp);
178 	return ret;
179 }
180 
181 static char test_ecdh_buffer[32];
182 
183 static ssize_t test_ecdh_read(struct file *file, char __user *user_buf,
184 			      size_t count, loff_t *ppos)
185 {
186 	return simple_read_from_buffer(user_buf, count, ppos, test_ecdh_buffer,
187 				       strlen(test_ecdh_buffer));
188 }
189 
190 static const struct file_operations test_ecdh_fops = {
191 	.owner		= THIS_MODULE,
192 	.open		= simple_open,
193 	.read		= test_ecdh_read,
194 	.llseek		= default_llseek,
195 };
196 
197 static int __init test_ecdh(void)
198 {
199 	struct crypto_kpp *tfm;
200 	ktime_t calltime, delta, rettime;
201 	unsigned long long duration = 0;
202 	int err;
203 
204 	calltime = ktime_get();
205 
206 	tfm = crypto_alloc_kpp("ecdh-nist-p256", 0, 0);
207 	if (IS_ERR(tfm)) {
208 		BT_ERR("Unable to create ECDH crypto context");
209 		err = PTR_ERR(tfm);
210 		goto done;
211 	}
212 
213 	err = test_ecdh_sample(tfm, priv_a_1, priv_b_1, pub_a_1, pub_b_1,
214 			       dhkey_1);
215 	if (err) {
216 		BT_ERR("ECDH sample 1 failed");
217 		goto done;
218 	}
219 
220 	err = test_ecdh_sample(tfm, priv_a_2, priv_b_2, pub_a_2, pub_b_2,
221 			       dhkey_2);
222 	if (err) {
223 		BT_ERR("ECDH sample 2 failed");
224 		goto done;
225 	}
226 
227 	err = test_ecdh_sample(tfm, priv_a_3, priv_a_3, pub_a_3, pub_a_3,
228 			       dhkey_3);
229 	if (err) {
230 		BT_ERR("ECDH sample 3 failed");
231 		goto done;
232 	}
233 
234 	crypto_free_kpp(tfm);
235 
236 	rettime = ktime_get();
237 	delta = ktime_sub(rettime, calltime);
238 	duration = (unsigned long long) ktime_to_ns(delta) >> 10;
239 
240 	BT_INFO("ECDH test passed in %llu usecs", duration);
241 
242 done:
243 	if (!err)
244 		snprintf(test_ecdh_buffer, sizeof(test_ecdh_buffer),
245 			 "PASS (%llu usecs)\n", duration);
246 	else
247 		snprintf(test_ecdh_buffer, sizeof(test_ecdh_buffer), "FAIL\n");
248 
249 	debugfs_create_file("selftest_ecdh", 0444, bt_debugfs, NULL,
250 			    &test_ecdh_fops);
251 
252 	return err;
253 }
254 
255 #else
256 
257 static inline int test_ecdh(void)
258 {
259 	return 0;
260 }
261 
262 #endif
263 
264 static int __init run_selftest(void)
265 {
266 	int err;
267 
268 	BT_INFO("Starting self testing");
269 
270 	err = test_ecdh();
271 	if (err)
272 		goto done;
273 
274 	err = bt_selftest_smp();
275 
276 done:
277 	BT_INFO("Finished self testing");
278 
279 	return err;
280 }
281 
282 #if IS_MODULE(CONFIG_BT)
283 
284 /* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=m and is just a
285  * wrapper to allow running this at module init.
286  *
287  * If CONFIG_BT_SELFTEST=n, then this code is not compiled at all.
288  */
289 int __init bt_selftest(void)
290 {
291 	return run_selftest();
292 }
293 
294 #else
295 
296 /* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=y and is run
297  * via late_initcall() as last item in the initialization sequence.
298  *
299  * If CONFIG_BT_SELFTEST=n, then this code is not compiled at all.
300  */
301 static int __init bt_selftest_init(void)
302 {
303 	return run_selftest();
304 }
305 late_initcall(bt_selftest_init);
306 
307 #endif
308