/*
BlueZ - Bluetooth protocol stack for Linux
Copyright ( C ) 2014 Intel Corporation
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation ;
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS
OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS .
IN NO EVENT SHALL THE COPYRIGHT HOLDER ( S ) AND AUTHOR ( S ) BE LIABLE FOR ANY
CLAIM , OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES , OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER IN AN
ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
ALL LIABILITY , INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS ,
COPYRIGHTS , TRADEMARKS OR OTHER RIGHTS , RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED .
*/
#include <linux/debugfs.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "ecdh_helper.h"
#include "smp.h"
#include "selftest.h"
#if IS_ENABLED(CONFIG_BT_SELFTEST_ECDH)
static const u8 priv_a_1[32 ] __initconst = {
0 xbd, 0 x1a, 0 x3c, 0 xcd, 0 xa6, 0 xb8, 0 x99, 0 x58,
0 x99, 0 xb7, 0 x40, 0 xeb, 0 x7b, 0 x60, 0 xff, 0 x4a,
0 x50, 0 x3f, 0 x10, 0 xd2, 0 xe3, 0 xb3, 0 xc9, 0 x74,
0 x38, 0 x5f, 0 xc5, 0 xa3, 0 xd4, 0 xf6, 0 x49, 0 x3f,
};
static const u8 priv_b_1[32 ] __initconst = {
0 xfd, 0 xc5, 0 x7f, 0 xf4, 0 x49, 0 xdd, 0 x4f, 0 x6b,
0 xfb, 0 x7c, 0 x9d, 0 xf1, 0 xc2, 0 x9a, 0 xcb, 0 x59,
0 x2a, 0 xe7, 0 xd4, 0 xee, 0 xfb, 0 xfc, 0 x0a, 0 x90,
0 x9a, 0 xbb, 0 xf6, 0 x32, 0 x3d, 0 x8b, 0 x18, 0 x55,
};
static const u8 pub_a_1[64 ] __initconst = {
0 xe6, 0 x9d, 0 x35, 0 x0e, 0 x48, 0 x01, 0 x03, 0 xcc,
0 xdb, 0 xfd, 0 xf4, 0 xac, 0 x11, 0 x91, 0 xf4, 0 xef,
0 xb9, 0 xa5, 0 xf9, 0 xe9, 0 xa7, 0 x83, 0 x2c, 0 x5e,
0 x2c, 0 xbe, 0 x97, 0 xf2, 0 xd2, 0 x03, 0 xb0, 0 x20,
0 x8b, 0 xd2, 0 x89, 0 x15, 0 xd0, 0 x8e, 0 x1c, 0 x74,
0 x24, 0 x30, 0 xed, 0 x8f, 0 xc2, 0 x45, 0 x63, 0 x76,
0 x5c, 0 x15, 0 x52, 0 x5a, 0 xbf, 0 x9a, 0 x32, 0 x63,
0 x6d, 0 xeb, 0 x2a, 0 x65, 0 x49, 0 x9c, 0 x80, 0 xdc,
};
static const u8 pub_b_1[64 ] __initconst = {
0 x90, 0 xa1, 0 xaa, 0 x2f, 0 xb2, 0 x77, 0 x90, 0 x55,
0 x9f, 0 xa6, 0 x15, 0 x86, 0 xfd, 0 x8a, 0 xb5, 0 x47,
0 x00, 0 x4c, 0 x9e, 0 xf1, 0 x84, 0 x22, 0 x59, 0 x09,
0 x96, 0 x1d, 0 xaf, 0 x1f, 0 xf0, 0 xf0, 0 xa1, 0 x1e,
0 x4a, 0 x21, 0 xb1, 0 x15, 0 xf9, 0 xaf, 0 x89, 0 x5f,
0 x76, 0 x36, 0 x8e, 0 xe2, 0 x30, 0 x11, 0 x2d, 0 x47,
0 x60, 0 x51, 0 xb8, 0 x9a, 0 x3a, 0 x70, 0 x56, 0 x73,
0 x37, 0 xad, 0 x9d, 0 x42, 0 x3e, 0 xf3, 0 x55, 0 x4c,
};
static const u8 dhkey_1[32 ] __initconst = {
0 x98, 0 xa6, 0 xbf, 0 x73, 0 xf3, 0 x34, 0 x8d, 0 x86,
0 xf1, 0 x66, 0 xf8, 0 xb4, 0 x13, 0 x6b, 0 x79, 0 x99,
0 x9b, 0 x7d, 0 x39, 0 x0a, 0 xa6, 0 x10, 0 x10, 0 x34,
0 x05, 0 xad, 0 xc8, 0 x57, 0 xa3, 0 x34, 0 x02, 0 xec,
};
static const u8 priv_a_2[32 ] __initconst = {
0 x63, 0 x76, 0 x45, 0 xd0, 0 xf7, 0 x73, 0 xac, 0 xb7,
0 xff, 0 xdd, 0 x03, 0 x72, 0 xb9, 0 x72, 0 x85, 0 xb4,
0 x41, 0 xb6, 0 x5d, 0 x0c, 0 x5d, 0 x54, 0 x84, 0 x60,
0 x1a, 0 xa3, 0 x9a, 0 x3c, 0 x69, 0 x16, 0 xa5, 0 x06,
};
static const u8 priv_b_2[32 ] __initconst = {
0 xba, 0 x30, 0 x55, 0 x50, 0 x19, 0 xa2, 0 xca, 0 xa3,
0 xa5, 0 x29, 0 x08, 0 xc6, 0 xb5, 0 x03, 0 x88, 0 x7e,
0 x03, 0 x2b, 0 x50, 0 x73, 0 xd4, 0 x2e, 0 x50, 0 x97,
0 x64, 0 xcd, 0 x72, 0 x0d, 0 x67, 0 xa0, 0 x9a, 0 x52,
};
static const u8 pub_a_2[64 ] __initconst = {
0 xdd, 0 x78, 0 x5c, 0 x74, 0 x03, 0 x9b, 0 x7e, 0 x98,
0 xcb, 0 x94, 0 x87, 0 x4a, 0 xad, 0 xfa, 0 xf8, 0 xd5,
0 x43, 0 x3e, 0 x5c, 0 xaf, 0 xea, 0 xb5, 0 x4c, 0 xf4,
0 x9e, 0 x80, 0 x79, 0 x57, 0 x7b, 0 xa4, 0 x31, 0 x2c,
0 x4f, 0 x5d, 0 x71, 0 x43, 0 x77, 0 x43, 0 xf8, 0 xea,
0 xd4, 0 x3e, 0 xbd, 0 x17, 0 x91, 0 x10, 0 x21, 0 xd0,
0 x1f, 0 x87, 0 x43, 0 x8e, 0 x40, 0 xe2, 0 x52, 0 xcd,
0 xbe, 0 xdf, 0 x98, 0 x38, 0 x18, 0 x12, 0 x95, 0 x91,
};
static const u8 pub_b_2[64 ] __initconst = {
0 xcc, 0 x00, 0 x65, 0 xe1, 0 xf5, 0 x6c, 0 x0d, 0 xcf,
0 xec, 0 x96, 0 x47, 0 x20, 0 x66, 0 xc9, 0 xdb, 0 x84,
0 x81, 0 x75, 0 xa8, 0 x4d, 0 xc0, 0 xdf, 0 xc7, 0 x9d,
0 x1b, 0 x3f, 0 x3d, 0 xf2, 0 x3f, 0 xe4, 0 x65, 0 xf4,
0 x79, 0 xb2, 0 xec, 0 xd8, 0 xca, 0 x55, 0 xa1, 0 xa8,
0 x43, 0 x4d, 0 x6b, 0 xca, 0 x10, 0 xb0, 0 xc2, 0 x01,
0 xc2, 0 x33, 0 x4e, 0 x16, 0 x24, 0 xc4, 0 xef, 0 xee,
0 x99, 0 xd8, 0 xbb, 0 xbc, 0 x48, 0 xd0, 0 x01, 0 x02,
};
static const u8 dhkey_2[32 ] __initconst = {
0 x69, 0 xeb, 0 x21, 0 x32, 0 xf2, 0 xc6, 0 x05, 0 x41,
0 x60, 0 x19, 0 xcd, 0 x5e, 0 x94, 0 xe1, 0 xe6, 0 x5f,
0 x33, 0 x07, 0 xe3, 0 x38, 0 x4b, 0 x68, 0 xe5, 0 x62,
0 x3f, 0 x88, 0 x6d, 0 x2f, 0 x3a, 0 x84, 0 x85, 0 xab,
};
static const u8 priv_a_3[32 ] __initconst = {
0 xbd, 0 x1a, 0 x3c, 0 xcd, 0 xa6, 0 xb8, 0 x99, 0 x58,
0 x99, 0 xb7, 0 x40, 0 xeb, 0 x7b, 0 x60, 0 xff, 0 x4a,
0 x50, 0 x3f, 0 x10, 0 xd2, 0 xe3, 0 xb3, 0 xc9, 0 x74,
0 x38, 0 x5f, 0 xc5, 0 xa3, 0 xd4, 0 xf6, 0 x49, 0 x3f,
};
static const u8 pub_a_3[64 ] __initconst = {
0 xe6, 0 x9d, 0 x35, 0 x0e, 0 x48, 0 x01, 0 x03, 0 xcc,
0 xdb, 0 xfd, 0 xf4, 0 xac, 0 x11, 0 x91, 0 xf4, 0 xef,
0 xb9, 0 xa5, 0 xf9, 0 xe9, 0 xa7, 0 x83, 0 x2c, 0 x5e,
0 x2c, 0 xbe, 0 x97, 0 xf2, 0 xd2, 0 x03, 0 xb0, 0 x20,
0 x8b, 0 xd2, 0 x89, 0 x15, 0 xd0, 0 x8e, 0 x1c, 0 x74,
0 x24, 0 x30, 0 xed, 0 x8f, 0 xc2, 0 x45, 0 x63, 0 x76,
0 x5c, 0 x15, 0 x52, 0 x5a, 0 xbf, 0 x9a, 0 x32, 0 x63,
0 x6d, 0 xeb, 0 x2a, 0 x65, 0 x49, 0 x9c, 0 x80, 0 xdc,
};
static const u8 dhkey_3[32 ] __initconst = {
0 x2d, 0 xab, 0 x00, 0 x48, 0 xcb, 0 xb3, 0 x7b, 0 xda,
0 x55, 0 x7b, 0 x8b, 0 x72, 0 xa8, 0 x57, 0 x87, 0 xc3,
0 x87, 0 x27, 0 x99, 0 x32, 0 xfc, 0 x79, 0 x5f, 0 xae,
0 x7c, 0 x1c, 0 xf9, 0 x49, 0 xe6, 0 xd7, 0 xaa, 0 x70,
};
static int __init test_ecdh_sample(struct crypto_kpp *tfm, const u8 priv_a[32 ],
const u8 priv_b[32 ], const u8 pub_a[64 ],
const u8 pub_b[64 ], const u8 dhkey[32 ])
{
u8 *tmp, *dhkey_a, *dhkey_b;
int ret;
tmp = kmalloc(64 , GFP_KERNEL);
if (!tmp)
return -EINVAL;
dhkey_a = &tmp[0 ];
dhkey_b = &tmp[32 ];
ret = set_ecdh_privkey(tfm, priv_a);
if (ret)
goto out;
ret = compute_ecdh_secret(tfm, pub_b, dhkey_a);
if (ret)
goto out;
if (memcmp(dhkey_a, dhkey, 32 )) {
ret = -EINVAL;
goto out;
}
ret = set_ecdh_privkey(tfm, priv_b);
if (ret)
goto out;
ret = compute_ecdh_secret(tfm, pub_a, dhkey_b);
if (ret)
goto out;
if (memcmp(dhkey_b, dhkey, 32 ))
ret = -EINVAL;
/* fall through*/
out:
kfree(tmp);
return ret;
}
static char test_ecdh_buffer[32 ];
static ssize_t test_ecdh_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
return simple_read_from_buffer(user_buf, count, ppos, test_ecdh_buffer,
strlen(test_ecdh_buffer));
}
static const struct file_operations test_ecdh_fops = {
.open = simple_open,
.read = test_ecdh_read,
.llseek = default_llseek,
};
static int __init test_ecdh(void )
{
struct crypto_kpp *tfm;
ktime_t calltime, delta, rettime;
unsigned long long duration = 0 ;
int err;
calltime = ktime_get();
tfm = crypto_alloc_kpp("ecdh-nist-p256" , 0 , 0 );
if (IS_ERR(tfm)) {
BT_ERR("Unable to create ECDH crypto context" );
err = PTR_ERR(tfm);
goto done;
}
err = test_ecdh_sample(tfm, priv_a_1, priv_b_1, pub_a_1, pub_b_1,
dhkey_1);
if (err) {
BT_ERR("ECDH sample 1 failed" );
goto done;
}
err = test_ecdh_sample(tfm, priv_a_2, priv_b_2, pub_a_2, pub_b_2,
dhkey_2);
if (err) {
BT_ERR("ECDH sample 2 failed" );
goto done;
}
err = test_ecdh_sample(tfm, priv_a_3, priv_a_3, pub_a_3, pub_a_3,
dhkey_3);
if (err) {
BT_ERR("ECDH sample 3 failed" );
goto done;
}
crypto_free_kpp(tfm);
rettime = ktime_get();
delta = ktime_sub(rettime, calltime);
duration = (unsigned long long ) ktime_to_ns(delta) >> 10 ;
BT_INFO("ECDH test passed in %llu usecs" , duration);
done:
if (!err)
snprintf(test_ecdh_buffer, sizeof (test_ecdh_buffer),
"PASS (%llu usecs)\n" , duration);
else
snprintf(test_ecdh_buffer, sizeof (test_ecdh_buffer), "FAIL\n" );
debugfs_create_file("selftest_ecdh" , 0444 , bt_debugfs, NULL,
&test_ecdh_fops);
return err;
}
#else
static inline int test_ecdh(void )
{
return 0 ;
}
#endif
static int __init run_selftest(void )
{
int err;
BT_INFO("Starting self testing" );
err = test_ecdh();
if (err)
goto done;
err = bt_selftest_smp();
done:
BT_INFO("Finished self testing" );
return err;
}
#if IS_MODULE(CONFIG_BT)
/* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=m and is just a
* wrapper to allow running this at module init .
*
* If CONFIG_BT_SELFTEST = n , then this code is not compiled at all .
*/
int __init bt_selftest(void )
{
return run_selftest();
}
#else
/* This is run when CONFIG_BT_SELFTEST=y and CONFIG_BT=y and is run
* via late_initcall ( ) as last item in the initialization sequence .
*
* If CONFIG_BT_SELFTEST = n , then this code is not compiled at all .
*/
static int __init bt_selftest_init(void )
{
return run_selftest();
}
late_initcall(bt_selftest_init);
#endif
Messung V0.5 in Prozent C=99 H=81 G=90