xref: /linux/net/bluetooth/selftest.c (revision 3b165c2a29cfb6453f26e1ac833ca6afd28d28cf)
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 	.open		= simple_open,
192 	.read		= test_ecdh_read,
193 	.llseek		= default_llseek,
194 };
195 
196 static int __init test_ecdh(void)
197 {
198 	struct crypto_kpp *tfm;
199 	ktime_t calltime, delta, rettime;
200 	unsigned long long duration = 0;
201 	int err;
202 
203 	calltime = ktime_get();
204 
205 	tfm = crypto_alloc_kpp("ecdh-nist-p256", 0, 0);
206 	if (IS_ERR(tfm)) {
207 		BT_ERR("Unable to create ECDH crypto context");
208 		err = PTR_ERR(tfm);
209 		goto done;
210 	}
211 
212 	err = test_ecdh_sample(tfm, priv_a_1, priv_b_1, pub_a_1, pub_b_1,
213 			       dhkey_1);
214 	if (err) {
215 		BT_ERR("ECDH sample 1 failed");
216 		goto done;
217 	}
218 
219 	err = test_ecdh_sample(tfm, priv_a_2, priv_b_2, pub_a_2, pub_b_2,
220 			       dhkey_2);
221 	if (err) {
222 		BT_ERR("ECDH sample 2 failed");
223 		goto done;
224 	}
225 
226 	err = test_ecdh_sample(tfm, priv_a_3, priv_a_3, pub_a_3, pub_a_3,
227 			       dhkey_3);
228 	if (err) {
229 		BT_ERR("ECDH sample 3 failed");
230 		goto done;
231 	}
232 
233 	crypto_free_kpp(tfm);
234 
235 	rettime = ktime_get();
236 	delta = ktime_sub(rettime, calltime);
237 	duration = (unsigned long long) ktime_to_ns(delta) >> 10;
238 
239 	BT_INFO("ECDH test passed in %llu usecs", duration);
240 
241 done:
242 	if (!err)
243 		snprintf(test_ecdh_buffer, sizeof(test_ecdh_buffer),
244 			 "PASS (%llu usecs)\n", duration);
245 	else
246 		snprintf(test_ecdh_buffer, sizeof(test_ecdh_buffer), "FAIL\n");
247 
248 	debugfs_create_file("selftest_ecdh", 0444, bt_debugfs, NULL,
249 			    &test_ecdh_fops);
250 
251 	return err;
252 }
253 
254 #else
255 
256 static inline int test_ecdh(void)
257 {
258 	return 0;
259 }
260 
261 #endif
262 
263 static int __init run_selftest(void)
264 {
265 	int err;
266 
267 	BT_INFO("Starting self testing");
268 
269 	err = test_ecdh();
270 	if (err)
271 		goto done;
272 
273 	err = bt_selftest_smp();
274 
275 done:
276 	BT_INFO("Finished self testing");
277 
278 	return err;
279 }
280 
281 #if IS_MODULE(CONFIG_BT)
282 
283 /* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=m and is just a
284  * wrapper to allow running this at module init.
285  *
286  * If CONFIG_BT_SELFTEST=n, then this code is not compiled at all.
287  */
288 int __init bt_selftest(void)
289 {
290 	return run_selftest();
291 }
292 
293 #else
294 
295 /* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=y and is run
296  * via late_initcall() as last item in the initialization sequence.
297  *
298  * If CONFIG_BT_SELFTEST=n, then this code is not compiled at all.
299  */
300 static int __init bt_selftest_init(void)
301 {
302 	return run_selftest();
303 }
304 late_initcall(bt_selftest_init);
305 
306 #endif
307