1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <stdbool.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/init.h>
13 
14 #include <zephyr/fff.h>
15 
16 #include <zephyr/net/wifi_credentials.h>
17 
18 #include "wifi_credentials_internal.h"
19 #include "psa/crypto_types.h"
20 #include "psa/crypto_values.h"
21 
22 #define SSID1     "test1"
23 #define PSK1      "super secret"
24 #define SECURITY1 WIFI_SECURITY_TYPE_PSK
25 #define BSSID1    "abcdef"
26 #define FLAGS1    WIFI_CREDENTIALS_FLAG_BSSID
27 
28 #define SSID2     "test2"
29 #define PSK2      NULL
30 #define SECURITY2 WIFI_SECURITY_TYPE_NONE
31 #define BSSID2    NULL
32 #define FLAGS2    0
33 
34 #define WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN                                               \
35 	(PSA_KEY_ID_USER_MIN + CONFIG_WIFI_CREDENTIALS_BACKEND_PSA_OFFSET)
36 
37 DEFINE_FFF_GLOBALS;
38 
39 K_MUTEX_DEFINE(wifi_credentials_mutex);
40 
41 FAKE_VOID_FUNC(wifi_credentials_cache_ssid, size_t, const struct wifi_credentials_header *);
42 FAKE_VALUE_FUNC(psa_status_t, psa_export_key, mbedtls_svc_key_id_t, uint8_t *, size_t, size_t *);
43 FAKE_VALUE_FUNC(psa_status_t, psa_import_key, psa_key_attributes_t *, uint8_t *, size_t,
44 		mbedtls_svc_key_id_t *);
45 FAKE_VALUE_FUNC(psa_status_t, psa_destroy_key, mbedtls_svc_key_id_t);
46 FAKE_VOID_FUNC(psa_set_key_id, psa_key_attributes_t *, uint32_t);
47 FAKE_VOID_FUNC(psa_set_key_usage_flags, psa_key_attributes_t *, psa_key_usage_t);
48 FAKE_VOID_FUNC(psa_set_key_lifetime, psa_key_attributes_t *, psa_key_lifetime_t);
49 FAKE_VOID_FUNC(psa_set_key_algorithm, psa_key_attributes_t *, psa_algorithm_t);
50 FAKE_VOID_FUNC(psa_set_key_type, psa_key_attributes_t *, psa_key_type_t);
51 FAKE_VOID_FUNC(psa_set_key_bits, psa_key_attributes_t *, size_t);
52 
53 static const struct wifi_credentials_personal example1 = {
54 	.header = {
55 		.ssid = SSID1,
56 		.ssid_len = strlen(SSID1),
57 		.type = SECURITY1,
58 		.bssid = BSSID1,
59 		.flags = FLAGS1,
60 	},
61 	.password = PSK1,
62 	.password_len = strlen(PSK1),
63 };
64 
65 static const struct wifi_credentials_personal example2 = {
66 	.header = {
67 		.ssid = SSID2,
68 		.ssid_len = strlen(SSID2),
69 		.type = SECURITY2,
70 		.flags = FLAGS2,
71 	},
72 };
73 
74 static size_t idx;
75 
custom_psa_export_key(mbedtls_svc_key_id_t key,uint8_t * data,size_t data_size,size_t * data_length)76 psa_status_t custom_psa_export_key(mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size,
77 				   size_t *data_length)
78 {
79 	/* confirm that we read the requested amount of data */
80 	*data_length = data_size;
81 	return PSA_SUCCESS;
82 }
83 
custom_psa_set_key_id(psa_key_attributes_t * attributes,mbedtls_svc_key_id_t key)84 static void custom_psa_set_key_id(psa_key_attributes_t *attributes, mbedtls_svc_key_id_t key)
85 {
86 	zassert_equal(idx + WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN, key, "Key ID mismatch");
87 }
88 
custom_psa_set_key_bits(psa_key_attributes_t * attributes,size_t bits)89 void custom_psa_set_key_bits(psa_key_attributes_t *attributes, size_t bits)
90 {
91 	zassert_equal(sizeof(struct wifi_credentials_personal) * 8, bits, "Key bits mismatch");
92 }
93 
custom_psa_set_key_type(psa_key_attributes_t * attributes,psa_key_type_t type)94 void custom_psa_set_key_type(psa_key_attributes_t *attributes, psa_key_type_t type)
95 {
96 	zassert_equal(PSA_KEY_TYPE_RAW_DATA, type, "Key type mismatch");
97 }
98 
custom_psa_set_key_algorithm(psa_key_attributes_t * attributes,psa_algorithm_t alg)99 void custom_psa_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg)
100 {
101 	zassert_equal(PSA_ALG_NONE, alg, "Key algorithm mismatch");
102 }
103 
custom_psa_set_key_lifetime(psa_key_attributes_t * attributes,psa_key_lifetime_t lifetime)104 void custom_psa_set_key_lifetime(psa_key_attributes_t *attributes, psa_key_lifetime_t lifetime)
105 {
106 	zassert_equal(PSA_KEY_LIFETIME_PERSISTENT, lifetime, "Key lifetime mismatch");
107 }
108 
custom_psa_set_key_usage_flags(psa_key_attributes_t * attributes,psa_key_usage_t usage_flags)109 void custom_psa_set_key_usage_flags(psa_key_attributes_t *attributes, psa_key_usage_t usage_flags)
110 {
111 	zassert_equal(PSA_KEY_USAGE_EXPORT, usage_flags, "Key usage flags mismatch");
112 }
113 
wifi_credentials_backend_psa_setup(void * _unused)114 static void wifi_credentials_backend_psa_setup(void *_unused)
115 {
116 	RESET_FAKE(wifi_credentials_cache_ssid);
117 	RESET_FAKE(psa_export_key);
118 	RESET_FAKE(psa_import_key);
119 	RESET_FAKE(psa_destroy_key);
120 	psa_export_key_fake.custom_fake = custom_psa_export_key;
121 	psa_set_key_id_fake.custom_fake = custom_psa_set_key_id;
122 	psa_set_key_usage_flags_fake.custom_fake = custom_psa_set_key_usage_flags;
123 	psa_set_key_lifetime_fake.custom_fake = custom_psa_set_key_lifetime;
124 	psa_set_key_algorithm_fake.custom_fake = custom_psa_set_key_algorithm;
125 	psa_set_key_type_fake.custom_fake = custom_psa_set_key_type;
126 	psa_set_key_bits_fake.custom_fake = custom_psa_set_key_bits;
127 	idx = 0;
128 }
129 
ZTEST(wifi_credentials_backend_psa,test_init)130 ZTEST(wifi_credentials_backend_psa, test_init)
131 {
132 	int ret;
133 
134 	ret = wifi_credentials_backend_init();
135 
136 	zassert_equal(0, ret, "Initialization failed");
137 	zassert_equal(psa_export_key_fake.call_count, CONFIG_WIFI_CREDENTIALS_MAX_ENTRIES,
138 		      "Export key call count mismatch");
139 	zassert_equal(wifi_credentials_cache_ssid_fake.call_count,
140 		      CONFIG_WIFI_CREDENTIALS_MAX_ENTRIES, "Cache SSID call count mismatch");
141 }
142 
ZTEST(wifi_credentials_backend_psa,test_add)143 ZTEST(wifi_credentials_backend_psa, test_add)
144 {
145 	int ret = wifi_credentials_store_entry(idx, &example1,
146 					       sizeof(struct wifi_credentials_personal));
147 
148 	zassert_equal(0, ret, "Store entry failed");
149 	zassert_equal_ptr(psa_import_key_fake.arg1_val, &example1, "Import key arg1 mismatch");
150 	zassert_equal(psa_import_key_fake.arg2_val, sizeof(struct wifi_credentials_personal),
151 		      "Import key arg2 mismatch");
152 
153 	idx++;
154 
155 	ret = wifi_credentials_store_entry(idx, &example2,
156 					   sizeof(struct wifi_credentials_personal));
157 
158 	zassert_equal(0, ret, "Store entry failed");
159 	zassert_equal_ptr(psa_import_key_fake.arg1_val, &example2, "Import key arg1 mismatch");
160 	zassert_equal(psa_import_key_fake.arg2_val, sizeof(struct wifi_credentials_personal),
161 		      "Import key arg2 mismatch");
162 
163 	zassert_equal(psa_import_key_fake.call_count, 2, "Import key call count mismatch");
164 	zassert_equal(psa_set_key_id_fake.call_count, 2, "Set key ID call count mismatch");
165 	zassert_equal(psa_set_key_usage_flags_fake.call_count, 2,
166 		      "Set key usage flags call count mismatch");
167 	zassert_equal(psa_set_key_lifetime_fake.call_count, 2,
168 		      "Set key lifetime call count mismatch");
169 	zassert_equal(psa_set_key_algorithm_fake.call_count, 2,
170 		      "Set key algorithm call count mismatch");
171 	zassert_equal(psa_set_key_type_fake.call_count, 2, "Set key type call count mismatch");
172 	zassert_equal(psa_set_key_bits_fake.call_count, 2, "Set key bits call count mismatch");
173 }
174 
ZTEST(wifi_credentials_backend_psa,test_get)175 ZTEST(wifi_credentials_backend_psa, test_get)
176 {
177 	int ret;
178 	psa_key_id_t key_id = idx + WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN;
179 	uint8_t buf[ENTRY_MAX_LEN];
180 
181 	ret = wifi_credentials_load_entry(idx, buf, ARRAY_SIZE(buf));
182 
183 	zassert_equal(0, ret, "Load entry failed");
184 	zassert_equal(psa_export_key_fake.arg0_val, key_id, "Export key arg0 mismatch");
185 	zassert_equal_ptr(psa_export_key_fake.arg1_val, buf, "Export key arg1 mismatch");
186 	zassert_equal(psa_export_key_fake.arg2_val, ARRAY_SIZE(buf), "Export key arg2 mismatch");
187 
188 	idx++;
189 	key_id = idx + WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN;
190 
191 	ret = wifi_credentials_load_entry(idx, buf, ARRAY_SIZE(buf));
192 
193 	zassert_equal(0, ret, "Load entry failed");
194 	zassert_equal(psa_export_key_fake.arg0_val, key_id, "Export key arg0 mismatch");
195 	zassert_equal_ptr(psa_export_key_fake.arg1_val, buf, "Export key arg1 mismatch");
196 	zassert_equal(psa_export_key_fake.arg2_val, ARRAY_SIZE(buf), "Export key arg2 mismatch");
197 
198 	zassert_equal(psa_export_key_fake.call_count, 2, "Export key call count mismatch");
199 }
200 
ZTEST(wifi_credentials_backend_psa,test_delete)201 ZTEST(wifi_credentials_backend_psa, test_delete)
202 {
203 	int ret;
204 
205 	ret = wifi_credentials_delete_entry(idx);
206 
207 	zassert_equal(0, ret, "Delete entry failed");
208 	zassert_equal(psa_destroy_key_fake.arg0_val, WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN,
209 		      "Destroy key arg0 mismatch");
210 
211 	idx++;
212 
213 	ret = wifi_credentials_delete_entry(1);
214 
215 	zassert_equal(0, ret, "Delete entry failed");
216 	zassert_equal(psa_destroy_key_fake.arg0_val,
217 		      idx + WIFI_CREDENTIALS_BACKEND_PSA_KEY_ID_USER_MIN,
218 		      "Destroy key arg0 mismatch");
219 
220 	zassert_equal(psa_destroy_key_fake.call_count, 2, "Destroy key call count mismatch");
221 }
222 
223 ZTEST_SUITE(wifi_credentials_backend_psa, NULL, NULL, wifi_credentials_backend_psa_setup, NULL,
224 	    NULL);
225