1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8
9 #include <zephyr/bluetooth/mesh.h>
10 #include <zephyr/psa/key_ids.h>
11 #include <zephyr/sys/check.h>
12
13 #define LOG_LEVEL CONFIG_BT_MESH_CRYPTO_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(bt_mesh_crypto_psa);
16
17 #include "mesh.h"
18 #include "crypto.h"
19 #include "prov.h"
20
21 /* Mesh requires to keep in persistent memory network keys (2 keys per subnetwork),
22 * application keys (2 real keys per 1 configured) and device key + device key candidate.
23 */
24 #if defined CONFIG_BT_MESH_CDB
25 #define BT_MESH_CDB_KEY_ID_RANGE_SIZE (2 * SUBNET_COUNT + \
26 2 * APP_KEY_COUNT + NODE_COUNT)
27 #else
28 #define BT_MESH_CDB_KEY_ID_RANGE_SIZE 0
29 #endif
30
31 #define BT_MESH_PSA_KEY_ID_MIN ZEPHYR_PSA_BT_MESH_KEY_ID_RANGE_BEGIN
32
33 #define BT_MESH_PSA_KEY_ID_RANGE_SIZE (2 * CONFIG_BT_MESH_SUBNET_COUNT + \
34 2 * CONFIG_BT_MESH_APP_KEY_COUNT + 2 + BT_MESH_CDB_KEY_ID_RANGE_SIZE)
35 BUILD_ASSERT(BT_MESH_PSA_KEY_ID_RANGE_SIZE <= ZEPHYR_PSA_BT_MESH_KEY_ID_RANGE_SIZE,
36 "PSA key ID range exceeds officially allocated range.");
37
38 BUILD_ASSERT(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC) == 16,
39 "MAC length should be 16 bytes for 128-bits key for CMAC-AES");
40
41 BUILD_ASSERT(PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 256, PSA_ALG_HMAC(PSA_ALG_SHA_256)) == 32,
42 "MAC length should be 32 bytes for 256-bits key for HMAC-SHA");
43
44 static struct {
45 bool is_ready;
46 psa_key_id_t priv_key_id;
47 uint8_t public_key_be[PUB_KEY_SIZE + 1];
48 } dh_pair;
49
50 static ATOMIC_DEFINE(pst_keys, BT_MESH_PSA_KEY_ID_RANGE_SIZE);
51
bt_mesh_crypto_init(void)52 int bt_mesh_crypto_init(void)
53 {
54 if (psa_crypto_init() != PSA_SUCCESS) {
55 return -EIO;
56 }
57
58 return 0;
59 }
60
bt_mesh_encrypt(const struct bt_mesh_key * key,const uint8_t plaintext[16],uint8_t enc_data[16])61 int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
62 uint8_t enc_data[16])
63 {
64 uint32_t output_len;
65 psa_status_t status;
66 int err = 0;
67
68 status = psa_cipher_encrypt(key->key, PSA_ALG_ECB_NO_PADDING,
69 plaintext, 16,
70 enc_data, 16,
71 &output_len);
72
73 if (status != PSA_SUCCESS || output_len != 16) {
74 err = -EIO;
75 }
76
77 return err;
78 }
79
bt_mesh_ccm_encrypt(const struct bt_mesh_key * key,uint8_t nonce[13],const uint8_t * plaintext,size_t len,const uint8_t * aad,size_t aad_len,uint8_t * enc_data,size_t mic_size)80 int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
81 const uint8_t *plaintext, size_t len, const uint8_t *aad,
82 size_t aad_len, uint8_t *enc_data, size_t mic_size)
83 {
84 uint32_t output_len;
85 psa_status_t status;
86 int err = 0;
87 psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, mic_size);
88
89 status = psa_aead_encrypt(key->key, alg,
90 nonce, 13,
91 aad, aad_len,
92 plaintext, len,
93 enc_data, len + mic_size,
94 &output_len);
95
96 if (status != PSA_SUCCESS || output_len != len + mic_size) {
97 err = -EIO;
98 }
99
100 return err;
101 }
102
bt_mesh_ccm_decrypt(const struct bt_mesh_key * key,uint8_t nonce[13],const uint8_t * enc_data,size_t len,const uint8_t * aad,size_t aad_len,uint8_t * plaintext,size_t mic_size)103 int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
104 const uint8_t *enc_data, size_t len, const uint8_t *aad,
105 size_t aad_len, uint8_t *plaintext, size_t mic_size)
106 {
107 uint32_t output_len;
108 psa_status_t status;
109 int err = 0;
110 psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, mic_size);
111
112 status = psa_aead_decrypt(key->key, alg,
113 nonce, 13,
114 aad, aad_len,
115 enc_data, len + mic_size,
116 plaintext, len,
117 &output_len);
118
119 if (status != PSA_SUCCESS || output_len != len) {
120 err = -EIO;
121 }
122
123 return err;
124 }
125
bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key * key,struct bt_mesh_sg * sg,size_t sg_len,uint8_t mac[16])126 int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key, struct bt_mesh_sg *sg,
127 size_t sg_len, uint8_t mac[16])
128 {
129 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
130 psa_algorithm_t alg = PSA_ALG_CMAC;
131 psa_status_t status;
132
133 status = psa_mac_sign_setup(&operation, key->key, alg);
134 if (status != PSA_SUCCESS) {
135 return -EIO;
136 }
137
138 for (; sg_len; sg_len--, sg++) {
139 status = psa_mac_update(&operation, sg->data, sg->len);
140 if (status != PSA_SUCCESS) {
141 psa_mac_abort(&operation);
142 return -EIO;
143 }
144 }
145
146 size_t mac_len;
147
148 status = psa_mac_sign_finish(&operation, mac, 16, &mac_len);
149 if (status != PSA_SUCCESS) {
150 return -EIO;
151 }
152
153 if (mac_len != 16) {
154 return -ERANGE;
155 }
156
157 return 0;
158 }
159
bt_mesh_aes_cmac_raw_key(const uint8_t key[16],struct bt_mesh_sg * sg,size_t sg_len,uint8_t mac[16])160 int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
161 size_t sg_len, uint8_t mac[16])
162 {
163 struct bt_mesh_key key_id;
164 int err;
165
166 err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CMAC, key, &key_id);
167 if (err) {
168 return err;
169 }
170
171 err = bt_mesh_aes_cmac_mesh_key(&key_id, sg, sg_len, mac);
172
173 psa_destroy_key(key_id.key);
174
175 return err;
176 }
177
bt_mesh_sha256_hmac_raw_key(const uint8_t key[32],struct bt_mesh_sg * sg,size_t sg_len,uint8_t mac[32])178 int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg, size_t sg_len,
179 uint8_t mac[32])
180 {
181 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
182 psa_algorithm_t alg = PSA_ALG_HMAC(PSA_ALG_SHA_256);
183
184 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
185 psa_key_id_t key_id;
186
187 psa_status_t status;
188 int err = 0;
189
190 /* Import a key */
191 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
192 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
193 psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256));
194 psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
195 psa_set_key_bits(&attributes, 256);
196
197 status = psa_import_key(&attributes, key, 32, &key_id);
198 if (status != PSA_SUCCESS) {
199 err = -EIO;
200 goto end;
201 }
202
203 psa_reset_key_attributes(&attributes);
204
205 status = psa_mac_sign_setup(&operation, key_id, alg);
206 if (status != PSA_SUCCESS) {
207 err = -EIO;
208 goto end;
209 }
210
211 for (; sg_len; sg_len--, sg++) {
212 status = psa_mac_update(&operation, sg->data, sg->len);
213 if (status != PSA_SUCCESS) {
214 psa_mac_abort(&operation);
215 err = -EIO;
216 goto end;
217 }
218 }
219
220 size_t mac_len;
221
222 status = psa_mac_sign_finish(&operation, mac, 32, &mac_len);
223 if (status != PSA_SUCCESS) {
224 err = -EIO;
225 goto end;
226 }
227
228 if (mac_len != 32) {
229 err = -ERANGE;
230 }
231
232 end:
233 /* Destroy the key */
234 psa_destroy_key(key_id);
235
236 return err;
237 }
238
bt_mesh_pub_key_gen(void)239 int bt_mesh_pub_key_gen(void)
240 {
241 psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
242 psa_status_t status;
243 int err = 0;
244 size_t key_len;
245
246 psa_destroy_key(dh_pair.priv_key_id);
247 dh_pair.is_ready = false;
248
249 /* Crypto settings for ECDH using the SHA256 hashing algorithm,
250 * the secp256r1 curve
251 */
252 psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
253 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
254 psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
255 psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
256 psa_set_key_bits(&key_attributes, 256);
257
258 /* Generate a key pair */
259 status = psa_generate_key(&key_attributes, &dh_pair.priv_key_id);
260 if (status != PSA_SUCCESS) {
261 err = -EIO;
262 goto end;
263 }
264
265 status = psa_export_public_key(dh_pair.priv_key_id, dh_pair.public_key_be,
266 sizeof(dh_pair.public_key_be), &key_len);
267 if (status != PSA_SUCCESS) {
268 err = -EIO;
269 goto end;
270 }
271
272 if (key_len != PUB_KEY_SIZE + 1) {
273 err = -ERANGE;
274 goto end;
275 }
276
277 dh_pair.is_ready = true;
278
279 end:
280 psa_reset_key_attributes(&key_attributes);
281
282 return err;
283 }
284
bt_mesh_pub_key_get(void)285 const uint8_t *bt_mesh_pub_key_get(void)
286 {
287 return dh_pair.is_ready ? dh_pair.public_key_be + 1 : NULL;
288 }
289
290 BUILD_ASSERT(PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1),
291 256) == DH_KEY_SIZE,
292 "Diffie-Hellman shared secret size should be the same in PSA and Bluetooth Mesh");
293
294 BUILD_ASSERT(PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256) == PUB_KEY_SIZE + 1,
295 "Exported PSA public key should be 1 byte larger than Bluetooth Mesh public key");
296
bt_mesh_dhkey_gen(const uint8_t * pub_key,const uint8_t * priv_key,uint8_t * dhkey)297 int bt_mesh_dhkey_gen(const uint8_t *pub_key, const uint8_t *priv_key, uint8_t *dhkey)
298 {
299 int err = 0;
300 psa_key_id_t priv_key_id = PSA_KEY_ID_NULL;
301 uint8_t public_key_repr[PUB_KEY_SIZE + 1];
302 psa_status_t status;
303 size_t dh_key_len;
304
305 if (priv_key) {
306 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
307
308 /* Import a custom private key */
309 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
310 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
311 psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
312 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
313 psa_set_key_bits(&attributes, 256);
314
315 status = psa_import_key(&attributes, priv_key, PRIV_KEY_SIZE, &priv_key_id);
316 if (status != PSA_SUCCESS) {
317 err = -EIO;
318 goto end;
319 }
320
321 psa_reset_key_attributes(&attributes);
322 } else {
323 priv_key_id = dh_pair.priv_key_id;
324 }
325
326 /* For elliptic curve key pairs for Weierstrass curve families (PSA_ECC_FAMILY_SECP_R1)
327 * the representations of public key is:
328 * - The byte 0x04;
329 * - x_P as a ceiling(m/8)-byte string, big-endian;
330 * - y_P as a ceiling(m/8)-byte string, big-endian.
331 */
332 public_key_repr[0] = 0x04;
333 memcpy(public_key_repr + 1, pub_key, PUB_KEY_SIZE);
334
335 /* Calculate the secret */
336 status = psa_raw_key_agreement(PSA_ALG_ECDH, priv_key_id, public_key_repr,
337 PUB_KEY_SIZE + 1, dhkey, DH_KEY_SIZE, &dh_key_len);
338 if (status != PSA_SUCCESS) {
339 err = -EIO;
340 goto end;
341 }
342
343 if (dh_key_len != DH_KEY_SIZE) {
344 err = -ERANGE;
345 }
346
347 end:
348
349 if (priv_key) {
350 psa_destroy_key(priv_key_id);
351 }
352
353 return err;
354 }
355
keyid_alloc(void)356 static psa_key_id_t keyid_alloc(void)
357 {
358 for (int i = 0; i < BT_MESH_PSA_KEY_ID_RANGE_SIZE; i++) {
359 if (!atomic_test_bit(pst_keys, i)) {
360 atomic_set_bit(pst_keys, i);
361 return BT_MESH_PSA_KEY_ID_MIN + i;
362 }
363 }
364
365 return PSA_KEY_ID_NULL;
366 }
367
keyid_free(psa_key_id_t key_id)368 static int keyid_free(psa_key_id_t key_id)
369 {
370 if (IN_RANGE(key_id, BT_MESH_PSA_KEY_ID_MIN,
371 BT_MESH_PSA_KEY_ID_MIN + BT_MESH_PSA_KEY_ID_RANGE_SIZE - 1)) {
372 atomic_clear_bit(pst_keys, key_id - BT_MESH_PSA_KEY_ID_MIN);
373 return 0;
374 }
375
376 return -EIO;
377 }
378
keyid_assign(psa_key_id_t key_id)379 static void keyid_assign(psa_key_id_t key_id)
380 {
381 if (IN_RANGE(key_id, BT_MESH_PSA_KEY_ID_MIN,
382 BT_MESH_PSA_KEY_ID_MIN + BT_MESH_PSA_KEY_ID_RANGE_SIZE - 1)) {
383 atomic_set_bit(pst_keys, key_id - BT_MESH_PSA_KEY_ID_MIN);
384 }
385 }
386
bt_mesh_key_import(enum bt_mesh_key_type type,const uint8_t in[16],struct bt_mesh_key * out)387 int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16], struct bt_mesh_key *out)
388 {
389 psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
390 psa_status_t status;
391 psa_key_id_t key_id = PSA_KEY_ID_NULL;
392 int err = 0;
393
394 switch (type) {
395 case BT_MESH_KEY_TYPE_ECB:
396 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
397 psa_set_key_usage_flags(&key_attributes,
398 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
399 psa_set_key_algorithm(&key_attributes, PSA_ALG_ECB_NO_PADDING);
400 break;
401 case BT_MESH_KEY_TYPE_CCM:
402 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
403 psa_set_key_usage_flags(&key_attributes,
404 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
405 psa_set_key_algorithm(&key_attributes,
406 PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4));
407 break;
408 case BT_MESH_KEY_TYPE_CMAC:
409 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
410 psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
411 psa_set_key_algorithm(&key_attributes, PSA_ALG_CMAC);
412 break;
413 case BT_MESH_KEY_TYPE_NET:
414 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
415 key_id = keyid_alloc();
416
417 if (key_id == PSA_KEY_ID_NULL) {
418 return -ENOMEM;
419 }
420
421 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
422 psa_set_key_id(&key_attributes, key_id);
423 } else {
424 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
425 }
426 psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_EXPORT);
427 break;
428 case BT_MESH_KEY_TYPE_APP:
429 case BT_MESH_KEY_TYPE_DEV:
430 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
431 key_id = keyid_alloc();
432
433 if (key_id == PSA_KEY_ID_NULL) {
434 return -ENOMEM;
435 }
436
437 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
438 psa_set_key_id(&key_attributes, key_id);
439 } else {
440 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
441 }
442 psa_set_key_usage_flags(&key_attributes,
443 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT);
444 psa_set_key_algorithm(&key_attributes,
445 PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4));
446 break;
447 default:
448 return -EIO;
449 }
450
451 psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
452 psa_set_key_bits(&key_attributes, 128);
453
454 status = psa_import_key(&key_attributes, in, 16, &out->key);
455 err = status == PSA_SUCCESS ? 0 :
456 status == PSA_ERROR_ALREADY_EXISTS ? -EALREADY : -EIO;
457
458 if (err && key_id != PSA_KEY_ID_NULL) {
459 keyid_free(key_id);
460 }
461
462 psa_reset_key_attributes(&key_attributes);
463
464 return err;
465 }
466
bt_mesh_key_export(uint8_t out[16],const struct bt_mesh_key * in)467 int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in)
468 {
469 size_t data_length;
470
471 if (psa_export_key(in->key, out, 16, &data_length) != PSA_SUCCESS) {
472 return -EIO;
473 }
474
475 if (data_length != 16) {
476 return -EIO;
477 }
478
479 return 0;
480 }
481
bt_mesh_key_assign(struct bt_mesh_key * dst,const struct bt_mesh_key * src)482 void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src)
483 {
484 memcpy(dst, src, sizeof(struct bt_mesh_key));
485 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
486 keyid_assign(dst->key);
487 }
488 }
489
bt_mesh_key_destroy(const struct bt_mesh_key * key)490 int bt_mesh_key_destroy(const struct bt_mesh_key *key)
491 {
492 if (psa_destroy_key(key->key) != PSA_SUCCESS) {
493 return -EIO;
494 }
495
496 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
497 return keyid_free(key->key);
498 }
499
500 return 0;
501 }
502
bt_mesh_key_compare(const uint8_t raw_key[16],const struct bt_mesh_key * key)503 int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key)
504 {
505 uint8_t out[16];
506 int err;
507
508 err = bt_mesh_key_export(out, key);
509 if (err) {
510 return err;
511 }
512
513 return memcmp(out, raw_key, 16);
514 }
515
bt_rand(void * buf,size_t len)516 __weak int bt_rand(void *buf, size_t len)
517 {
518 CHECKIF(buf == NULL || len == 0) {
519 return -EINVAL;
520 }
521
522 return psa_generate_random(buf, len) == PSA_SUCCESS ? 0 : -EIO;
523 }
524