1 /*
2 * Copyright (c) 2017 Nordic Semiconductor ASA
3 * Copyright (c) 2015-2016 Intel Corporation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <string.h>
9 #include <errno.h>
10
11 #include <zephyr.h>
12 #include <sys/byteorder.h>
13
14 #include <bluetooth/bluetooth.h>
15 #include <bluetooth/hci.h>
16 #include <bluetooth/conn.h>
17 #include <bluetooth/crypto.h>
18
19 #include <tinycrypt/constants.h>
20 #include <tinycrypt/hmac_prng.h>
21 #include <tinycrypt/aes.h>
22 #include <tinycrypt/utils.h>
23
24 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
25 #define LOG_MODULE_NAME bt_crypto
26 #include "common/log.h"
27
28 #include "hci_core.h"
29
30 static struct tc_hmac_prng_struct prng;
31
prng_reseed(struct tc_hmac_prng_struct * h)32 static int prng_reseed(struct tc_hmac_prng_struct *h)
33 {
34 uint8_t seed[32];
35 int64_t extra;
36 size_t i;
37 int ret;
38
39 for (i = 0; i < (sizeof(seed) / 8); i++) {
40 struct bt_hci_rp_le_rand *rp;
41 struct net_buf *rsp;
42
43 ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
44 if (ret) {
45 return ret;
46 }
47
48 rp = (void *)rsp->data;
49 memcpy(&seed[i * 8], rp->rand, 8);
50
51 net_buf_unref(rsp);
52 }
53
54 extra = k_uptime_get();
55
56 ret = tc_hmac_prng_reseed(h, seed, sizeof(seed), (uint8_t *)&extra,
57 sizeof(extra));
58 if (ret == TC_CRYPTO_FAIL) {
59 BT_ERR("Failed to re-seed PRNG");
60 return -EIO;
61 }
62
63 return 0;
64 }
65
prng_init(void)66 int prng_init(void)
67 {
68 struct bt_hci_rp_le_rand *rp;
69 struct net_buf *rsp;
70 int ret;
71
72 /* Check first that HCI_LE_Rand is supported */
73 if (!BT_CMD_TEST(bt_dev.supported_commands, 27, 7)) {
74 return -ENOTSUP;
75 }
76
77 ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
78 if (ret) {
79 return ret;
80 }
81
82 rp = (void *)rsp->data;
83
84 ret = tc_hmac_prng_init(&prng, rp->rand, sizeof(rp->rand));
85
86 net_buf_unref(rsp);
87
88 if (ret == TC_CRYPTO_FAIL) {
89 BT_ERR("Failed to initialize PRNG");
90 return -EIO;
91 }
92
93 /* re-seed is needed after init */
94 return prng_reseed(&prng);
95 }
96
bt_rand(void * buf,size_t len)97 int bt_rand(void *buf, size_t len)
98 {
99 int ret;
100
101 ret = tc_hmac_prng_generate(buf, len, &prng);
102 if (ret == TC_HMAC_PRNG_RESEED_REQ) {
103 ret = prng_reseed(&prng);
104 if (ret) {
105 return ret;
106 }
107
108 ret = tc_hmac_prng_generate(buf, len, &prng);
109 }
110
111 if (ret == TC_CRYPTO_SUCCESS) {
112 return 0;
113 }
114
115 return -EIO;
116 }
117
bt_encrypt_le(const uint8_t key[16],const uint8_t plaintext[16],uint8_t enc_data[16])118 int bt_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
119 uint8_t enc_data[16])
120 {
121 struct tc_aes_key_sched_struct s;
122 uint8_t tmp[16];
123
124 BT_DBG("key %s", bt_hex(key, 16));
125 BT_DBG("plaintext %s", bt_hex(plaintext, 16));
126
127 sys_memcpy_swap(tmp, key, 16);
128
129 if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) {
130 return -EINVAL;
131 }
132
133 sys_memcpy_swap(tmp, plaintext, 16);
134
135 if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) {
136 return -EINVAL;
137 }
138
139 sys_mem_swap(enc_data, 16);
140
141 BT_DBG("enc_data %s", bt_hex(enc_data, 16));
142
143 return 0;
144 }
145
bt_encrypt_be(const uint8_t key[16],const uint8_t plaintext[16],uint8_t enc_data[16])146 int bt_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
147 uint8_t enc_data[16])
148 {
149 struct tc_aes_key_sched_struct s;
150
151 BT_DBG("key %s", bt_hex(key, 16));
152 BT_DBG("plaintext %s", bt_hex(plaintext, 16));
153
154 if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) {
155 return -EINVAL;
156 }
157
158 if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) {
159 return -EINVAL;
160 }
161
162 BT_DBG("enc_data %s", bt_hex(enc_data, 16));
163
164 return 0;
165 }
166