1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/logging/log.h>
9 #include "psa/crypto.h"
10 
11 #include "wifi_credentials_internal.h"
12 
13 LOG_MODULE_REGISTER(wifi_credentials_backend, CONFIG_WIFI_CREDENTIALS_LOG_LEVEL);
14 
15 #define WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN                                               \
16 	(PSA_KEY_ID_USER_MIN + CONFIG_WIFI_CREDENTIALS_BACKEND_PSA_OFFSET)
17 
18 BUILD_ASSERT((WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN + CONFIG_WIFI_CREDENTIALS_MAX_ENTRIES) <=
19 		     PSA_KEY_ID_USER_MAX,
20 	     "WIFI credentials management PSA key id range exceeds PSA_KEY_ID_USER_MAX.");
21 
wifi_credentials_backend_init(void)22 int wifi_credentials_backend_init(void)
23 {
24 	psa_status_t ret;
25 	uint8_t buf[ENTRY_MAX_LEN];
26 
27 	for (size_t i = 0; i < CONFIG_WIFI_CREDENTIALS_MAX_ENTRIES; ++i) {
28 		size_t length_read = 0;
29 		size_t key_id = i + WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN;
30 
31 		ret = psa_export_key(key_id, buf, ARRAY_SIZE(buf), &length_read);
32 		if (ret == PSA_SUCCESS && length_read == ENTRY_MAX_LEN) {
33 			wifi_credentials_cache_ssid(i, (struct wifi_credentials_header *)buf);
34 		} else if (ret != PSA_ERROR_INVALID_HANDLE) {
35 			LOG_ERR("psa_export_key failed, err: %d", ret);
36 			return -EFAULT;
37 		}
38 	}
39 
40 	return 0;
41 }
42 
wifi_credentials_store_entry(size_t idx,const void * buf,size_t buf_len)43 int wifi_credentials_store_entry(size_t idx, const void *buf, size_t buf_len)
44 {
45 	psa_status_t ret;
46 	psa_key_attributes_t key_attributes = {0};
47 	psa_key_id_t key_id;
48 
49 	psa_set_key_id(&key_attributes, idx + WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN);
50 	psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_EXPORT);
51 	psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
52 	psa_set_key_algorithm(&key_attributes, PSA_ALG_NONE);
53 	psa_set_key_type(&key_attributes, PSA_KEY_TYPE_RAW_DATA);
54 	psa_set_key_bits(&key_attributes, buf_len * 8);
55 
56 	ret = psa_import_key(&key_attributes, buf, buf_len, &key_id);
57 	if (ret == PSA_ERROR_ALREADY_EXISTS) {
58 		LOG_ERR("psa_import_key failed, duplicate key: %d", ret);
59 		return -EEXIST;
60 	} else if (ret != PSA_SUCCESS) {
61 		LOG_ERR("psa_import_key failed, err: %d", ret);
62 		return -EFAULT;
63 	}
64 
65 	return 0;
66 }
67 
wifi_credentials_delete_entry(size_t idx)68 int wifi_credentials_delete_entry(size_t idx)
69 {
70 	psa_status_t ret = psa_destroy_key(idx + WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN);
71 
72 	if (ret != PSA_SUCCESS) {
73 		LOG_ERR("psa_destroy_key failed, err: %d", ret);
74 		return -EFAULT;
75 	}
76 
77 	return 0;
78 }
79 
wifi_credentials_load_entry(size_t idx,void * buf,size_t buf_len)80 int wifi_credentials_load_entry(size_t idx, void *buf, size_t buf_len)
81 {
82 	size_t length_read = 0;
83 	size_t key_id = idx + WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN;
84 	psa_status_t ret;
85 
86 	ret = psa_export_key(key_id, buf, buf_len, &length_read);
87 	if (ret != PSA_SUCCESS) {
88 		LOG_ERR("psa_export_key failed, err: %d", ret);
89 		return -EFAULT;
90 	}
91 
92 	if (buf_len != length_read) {
93 		return -EIO;
94 	}
95 
96 	return 0;
97 }
98