1 /* Copyright (c) 2024 Nordic Semiconductor
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 #include <zephyr/secure_storage/its/transform/aead_get.h>
5 #include <zephyr/drivers/hwinfo.h>
6 #include <zephyr/init.h>
7 #include <zephyr/logging/log.h>
8 #include <psa/crypto.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <mbedtls/platform_util.h>
12 
13 LOG_MODULE_DECLARE(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL);
14 
15 #if defined(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_AES_GCM)
16 #define PSA_KEY_TYPE PSA_KEY_TYPE_AES
17 #define PSA_ALG PSA_ALG_GCM
18 #elif defined(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CHACHA20_POLY1305)
19 #define PSA_KEY_TYPE PSA_KEY_TYPE_CHACHA20
20 #define PSA_ALG PSA_ALG_CHACHA20_POLY1305
21 #endif
22 #ifdef PSA_KEY_TYPE
secure_storage_its_transform_aead_get_scheme(psa_key_type_t * key_type,psa_algorithm_t * alg)23 void secure_storage_its_transform_aead_get_scheme(psa_key_type_t *key_type, psa_algorithm_t *alg)
24 {
25 	*key_type = PSA_KEY_TYPE;
26 	*alg = PSA_ALG;
27 }
28 #endif /* PSA_KEY_TYPE */
29 
30 #if	defined(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH) || \
31 	defined(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH)
32 
33 #define SHA256_OUTPUT_SIZE 32
34 BUILD_ASSERT(SHA256_OUTPUT_SIZE == PSA_HASH_LENGTH(PSA_ALG_SHA_256));
35 BUILD_ASSERT(SHA256_OUTPUT_SIZE >= CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE);
36 
hash_data_into_key(size_t data_len,const void * data,uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])37 static psa_status_t hash_data_into_key(
38 		size_t data_len, const void *data,
39 		uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])
40 {
41 	size_t hash_len;
42 
43 #if CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE == SHA256_OUTPUT_SIZE
44 	/* Save stack usage and avoid unnecessary memory operations.*/
45 	return psa_hash_compute(PSA_ALG_SHA_256, data, data_len, key,
46 				CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE, &hash_len);
47 #else
48 	uint8_t hash_output[SHA256_OUTPUT_SIZE];
49 	const psa_status_t ret = psa_hash_compute(PSA_ALG_SHA_256, data, data_len, hash_output,
50 						  sizeof(hash_output), &hash_len);
51 
52 	if (ret == PSA_SUCCESS) {
53 		memcpy(key, hash_output, CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE);
54 		mbedtls_platform_zeroize(hash_output, sizeof(hash_output));
55 	}
56 	return ret;
57 #endif
58 }
59 
60 #ifdef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH
61 
62 #define WARNING "Using a potentially insecure PSA ITS encryption key provider."
63 
secure_storage_its_transform_aead_get_key(secure_storage_its_uid_t uid,uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])64 psa_status_t secure_storage_its_transform_aead_get_key(
65 		secure_storage_its_uid_t uid,
66 		uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])
67 {
68 	psa_status_t ret;
69 	ssize_t hwinfo_ret;
70 	struct {
71 		uint8_t device_id[8];
72 		secure_storage_its_uid_t uid; /* acts as a salt */
73 	} __packed data;
74 
75 	hwinfo_ret = hwinfo_get_device_eui64(data.device_id);
76 	if (hwinfo_ret != 0) {
77 		hwinfo_ret = hwinfo_get_device_id(data.device_id, sizeof(data.device_id));
78 		if (hwinfo_ret <= 0) {
79 			LOG_DBG("Failed to retrieve the device ID. (%zd)", hwinfo_ret);
80 			return PSA_ERROR_HARDWARE_FAILURE;
81 		}
82 		if (hwinfo_ret < sizeof(data.device_id)) {
83 			memset(data.device_id + hwinfo_ret, 0, sizeof(data.device_id) - hwinfo_ret);
84 		}
85 	}
86 	data.uid = uid;
87 	ret = hash_data_into_key(sizeof(data), &data, key);
88 
89 	mbedtls_platform_zeroize(data.device_id, sizeof(data.device_id));
90 	return ret;
91 }
92 
93 #elif defined(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH)
94 
95 #define WARNING "Using an insecure PSA ITS encryption key provider."
96 
secure_storage_its_transform_aead_get_key(secure_storage_its_uid_t uid,uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])97 psa_status_t secure_storage_its_transform_aead_get_key(
98 		secure_storage_its_uid_t uid,
99 		uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])
100 {
101 	return hash_data_into_key(sizeof(uid), &uid, key);
102 }
103 
104 #endif /* CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER */
105 
106 #ifndef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING
107 
warn_insecure_key(void)108 static int warn_insecure_key(void)
109 {
110 	printk("WARNING: %s\n", WARNING);
111 	LOG_WRN("%s", WARNING);
112 	return 0;
113 }
114 SYS_INIT(warn_insecure_key, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
115 
116 #endif /* !CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING */
117 
118 #endif /* CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH || */
119        /* CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH    */
120 
121 #ifdef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_DEFAULT
122 
secure_storage_its_transform_aead_get_nonce(uint8_t nonce[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE])123 psa_status_t secure_storage_its_transform_aead_get_nonce(
124 		uint8_t nonce[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE])
125 {
126 	psa_status_t ret;
127 	static uint8_t s_nonce[CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE];
128 	static bool s_nonce_initialized;
129 
130 	if (!s_nonce_initialized) {
131 		ret = psa_generate_random(s_nonce, sizeof(s_nonce));
132 		if (ret != PSA_SUCCESS) {
133 			return ret;
134 		}
135 		s_nonce_initialized = true;
136 	} else {
137 		for (unsigned int i = 0; i != sizeof(s_nonce); ++i) {
138 			++s_nonce[i];
139 			if (s_nonce[i] != 0) {
140 				break;
141 			}
142 		}
143 	}
144 
145 	memcpy(nonce, &s_nonce, sizeof(s_nonce));
146 	return PSA_SUCCESS;
147 }
148 #endif /* CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_DEFAULT */
149