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