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 = compute_ecdh_secret(tfm, pub_b, priv_a, dhkey_a); 156 if (ret) 157 goto out; 158 159 ret = compute_ecdh_secret(tfm, pub_a, priv_b, dhkey_b); 160 if (ret) 161 goto out; 162 163 if (memcmp(dhkey_a, dhkey, 32)) { 164 ret = -EINVAL; 165 goto out; 166 } 167 168 if (memcmp(dhkey_b, dhkey, 32)) 169 ret = -EINVAL; 170 171 out: 172 kfree(tmp); 173 return ret; 174 } 175 176 static char test_ecdh_buffer[32]; 177 178 static ssize_t test_ecdh_read(struct file *file, char __user *user_buf, 179 size_t count, loff_t *ppos) 180 { 181 return simple_read_from_buffer(user_buf, count, ppos, test_ecdh_buffer, 182 strlen(test_ecdh_buffer)); 183 } 184 185 static const struct file_operations test_ecdh_fops = { 186 .open = simple_open, 187 .read = test_ecdh_read, 188 .llseek = default_llseek, 189 }; 190 191 static int __init test_ecdh(void) 192 { 193 struct crypto_kpp *tfm; 194 ktime_t calltime, delta, rettime; 195 unsigned long long duration; 196 int err; 197 198 calltime = ktime_get(); 199 200 tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0); 201 if (IS_ERR(tfm)) { 202 BT_ERR("Unable to create ECDH crypto context"); 203 err = PTR_ERR(tfm); 204 goto done; 205 } 206 207 err = test_ecdh_sample(tfm, priv_a_1, priv_b_1, pub_a_1, pub_b_1, 208 dhkey_1); 209 if (err) { 210 BT_ERR("ECDH sample 1 failed"); 211 goto done; 212 } 213 214 err = test_ecdh_sample(tfm, priv_a_2, priv_b_2, pub_a_2, pub_b_2, 215 dhkey_2); 216 if (err) { 217 BT_ERR("ECDH sample 2 failed"); 218 goto done; 219 } 220 221 err = test_ecdh_sample(tfm, priv_a_3, priv_a_3, pub_a_3, pub_a_3, 222 dhkey_3); 223 if (err) { 224 BT_ERR("ECDH sample 3 failed"); 225 goto done; 226 } 227 228 crypto_free_kpp(tfm); 229 230 rettime = ktime_get(); 231 delta = ktime_sub(rettime, calltime); 232 duration = (unsigned long long) ktime_to_ns(delta) >> 10; 233 234 BT_INFO("ECDH test passed in %llu usecs", duration); 235 236 done: 237 if (!err) 238 snprintf(test_ecdh_buffer, sizeof(test_ecdh_buffer), 239 "PASS (%llu usecs)\n", duration); 240 else 241 snprintf(test_ecdh_buffer, sizeof(test_ecdh_buffer), "FAIL\n"); 242 243 debugfs_create_file("selftest_ecdh", 0444, bt_debugfs, NULL, 244 &test_ecdh_fops); 245 246 return err; 247 } 248 249 #else 250 251 static inline int test_ecdh(void) 252 { 253 return 0; 254 } 255 256 #endif 257 258 static int __init run_selftest(void) 259 { 260 int err; 261 262 BT_INFO("Starting self testing"); 263 264 err = test_ecdh(); 265 if (err) 266 goto done; 267 268 err = bt_selftest_smp(); 269 270 done: 271 BT_INFO("Finished self testing"); 272 273 return err; 274 } 275 276 #if IS_MODULE(CONFIG_BT) 277 278 /* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=m and is just a 279 * wrapper to allow running this at module init. 280 * 281 * If CONFIG_BT_SELFTEST=n, then this code is not compiled at all. 282 */ 283 int __init bt_selftest(void) 284 { 285 return run_selftest(); 286 } 287 288 #else 289 290 /* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=y and is run 291 * via late_initcall() as last item in the initialization sequence. 292 * 293 * If CONFIG_BT_SELFTEST=n, then this code is not compiled at all. 294 */ 295 static int __init bt_selftest_init(void) 296 { 297 return run_selftest(); 298 } 299 late_initcall(bt_selftest_init); 300 301 #endif 302