1ee485290SMarcel Holtmann /* 2ee485290SMarcel Holtmann BlueZ - Bluetooth protocol stack for Linux 3ee485290SMarcel Holtmann 4ee485290SMarcel Holtmann Copyright (C) 2014 Intel Corporation 5ee485290SMarcel Holtmann 6ee485290SMarcel Holtmann This program is free software; you can redistribute it and/or modify 7ee485290SMarcel Holtmann it under the terms of the GNU General Public License version 2 as 8ee485290SMarcel Holtmann published by the Free Software Foundation; 9ee485290SMarcel Holtmann 10ee485290SMarcel Holtmann THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 11ee485290SMarcel Holtmann OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12ee485290SMarcel Holtmann FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 13ee485290SMarcel Holtmann IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 14ee485290SMarcel Holtmann CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 15ee485290SMarcel Holtmann WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16ee485290SMarcel Holtmann ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17ee485290SMarcel Holtmann OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18ee485290SMarcel Holtmann 19ee485290SMarcel Holtmann ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 20ee485290SMarcel Holtmann COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 21ee485290SMarcel Holtmann SOFTWARE IS DISCLAIMED. 22ee485290SMarcel Holtmann */ 23ee485290SMarcel Holtmann 246de50f9fSMarcel Holtmann #include <linux/debugfs.h> 256de50f9fSMarcel Holtmann 26ee485290SMarcel Holtmann #include <net/bluetooth/bluetooth.h> 270a2b0f04SJohan Hedberg #include <net/bluetooth/hci_core.h> 28ee485290SMarcel Holtmann 2958771c1cSSalvatore Benedetto #include "ecdh_helper.h" 300a2b0f04SJohan Hedberg #include "smp.h" 31ee485290SMarcel Holtmann #include "selftest.h" 32ee485290SMarcel Holtmann 330b6415b6SJohan Hedberg #if IS_ENABLED(CONFIG_BT_SELFTEST_ECDH) 340b6415b6SJohan Hedberg 350b6415b6SJohan Hedberg static const u8 priv_a_1[32] __initconst = { 360b6415b6SJohan Hedberg 0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58, 370b6415b6SJohan Hedberg 0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a, 380b6415b6SJohan Hedberg 0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74, 390b6415b6SJohan Hedberg 0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f, 400b6415b6SJohan Hedberg }; 410b6415b6SJohan Hedberg static const u8 priv_b_1[32] __initconst = { 420b6415b6SJohan Hedberg 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b, 430b6415b6SJohan Hedberg 0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59, 440b6415b6SJohan Hedberg 0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90, 450b6415b6SJohan Hedberg 0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55, 460b6415b6SJohan Hedberg }; 470b6415b6SJohan Hedberg static const u8 pub_a_1[64] __initconst = { 480b6415b6SJohan Hedberg 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 490b6415b6SJohan Hedberg 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, 500b6415b6SJohan Hedberg 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, 510b6415b6SJohan Hedberg 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, 520b6415b6SJohan Hedberg 530b6415b6SJohan Hedberg 0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74, 540b6415b6SJohan Hedberg 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76, 550b6415b6SJohan Hedberg 0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, 560b6415b6SJohan Hedberg 0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc, 570b6415b6SJohan Hedberg }; 580b6415b6SJohan Hedberg static const u8 pub_b_1[64] __initconst = { 590b6415b6SJohan Hedberg 0x90, 0xa1, 0xaa, 0x2f, 0xb2, 0x77, 0x90, 0x55, 600b6415b6SJohan Hedberg 0x9f, 0xa6, 0x15, 0x86, 0xfd, 0x8a, 0xb5, 0x47, 610b6415b6SJohan Hedberg 0x00, 0x4c, 0x9e, 0xf1, 0x84, 0x22, 0x59, 0x09, 620b6415b6SJohan Hedberg 0x96, 0x1d, 0xaf, 0x1f, 0xf0, 0xf0, 0xa1, 0x1e, 630b6415b6SJohan Hedberg 640b6415b6SJohan Hedberg 0x4a, 0x21, 0xb1, 0x15, 0xf9, 0xaf, 0x89, 0x5f, 650b6415b6SJohan Hedberg 0x76, 0x36, 0x8e, 0xe2, 0x30, 0x11, 0x2d, 0x47, 660b6415b6SJohan Hedberg 0x60, 0x51, 0xb8, 0x9a, 0x3a, 0x70, 0x56, 0x73, 670b6415b6SJohan Hedberg 0x37, 0xad, 0x9d, 0x42, 0x3e, 0xf3, 0x55, 0x4c, 680b6415b6SJohan Hedberg }; 690b6415b6SJohan Hedberg static const u8 dhkey_1[32] __initconst = { 700b6415b6SJohan Hedberg 0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86, 710b6415b6SJohan Hedberg 0xf1, 0x66, 0xf8, 0xb4, 0x13, 0x6b, 0x79, 0x99, 720b6415b6SJohan Hedberg 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, 730b6415b6SJohan Hedberg 0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec, 740b6415b6SJohan Hedberg }; 750b6415b6SJohan Hedberg 760b6415b6SJohan Hedberg static const u8 priv_a_2[32] __initconst = { 770b6415b6SJohan Hedberg 0x63, 0x76, 0x45, 0xd0, 0xf7, 0x73, 0xac, 0xb7, 780b6415b6SJohan Hedberg 0xff, 0xdd, 0x03, 0x72, 0xb9, 0x72, 0x85, 0xb4, 790b6415b6SJohan Hedberg 0x41, 0xb6, 0x5d, 0x0c, 0x5d, 0x54, 0x84, 0x60, 800b6415b6SJohan Hedberg 0x1a, 0xa3, 0x9a, 0x3c, 0x69, 0x16, 0xa5, 0x06, 810b6415b6SJohan Hedberg }; 820b6415b6SJohan Hedberg static const u8 priv_b_2[32] __initconst = { 830b6415b6SJohan Hedberg 0xba, 0x30, 0x55, 0x50, 0x19, 0xa2, 0xca, 0xa3, 840b6415b6SJohan Hedberg 0xa5, 0x29, 0x08, 0xc6, 0xb5, 0x03, 0x88, 0x7e, 850b6415b6SJohan Hedberg 0x03, 0x2b, 0x50, 0x73, 0xd4, 0x2e, 0x50, 0x97, 860b6415b6SJohan Hedberg 0x64, 0xcd, 0x72, 0x0d, 0x67, 0xa0, 0x9a, 0x52, 870b6415b6SJohan Hedberg }; 880b6415b6SJohan Hedberg static const u8 pub_a_2[64] __initconst = { 890b6415b6SJohan Hedberg 0xdd, 0x78, 0x5c, 0x74, 0x03, 0x9b, 0x7e, 0x98, 900b6415b6SJohan Hedberg 0xcb, 0x94, 0x87, 0x4a, 0xad, 0xfa, 0xf8, 0xd5, 910b6415b6SJohan Hedberg 0x43, 0x3e, 0x5c, 0xaf, 0xea, 0xb5, 0x4c, 0xf4, 920b6415b6SJohan Hedberg 0x9e, 0x80, 0x79, 0x57, 0x7b, 0xa4, 0x31, 0x2c, 930b6415b6SJohan Hedberg 940b6415b6SJohan Hedberg 0x4f, 0x5d, 0x71, 0x43, 0x77, 0x43, 0xf8, 0xea, 950b6415b6SJohan Hedberg 0xd4, 0x3e, 0xbd, 0x17, 0x91, 0x10, 0x21, 0xd0, 960b6415b6SJohan Hedberg 0x1f, 0x87, 0x43, 0x8e, 0x40, 0xe2, 0x52, 0xcd, 970b6415b6SJohan Hedberg 0xbe, 0xdf, 0x98, 0x38, 0x18, 0x12, 0x95, 0x91, 980b6415b6SJohan Hedberg }; 990b6415b6SJohan Hedberg static const u8 pub_b_2[64] __initconst = { 1000b6415b6SJohan Hedberg 0xcc, 0x00, 0x65, 0xe1, 0xf5, 0x6c, 0x0d, 0xcf, 1010b6415b6SJohan Hedberg 0xec, 0x96, 0x47, 0x20, 0x66, 0xc9, 0xdb, 0x84, 1020b6415b6SJohan Hedberg 0x81, 0x75, 0xa8, 0x4d, 0xc0, 0xdf, 0xc7, 0x9d, 1030b6415b6SJohan Hedberg 0x1b, 0x3f, 0x3d, 0xf2, 0x3f, 0xe4, 0x65, 0xf4, 1040b6415b6SJohan Hedberg 1050b6415b6SJohan Hedberg 0x79, 0xb2, 0xec, 0xd8, 0xca, 0x55, 0xa1, 0xa8, 1060b6415b6SJohan Hedberg 0x43, 0x4d, 0x6b, 0xca, 0x10, 0xb0, 0xc2, 0x01, 1070b6415b6SJohan Hedberg 0xc2, 0x33, 0x4e, 0x16, 0x24, 0xc4, 0xef, 0xee, 1080b6415b6SJohan Hedberg 0x99, 0xd8, 0xbb, 0xbc, 0x48, 0xd0, 0x01, 0x02, 1090b6415b6SJohan Hedberg }; 1100b6415b6SJohan Hedberg static const u8 dhkey_2[32] __initconst = { 1110b6415b6SJohan Hedberg 0x69, 0xeb, 0x21, 0x32, 0xf2, 0xc6, 0x05, 0x41, 1120b6415b6SJohan Hedberg 0x60, 0x19, 0xcd, 0x5e, 0x94, 0xe1, 0xe6, 0x5f, 1130b6415b6SJohan Hedberg 0x33, 0x07, 0xe3, 0x38, 0x4b, 0x68, 0xe5, 0x62, 1140b6415b6SJohan Hedberg 0x3f, 0x88, 0x6d, 0x2f, 0x3a, 0x84, 0x85, 0xab, 1150b6415b6SJohan Hedberg }; 1160b6415b6SJohan Hedberg 1170b6415b6SJohan Hedberg static const u8 priv_a_3[32] __initconst = { 1180b6415b6SJohan Hedberg 0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58, 1190b6415b6SJohan Hedberg 0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a, 1200b6415b6SJohan Hedberg 0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74, 1210b6415b6SJohan Hedberg 0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f, 1220b6415b6SJohan Hedberg }; 1230b6415b6SJohan Hedberg static const u8 pub_a_3[64] __initconst = { 1240b6415b6SJohan Hedberg 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 1250b6415b6SJohan Hedberg 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef, 1260b6415b6SJohan Hedberg 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e, 1270b6415b6SJohan Hedberg 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, 1280b6415b6SJohan Hedberg 1290b6415b6SJohan Hedberg 0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74, 1300b6415b6SJohan Hedberg 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76, 1310b6415b6SJohan Hedberg 0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, 1320b6415b6SJohan Hedberg 0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc, 1330b6415b6SJohan Hedberg }; 1340b6415b6SJohan Hedberg static const u8 dhkey_3[32] __initconst = { 1350b6415b6SJohan Hedberg 0x2d, 0xab, 0x00, 0x48, 0xcb, 0xb3, 0x7b, 0xda, 1360b6415b6SJohan Hedberg 0x55, 0x7b, 0x8b, 0x72, 0xa8, 0x57, 0x87, 0xc3, 1370b6415b6SJohan Hedberg 0x87, 0x27, 0x99, 0x32, 0xfc, 0x79, 0x5f, 0xae, 1380b6415b6SJohan Hedberg 0x7c, 0x1c, 0xf9, 0x49, 0xe6, 0xd7, 0xaa, 0x70, 1390b6415b6SJohan Hedberg }; 1400b6415b6SJohan Hedberg 14147eb2ac8STudor Ambarus static int __init test_ecdh_sample(struct crypto_kpp *tfm, const u8 priv_a[32], 14247eb2ac8STudor Ambarus const u8 priv_b[32], const u8 pub_a[64], 14347eb2ac8STudor Ambarus const u8 pub_b[64], const u8 dhkey[32]) 1440b6415b6SJohan Hedberg { 145763d9a30SSalvatore Benedetto u8 *tmp, *dhkey_a, *dhkey_b; 146*3814baf3STudor Ambarus int ret; 147763d9a30SSalvatore Benedetto 148763d9a30SSalvatore Benedetto tmp = kmalloc(64, GFP_KERNEL); 149763d9a30SSalvatore Benedetto if (!tmp) 150763d9a30SSalvatore Benedetto return -EINVAL; 151763d9a30SSalvatore Benedetto 152763d9a30SSalvatore Benedetto dhkey_a = &tmp[0]; 153763d9a30SSalvatore Benedetto dhkey_b = &tmp[32]; 1540b6415b6SJohan Hedberg 155*3814baf3STudor Ambarus ret = compute_ecdh_secret(tfm, pub_b, priv_a, dhkey_a); 156*3814baf3STudor Ambarus if (ret) 157*3814baf3STudor Ambarus goto out; 158*3814baf3STudor Ambarus 159*3814baf3STudor Ambarus ret = compute_ecdh_secret(tfm, pub_a, priv_b, dhkey_b); 160*3814baf3STudor Ambarus if (ret) 161*3814baf3STudor Ambarus goto out; 1620b6415b6SJohan Hedberg 163763d9a30SSalvatore Benedetto if (memcmp(dhkey_a, dhkey, 32)) { 164763d9a30SSalvatore Benedetto ret = -EINVAL; 165763d9a30SSalvatore Benedetto goto out; 166763d9a30SSalvatore Benedetto } 1670b6415b6SJohan Hedberg 1680b6415b6SJohan Hedberg if (memcmp(dhkey_b, dhkey, 32)) 169763d9a30SSalvatore Benedetto ret = -EINVAL; 1700b6415b6SJohan Hedberg 171763d9a30SSalvatore Benedetto out: 1723dfe55d9SColin Ian King kfree(tmp); 173763d9a30SSalvatore Benedetto return ret; 1740b6415b6SJohan Hedberg } 1750b6415b6SJohan Hedberg 1766de50f9fSMarcel Holtmann static char test_ecdh_buffer[32]; 1776de50f9fSMarcel Holtmann 1786de50f9fSMarcel Holtmann static ssize_t test_ecdh_read(struct file *file, char __user *user_buf, 1796de50f9fSMarcel Holtmann size_t count, loff_t *ppos) 1806de50f9fSMarcel Holtmann { 1816de50f9fSMarcel Holtmann return simple_read_from_buffer(user_buf, count, ppos, test_ecdh_buffer, 1826de50f9fSMarcel Holtmann strlen(test_ecdh_buffer)); 1836de50f9fSMarcel Holtmann } 1846de50f9fSMarcel Holtmann 1856de50f9fSMarcel Holtmann static const struct file_operations test_ecdh_fops = { 1866de50f9fSMarcel Holtmann .open = simple_open, 1876de50f9fSMarcel Holtmann .read = test_ecdh_read, 1886de50f9fSMarcel Holtmann .llseek = default_llseek, 1896de50f9fSMarcel Holtmann }; 1906de50f9fSMarcel Holtmann 1910b6415b6SJohan Hedberg static int __init test_ecdh(void) 1920b6415b6SJohan Hedberg { 19347eb2ac8STudor Ambarus struct crypto_kpp *tfm; 194e64b4fb6SMarcel Holtmann ktime_t calltime, delta, rettime; 195e64b4fb6SMarcel Holtmann unsigned long long duration; 1960b6415b6SJohan Hedberg int err; 1970b6415b6SJohan Hedberg 198e64b4fb6SMarcel Holtmann calltime = ktime_get(); 199e64b4fb6SMarcel Holtmann 20047eb2ac8STudor Ambarus tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0); 20147eb2ac8STudor Ambarus if (IS_ERR(tfm)) { 20247eb2ac8STudor Ambarus BT_ERR("Unable to create ECDH crypto context"); 20347eb2ac8STudor Ambarus err = PTR_ERR(tfm); 20447eb2ac8STudor Ambarus goto done; 20547eb2ac8STudor Ambarus } 20647eb2ac8STudor Ambarus 20747eb2ac8STudor Ambarus err = test_ecdh_sample(tfm, priv_a_1, priv_b_1, pub_a_1, pub_b_1, 20847eb2ac8STudor Ambarus dhkey_1); 2090b6415b6SJohan Hedberg if (err) { 2100b6415b6SJohan Hedberg BT_ERR("ECDH sample 1 failed"); 2116de50f9fSMarcel Holtmann goto done; 2120b6415b6SJohan Hedberg } 2130b6415b6SJohan Hedberg 21447eb2ac8STudor Ambarus err = test_ecdh_sample(tfm, priv_a_2, priv_b_2, pub_a_2, pub_b_2, 21547eb2ac8STudor Ambarus dhkey_2); 2160b6415b6SJohan Hedberg if (err) { 2170b6415b6SJohan Hedberg BT_ERR("ECDH sample 2 failed"); 2186de50f9fSMarcel Holtmann goto done; 2190b6415b6SJohan Hedberg } 2200b6415b6SJohan Hedberg 22147eb2ac8STudor Ambarus err = test_ecdh_sample(tfm, priv_a_3, priv_a_3, pub_a_3, pub_a_3, 22247eb2ac8STudor Ambarus dhkey_3); 2230b6415b6SJohan Hedberg if (err) { 2240b6415b6SJohan Hedberg BT_ERR("ECDH sample 3 failed"); 2256de50f9fSMarcel Holtmann goto done; 2260b6415b6SJohan Hedberg } 2270b6415b6SJohan Hedberg 22847eb2ac8STudor Ambarus crypto_free_kpp(tfm); 22947eb2ac8STudor Ambarus 230e64b4fb6SMarcel Holtmann rettime = ktime_get(); 231e64b4fb6SMarcel Holtmann delta = ktime_sub(rettime, calltime); 232e64b4fb6SMarcel Holtmann duration = (unsigned long long) ktime_to_ns(delta) >> 10; 233e64b4fb6SMarcel Holtmann 2345ced2464SMarcel Holtmann BT_INFO("ECDH test passed in %llu usecs", duration); 2350b6415b6SJohan Hedberg 2366de50f9fSMarcel Holtmann done: 2376de50f9fSMarcel Holtmann if (!err) 2386de50f9fSMarcel Holtmann snprintf(test_ecdh_buffer, sizeof(test_ecdh_buffer), 2396de50f9fSMarcel Holtmann "PASS (%llu usecs)\n", duration); 2406de50f9fSMarcel Holtmann else 2416de50f9fSMarcel Holtmann snprintf(test_ecdh_buffer, sizeof(test_ecdh_buffer), "FAIL\n"); 2426de50f9fSMarcel Holtmann 2436de50f9fSMarcel Holtmann debugfs_create_file("selftest_ecdh", 0444, bt_debugfs, NULL, 2446de50f9fSMarcel Holtmann &test_ecdh_fops); 2456de50f9fSMarcel Holtmann 2466de50f9fSMarcel Holtmann return err; 2470b6415b6SJohan Hedberg } 2480b6415b6SJohan Hedberg 2490b6415b6SJohan Hedberg #else 2500b6415b6SJohan Hedberg 2510b6415b6SJohan Hedberg static inline int test_ecdh(void) 2520b6415b6SJohan Hedberg { 2530b6415b6SJohan Hedberg return 0; 2540b6415b6SJohan Hedberg } 2550b6415b6SJohan Hedberg 2560b6415b6SJohan Hedberg #endif 2570b6415b6SJohan Hedberg 258ee485290SMarcel Holtmann static int __init run_selftest(void) 259ee485290SMarcel Holtmann { 2600b6415b6SJohan Hedberg int err; 2610b6415b6SJohan Hedberg 262ee485290SMarcel Holtmann BT_INFO("Starting self testing"); 263ee485290SMarcel Holtmann 2640b6415b6SJohan Hedberg err = test_ecdh(); 2650a2b0f04SJohan Hedberg if (err) 2660a2b0f04SJohan Hedberg goto done; 2670b6415b6SJohan Hedberg 2680a2b0f04SJohan Hedberg err = bt_selftest_smp(); 2690a2b0f04SJohan Hedberg 2700a2b0f04SJohan Hedberg done: 271ee485290SMarcel Holtmann BT_INFO("Finished self testing"); 272ee485290SMarcel Holtmann 2730b6415b6SJohan Hedberg return err; 274ee485290SMarcel Holtmann } 275ee485290SMarcel Holtmann 276ee485290SMarcel Holtmann #if IS_MODULE(CONFIG_BT) 277ee485290SMarcel Holtmann 278ee485290SMarcel Holtmann /* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=m and is just a 279ee485290SMarcel Holtmann * wrapper to allow running this at module init. 280ee485290SMarcel Holtmann * 281ee485290SMarcel Holtmann * If CONFIG_BT_SELFTEST=n, then this code is not compiled at all. 282ee485290SMarcel Holtmann */ 283ee485290SMarcel Holtmann int __init bt_selftest(void) 284ee485290SMarcel Holtmann { 285ee485290SMarcel Holtmann return run_selftest(); 286ee485290SMarcel Holtmann } 287ee485290SMarcel Holtmann 288ee485290SMarcel Holtmann #else 289ee485290SMarcel Holtmann 290ee485290SMarcel Holtmann /* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=y and is run 291ee485290SMarcel Holtmann * via late_initcall() as last item in the initialization sequence. 292ee485290SMarcel Holtmann * 293ee485290SMarcel Holtmann * If CONFIG_BT_SELFTEST=n, then this code is not compiled at all. 294ee485290SMarcel Holtmann */ 295ee485290SMarcel Holtmann static int __init bt_selftest_init(void) 296ee485290SMarcel Holtmann { 297ee485290SMarcel Holtmann return run_selftest(); 298ee485290SMarcel Holtmann } 299ee485290SMarcel Holtmann late_initcall(bt_selftest_init); 300ee485290SMarcel Holtmann 301ee485290SMarcel Holtmann #endif 302