1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018, Linaro Limited */
3 
4 #include "xtest_test.h"
5 #include "xtest_helpers.h"
6 
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ta_crypt.h>
12 #include <tee_api_defines.h>
13 #include <tee_api_types.h>
14 #include <tee_api_compat.h>
15 #include <adbg.h>
16 
17 #ifdef OPENSSL_FOUND
18 #include <openssl/x509_vfy.h>
19 #include <openssl/pem.h>
20 #include <openssl/err.h>
21 #include <openssl/crypto.h>
22 #endif
23 
24 #include "regression_8100_ca_crt.h"
25 #include "regression_8100_mid_crt.h"
26 #include "regression_8100_my_crt.h"
27 #include "regression_8100_my_csr.h"
28 
29 #ifdef CFG_TA_MBEDTLS
30 
test_8101(ADBG_Case_t * c __maybe_unused)31 static void test_8101(ADBG_Case_t *c __maybe_unused)
32 {
33 #ifdef CFG_TA_MBEDTLS_SELF_TEST
34 	TEEC_Session session = { };
35 	uint32_t ret_orig = 0;
36 
37 	if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
38 					      &session, &crypt_user_ta_uuid,
39 					      NULL, &ret_orig)))
40 		return;
41 	ADBG_EXPECT_TEEC_SUCCESS(c,
42 		TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_SELF_TESTS,
43 				   NULL, &ret_orig));
44 	TEEC_CloseSession(&session);
45 #else
46 	Do_ADBG_Log("CFG_TA_MBEDTLS_SELF_TEST not set, test skipped");
47 #endif
48 }
49 ADBG_CASE_DEFINE(regression, 8101, test_8101, "TA mbedTLS self tests");
50 
myasprintf(char ** strp,const char * fmt,...)51 static int __printf(2, 3) myasprintf(char **strp, const char *fmt, ...)
52 {
53 	char *str = NULL;
54 	int rc = 0;
55 	va_list ap;
56 
57 	va_start(ap, fmt);
58 	rc = vsnprintf(str, rc, fmt, ap);
59 	va_end(ap);
60 	if (rc <= 0)
61 		goto out;
62 
63 	str = malloc(rc);
64 	if (!str) {
65 		rc = -1;
66 		goto out;
67 	}
68 
69 	va_start(ap, fmt);
70 	rc = vsnprintf(str, rc, fmt, ap);
71 	va_end(ap);
72 	if (rc <= 0)
73 		free(str);
74 	else
75 		*strp = str;
76 
77 out:
78 	return rc;
79 }
80 
test_8102(ADBG_Case_t * c)81 static void test_8102(ADBG_Case_t *c)
82 {
83 	TEEC_Session session = { };
84 	TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
85 	uint32_t ret_orig = 0;
86 	char *chain = NULL;
87 	int clen = 0;
88 	char *trust = NULL;
89 	int tlen = 0;
90 
91 	if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
92 					      &session, &crypt_user_ta_uuid,
93 					      NULL, &ret_orig)))
94 		return;
95 
96 	clen = myasprintf(&chain, "%*s\n%*s",
97 			  (int)regression_8100_my_crt_size,
98 			  regression_8100_my_crt,
99 			  (int)regression_8100_mid_crt_size,
100 			   regression_8100_mid_crt);
101 	if (!ADBG_EXPECT_COMPARE_SIGNED(c, clen, !=, -1))
102 		goto out;
103 	tlen = myasprintf(&trust, "%*s", (int)regression_8100_ca_crt_size,
104 			  regression_8100_ca_crt);
105 	if (!ADBG_EXPECT_COMPARE_SIGNED(c, tlen, !=, -1))
106 		goto out;
107 
108 	op.params[0].tmpref.buffer = chain;
109 	op.params[0].tmpref.size = clen;
110 	op.params[1].tmpref.buffer = trust;
111 	op.params[1].tmpref.size = tlen;
112 	op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
113 					 TEEC_MEMREF_TEMP_INPUT,
114 					 TEEC_NONE, TEEC_NONE);
115 
116 	ADBG_EXPECT_TEEC_SUCCESS(c,
117 		TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_CHECK_CERT,
118 				   &op, &ret_orig));
119 out:
120 	free(chain);
121 	free(trust);
122 	TEEC_CloseSession(&session);
123 }
124 ADBG_CASE_DEFINE(regression, 8102, test_8102, "TA mbedTLS test cert chain");
125 
126 #ifdef OPENSSL_FOUND
osslerr(void)127 static void osslerr(void)
128 {
129 	while (true) {
130 		unsigned long e = 0;
131 		char b[256] = { };
132 		const char *f = NULL;
133 		int l = 0;
134 
135 		e = ERR_get_error_line(&f, &l);
136 		if (!e)
137 			return;
138 		ERR_error_string_n(e, b, sizeof(b));
139 		Do_ADBG_Log("%s:%d \"%s\"", f, l, b);
140 	}
141 }
142 
get_cert(ADBG_Case_t * c,const char * crt_str,X509 ** crt)143 static bool get_cert(ADBG_Case_t *c, const char *crt_str, X509 **crt)
144 {
145 	bool ret = false;
146 	size_t slen = strlen(crt_str) + 1;
147 	BIO *buf = BIO_new(BIO_s_mem());
148 	size_t b = 0;
149 
150 	if (!ADBG_EXPECT_NOT_NULL(c, buf))
151 		goto out;
152 
153 	b = BIO_write(buf, crt_str, slen);
154 	if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, b, ==, slen))
155 		goto out;
156 
157 	if (!PEM_read_bio_X509(buf, crt, 0, NULL))
158 		goto out;
159 
160 	ret = true;
161 out:
162 	if (!ret)
163 		osslerr();
164 	BIO_free(buf);
165 	return ret;
166 }
167 
push_cert(ADBG_Case_t * c,const char * crt_str,STACK_OF (X509)* cs)168 static bool push_cert(ADBG_Case_t *c, const char *crt_str, STACK_OF(X509) *cs)
169 {
170 	X509 *crt = NULL;
171 	int rc = 0;
172 
173 	if (!get_cert(c, crt_str, &crt))
174 		return false;
175 	rc = sk_X509_push(cs, crt);
176 	if (!ADBG_EXPECT_COMPARE_SIGNED(c, rc, >, 0)) {
177 		osslerr();
178 		X509_free(crt);
179 		return false;
180 	}
181 
182 	return true;
183 }
184 
check(ADBG_Case_t * c,STACK_OF (X509)* trusted,STACK_OF (X509)* untrusted,X509 * crt)185 static bool check(ADBG_Case_t *c, STACK_OF(X509) *trusted,
186 		  STACK_OF(X509) *untrusted, X509 *crt)
187 {
188 	bool ret = false;
189 	X509_STORE *store = NULL;
190 	X509_STORE_CTX *csc = NULL;
191 	X509_VERIFY_PARAM *pm = NULL;
192 	int i = 0;
193 	time_t vfy_time = 0;
194 
195 	pm = X509_VERIFY_PARAM_new();
196 	vfy_time = 1526898005; /* Mon, 21 May 2018 10:20:05 +0000 */
197 	X509_VERIFY_PARAM_set_time(pm, vfy_time);
198 
199 	store = X509_STORE_new();
200 	if (!ADBG_EXPECT_NOT_NULL(c, store))
201 		goto out;
202 	X509_STORE_set_flags(store, 0);
203 	if (!ADBG_EXPECT_TRUE(c, X509_STORE_set1_param(store, pm)))
204 		goto out;
205 
206 	csc = X509_STORE_CTX_new();
207 	if (!ADBG_EXPECT_NOT_NULL(c, csc))
208 		goto out;
209 
210 	if (!ADBG_EXPECT_TRUE(c, X509_STORE_CTX_init(csc, store, crt,
211 						     untrusted)))
212 		goto out;
213 	X509_STORE_CTX_trusted_stack(csc, trusted);
214 
215 	i = X509_verify_cert(csc);
216 	if (!ADBG_EXPECT_COMPARE_SIGNED(c, i, >, 0))
217 		goto out;
218 	i = X509_STORE_CTX_get_error(csc);
219 	if (!ADBG_EXPECT_COMPARE_SIGNED(c, i, ==, X509_V_OK))
220 		goto out;
221 	ret = true;
222 out:
223 	if (!ret)
224 		osslerr();
225 	X509_VERIFY_PARAM_free(pm);
226 	X509_STORE_free(store);
227 	X509_STORE_CTX_free(csc);
228 	return ret;
229 }
230 
verify_cert(ADBG_Case_t * c,const char * ca,const char * mid,const char * cert)231 static bool verify_cert(ADBG_Case_t *c, const char *ca, const char *mid,
232 			const char *cert)
233 {
234 	bool ret = false;
235 	STACK_OF(X509) *trusted = NULL;
236 	STACK_OF(X509) *untrusted = NULL;
237 	X509 *crt = NULL;
238 
239 	trusted = sk_X509_new_null();
240 	if (!ADBG_EXPECT_NOT_NULL(c, trusted))
241 		goto out;
242 	untrusted = sk_X509_new_null();
243 	if (!ADBG_EXPECT_NOT_NULL(c, untrusted))
244 		goto out;
245 
246 	if (!ADBG_EXPECT_TRUE(c, get_cert(c, cert, &crt)))
247 		goto out;
248 	if (!ADBG_EXPECT_TRUE(c, push_cert(c, mid, untrusted)))
249 		goto out;
250 	if (!ADBG_EXPECT_TRUE(c, push_cert(c, ca, trusted)))
251 		goto out;
252 
253 	ret = ADBG_EXPECT_TRUE(c, check(c, trusted, untrusted, crt));
254 out:
255 	if (!ret)
256 		osslerr();
257 	X509_free(crt);
258 	sk_X509_pop_free(untrusted, X509_free);
259 	sk_X509_pop_free(trusted, X509_free);
260 	return ret;
261 }
262 #else /*!OPENSSL_FOUND*/
verify_cert(ADBG_Case_t * c,const char * ca,const char * mid,const char * cert)263 static bool verify_cert(ADBG_Case_t *c, const char *ca,
264 			const char *mid, const char *cert)
265 {
266 	UNUSED(c);
267 	UNUSED(ca);
268 	UNUSED(mid);
269 	UNUSED(cert);
270 	Do_ADBG_Log("OpenSSL not available, skipping certificate verification");
271 	return true;
272 }
273 #endif
274 
test_8103(ADBG_Case_t * c)275 static void test_8103(ADBG_Case_t *c)
276 {
277 	TEEC_Result res = TEEC_ERROR_GENERIC;
278 	TEEC_Session session = { };
279 	TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
280 	uint32_t ret_orig = 0;
281 	char *csr = NULL;
282 	int clen = 0;
283 	char cert[2048];
284 	char chain[4096];
285 	char *ca = NULL;
286 
287 	if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
288 					      &session, &crypt_user_ta_uuid,
289 					      NULL, &ret_orig)))
290 		return;
291 
292 	clen = myasprintf(&csr, "%*s", (int)regression_8100_my_csr_size,
293 			  regression_8100_my_csr);
294 	if (!ADBG_EXPECT_COMPARE_SIGNED(c, clen, >=, 0))
295 		goto out;
296 	op.params[0].tmpref.buffer = csr;
297 	op.params[0].tmpref.size = clen;
298 	op.params[1].tmpref.buffer = cert;
299 	op.params[1].tmpref.size = sizeof(cert);
300 	op.params[2].tmpref.buffer = chain;
301 	op.params[2].tmpref.size = sizeof(chain);
302 	op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
303 					 TEEC_MEMREF_TEMP_OUTPUT,
304 					 TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE);
305 	res = TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_SIGN_CERT, &op,
306 				 &ret_orig);
307 	if (!ADBG_EXPECT_TEEC_SUCCESS(c, res))
308 		goto out;
309 
310 	myasprintf(&ca, "%*s", (int)regression_8100_ca_crt_size,
311 		   regression_8100_ca_crt);
312 	if (!ADBG_EXPECT_NOT_NULL(c, ca))
313 		goto out;
314 	verify_cert(c, ca, op.params[2].tmpref.buffer,
315 		    op.params[1].tmpref.buffer);
316 out:
317 	free(ca);
318 	free(csr);
319 	TEEC_CloseSession(&session);
320 }
321 ADBG_CASE_DEFINE(regression, 8103, test_8103,
322 		 "TA mbedTLS process certificate request");
323 #endif /*CFG_TA_MBEDTLS*/
324