/* * Copyright (c) 2017 Nordic Semiconductor ASA * Copyright (c) 2015-2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE) #include "common/log.h" #include "hci_core.h" static struct tc_hmac_prng_struct prng; static int prng_reseed(struct tc_hmac_prng_struct *h) { u8_t seed[32]; s64_t extra; int ret, i; for (i = 0; i < (sizeof(seed) / 8); i++) { struct bt_hci_rp_le_rand *rp; struct net_buf *rsp; ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp); if (ret) { return ret; } rp = (void *)rsp->data; memcpy(&seed[i * 8], rp->rand, 8); net_buf_unref(rsp); } extra = k_uptime_get(); ret = tc_hmac_prng_reseed(h, seed, sizeof(seed), (u8_t *)&extra, sizeof(extra)); if (ret == TC_CRYPTO_FAIL) { BT_ERR("Failed to re-seed PRNG"); return -EIO; } return 0; } int prng_init(void) { struct bt_hci_rp_le_rand *rp; struct net_buf *rsp; int ret; /* Check first that HCI_LE_Rand is supported */ if (!(bt_dev.supported_commands[27] & BIT(7))) { return -ENOTSUP; } ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp); if (ret) { return ret; } rp = (void *)rsp->data; ret = tc_hmac_prng_init(&prng, rp->rand, sizeof(rp->rand)); net_buf_unref(rsp); if (ret == TC_CRYPTO_FAIL) { BT_ERR("Failed to initialize PRNG"); return -EIO; } /* re-seed is needed after init */ return prng_reseed(&prng); } int bt_rand(void *buf, size_t len) { int ret; ret = tc_hmac_prng_generate(buf, len, &prng); if (ret == TC_HMAC_PRNG_RESEED_REQ) { ret = prng_reseed(&prng); if (ret) { return ret; } ret = tc_hmac_prng_generate(buf, len, &prng); } if (ret == TC_CRYPTO_SUCCESS) { return 0; } return -EIO; } int bt_encrypt_le(const u8_t key[16], const u8_t plaintext[16], u8_t enc_data[16]) { struct tc_aes_key_sched_struct s; u8_t tmp[16]; BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16)); sys_memcpy_swap(tmp, key, 16); if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) { return -EINVAL; } sys_memcpy_swap(tmp, plaintext, 16); if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) { return -EINVAL; } sys_mem_swap(enc_data, 16); BT_DBG("enc_data %s", bt_hex(enc_data, 16)); return 0; } int bt_encrypt_be(const u8_t key[16], const u8_t plaintext[16], u8_t enc_data[16]) { struct tc_aes_key_sched_struct s; BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16)); if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) { return -EINVAL; } if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) { return -EINVAL; } BT_DBG("enc_data %s", bt_hex(enc_data, 16)); return 0; }