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