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