Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/bluetooth/selftest.c
26285 views
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
35
static 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
};
41
static 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
};
47
static 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
};
58
static 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
};
69
static 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
76
static 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
};
82
static 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
};
88
static 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
};
99
static 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
};
110
static 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
117
static 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
};
123
static 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
};
134
static 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
141
static 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*/
179
out:
180
kfree(tmp);
181
return ret;
182
}
183
184
static char test_ecdh_buffer[32];
185
186
static 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
193
static const struct file_operations test_ecdh_fops = {
194
.open = simple_open,
195
.read = test_ecdh_read,
196
.llseek = default_llseek,
197
};
198
199
static 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
244
done:
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
259
static inline int test_ecdh(void)
260
{
261
return 0;
262
}
263
264
#endif
265
266
static 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
278
done:
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
*/
291
int __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
*/
303
static int __init bt_selftest_init(void)
304
{
305
return run_selftest();
306
}
307
late_initcall(bt_selftest_init);
308
309
#endif
310
311