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