1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 
9 #include "tls_internal.h"
10 
11 static const char test_ca_cert[] = "Test CA certificate";
12 static const char test_server_cert[] = "Test server certificate";
13 static const char test_server_key[] = "Test server key";
14 
15 static const int invalid_tag = CONFIG_TLS_MAX_CREDENTIALS_NUMBER + 1;
16 static const int unused_tag = CONFIG_TLS_MAX_CREDENTIALS_NUMBER;
17 static const int common_tag = CONFIG_TLS_MAX_CREDENTIALS_NUMBER - 1;
18 
19 /**
20  * @brief Test test_credential_add function
21  *
22  * This test verifies the credential add operation.
23  */
test_credential_add(void)24 static void test_credential_add(void)
25 {
26 	int ret, i;
27 
28 	for (i = 0; i < CONFIG_TLS_MAX_CREDENTIALS_NUMBER - 2; i++) {
29 		ret = tls_credential_add(i, TLS_CREDENTIAL_CA_CERTIFICATE,
30 					 test_ca_cert, sizeof(test_ca_cert));
31 		zassert_equal(ret, 0, "Failed to add credential %d %d", i);
32 	}
33 
34 	/* Function should allow to add credentials of different types
35 	 * with the same tag
36 	 */
37 	ret = tls_credential_add(common_tag, TLS_CREDENTIAL_SERVER_CERTIFICATE,
38 				 test_server_cert, sizeof(test_server_cert));
39 	zassert_equal(ret, 0, "Failed to add credential %d %d",
40 		      common_tag, TLS_CREDENTIAL_SERVER_CERTIFICATE);
41 
42 	ret = tls_credential_add(common_tag, TLS_CREDENTIAL_PRIVATE_KEY,
43 				 test_server_key, sizeof(test_server_key));
44 	zassert_equal(ret, 0, "Failed to add credential %d %d",
45 		      common_tag, TLS_CREDENTIAL_PRIVATE_KEY);
46 
47 	/* Try to register another credential - should not have memory for that
48 	 */
49 	ret = tls_credential_add(unused_tag, TLS_CREDENTIAL_CA_CERTIFICATE,
50 				 test_ca_cert, sizeof(test_ca_cert));
51 	zassert_equal(ret, -ENOMEM, "Should have failed with ENOMEM");
52 
53 	/* Try to re-register with already registered tag and type */
54 	ret = tls_credential_add(common_tag, TLS_CREDENTIAL_PRIVATE_KEY,
55 				 test_server_key, sizeof(test_server_key));
56 	zassert_equal(ret, -EEXIST, "Should have failed with EEXIST");
57 }
58 
59 /**
60  * @brief Test test_credential_get function
61  *
62  * This test verifies the credential get operation.
63  */
test_credential_get(void)64 static void test_credential_get(void)
65 {
66 	char cred[64];
67 	size_t credlen;
68 	int ret;
69 
70 	/* Read existing credential */
71 	(void)memset(cred, 0, sizeof(cred));
72 	credlen = sizeof(cred);
73 	ret = tls_credential_get(common_tag, TLS_CREDENTIAL_PRIVATE_KEY,
74 				 cred, &credlen);
75 	zassert_equal(ret, 0, "Failed to read credential %d %d",
76 		      0, TLS_CREDENTIAL_CA_CERTIFICATE);
77 	ret = strcmp(cred, test_server_key);
78 	zassert_equal(ret, 0, "Invalid credential content");
79 	zassert_equal(credlen, sizeof(test_server_key),
80 		      "Invalid credential length");
81 
82 	/* Try to read non-existing credentials */
83 	credlen = sizeof(cred);
84 	ret = tls_credential_get(invalid_tag, TLS_CREDENTIAL_PSK,
85 				 cred, &credlen);
86 	zassert_equal(ret, -ENOENT, "Should have failed with ENOENT");
87 
88 	/* Try to read with too small buffer */
89 	credlen = sizeof(test_server_cert) - 1;
90 	ret = tls_credential_get(common_tag, TLS_CREDENTIAL_SERVER_CERTIFICATE,
91 				 cred, &credlen);
92 	zassert_equal(ret, -EFBIG, "Should have failed with EFBIG");
93 }
94 
95 /**
96  * @brief Test test_credential_internal_iterate function
97  *
98  * This test verifies the internal function for iterating over credentials.
99  */
test_credential_internal_iterate(void)100 static void test_credential_internal_iterate(void)
101 {
102 	struct tls_credential *cert, *key, *temp;
103 
104 	/* Non-existing credential should return NULL */
105 	key = credential_next_get(invalid_tag, NULL);
106 	zassert_is_null(key, "Should have return NULL for unknown credential");
107 
108 	/* Iterate over credentials with the same tag */
109 	cert = credential_next_get(common_tag, NULL);
110 	zassert_not_null(cert, "Should have find a credential");
111 
112 	key = credential_next_get(common_tag, cert);
113 	zassert_not_null(key, "Should have find a credential");
114 
115 	if (cert->type == TLS_CREDENTIAL_PRIVATE_KEY) {
116 		/* Function does not guarantee order of reads,
117 		 * so assume we could read key first
118 		 */
119 		temp = key;
120 		key = cert;
121 		cert = temp;
122 	}
123 
124 	zassert_equal(cert->type, TLS_CREDENTIAL_SERVER_CERTIFICATE,
125 		      "Invalid type for cert");
126 	zassert_equal(cert->tag, common_tag, "Invalid tag for cert");
127 	zassert_equal(cert->len, sizeof(test_server_cert),
128 		      "Invalid cert length");
129 	zassert_mem_equal(cert->buf, test_server_cert, sizeof(test_server_key),
130 			  "Invalid cert content");
131 
132 	zassert_equal(key->type, TLS_CREDENTIAL_PRIVATE_KEY,
133 		      "Invalid type for key");
134 	zassert_equal(key->tag, common_tag, "Invalid tag for key");
135 	zassert_equal(key->len, sizeof(test_server_key), "Invalid key length");
136 	zassert_mem_equal(key->buf, test_server_key, sizeof(test_server_key),
137 			  "Invalid key content");
138 
139 	/* Iteration after getting last credential should return NULL */
140 	key = credential_next_get(common_tag, key);
141 	zassert_is_null(key, "Should have return NULL after last credential");
142 }
143 
144 /**
145  * @brief Test test_credential_delete function
146  *
147  * This test verifies the credential delete operation.
148  */
test_credential_delete(void)149 static void test_credential_delete(void)
150 {
151 	int ret;
152 	char cred[64];
153 	size_t credlen = sizeof(cred);
154 
155 	/* Should fail if when trying to remove non-existing credential. */
156 	ret = tls_credential_delete(invalid_tag, TLS_CREDENTIAL_CA_CERTIFICATE);
157 	zassert_equal(ret, -ENOENT, "Should have failed with ENOENT");
158 
159 	/* Should remove existing credential. */
160 	ret = tls_credential_delete(common_tag, TLS_CREDENTIAL_PRIVATE_KEY);
161 	zassert_equal(ret, 0, "Failed to delete credential %d %d",
162 		      common_tag, TLS_CREDENTIAL_PRIVATE_KEY);
163 
164 	ret = tls_credential_get(common_tag, TLS_CREDENTIAL_PRIVATE_KEY,
165 				 cred, &credlen);
166 	zassert_equal(ret, -ENOENT, "Should have failed with ENOENT");
167 }
168 
ZTEST(tls_crecentials,test_tls_crecentials)169 ZTEST(tls_crecentials, test_tls_crecentials)
170 {
171 	test_credential_add();
172 	test_credential_get();
173 	test_credential_internal_iterate();
174 	test_credential_delete();
175 }
176 
177 ZTEST_SUITE(tls_crecentials, NULL, NULL, NULL, NULL, NULL);
178