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