projects/linux·blob master · refs

306 lines · 8.4 KiB

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
32static 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};
38static 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};
44static 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};
55static 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};
66static 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
73static 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};
79static 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};
85static 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};
96static 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};
107static 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
114static 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};
120static 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};
131static 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
138static 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*/
176out:
177 kfree(tmp);
178 return ret;
179}
180
181static char test_ecdh_buffer[32];
182
183static 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
190static const struct file_operations test_ecdh_fops = {
191 .open = simple_open,
192 .read = test_ecdh_read,
193 .llseek = default_llseek,
194};
195
196static 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
241done:
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
256static inline int test_ecdh(void)
257{
258 return 0;
259}
260
261#endif
262
263static 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
275done:
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 */
288int __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 */
300static int __init bt_selftest_init(void)
301{
302 return run_selftest();
303}
304late_initcall(bt_selftest_init);
305
306#endif