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