// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2018, Linaro Limited */ #include "xtest_test.h" #include "xtest_helpers.h" #include #include #include #include #include #include #include #include #include #ifdef OPENSSL_FOUND #include #include #include #include #endif #include "regression_8100_ca_crt.h" #include "regression_8100_mid_crt.h" #include "regression_8100_my_crt.h" #include "regression_8100_my_csr.h" #ifdef CFG_TA_MBEDTLS static void test_8101(ADBG_Case_t *c __maybe_unused) { #ifdef CFG_TA_MBEDTLS_SELF_TEST TEEC_Session session = { }; uint32_t ret_orig = 0; if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( &session, &crypt_user_ta_uuid, NULL, &ret_orig))) return; ADBG_EXPECT_TEEC_SUCCESS(c, TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_SELF_TESTS, NULL, &ret_orig)); TEEC_CloseSession(&session); #else Do_ADBG_Log("CFG_TA_MBEDTLS_SELF_TEST not set, test skipped"); #endif } ADBG_CASE_DEFINE(regression, 8101, test_8101, "TA mbedTLS self tests"); static int __printf(2, 3) myasprintf(char **strp, const char *fmt, ...) { char *str = NULL; int rc = 0; va_list ap; va_start(ap, fmt); rc = vsnprintf(str, rc, fmt, ap); va_end(ap); if (rc <= 0) goto out; str = malloc(rc); if (!str) { rc = -1; goto out; } va_start(ap, fmt); rc = vsnprintf(str, rc, fmt, ap); va_end(ap); if (rc <= 0) free(str); else *strp = str; out: return rc; } static void test_8102(ADBG_Case_t *c) { TEEC_Session session = { }; TEEC_Operation op = TEEC_OPERATION_INITIALIZER; uint32_t ret_orig = 0; char *chain = NULL; int clen = 0; char *trust = NULL; int tlen = 0; if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( &session, &crypt_user_ta_uuid, NULL, &ret_orig))) return; clen = myasprintf(&chain, "%*s\n%*s", (int)regression_8100_my_crt_size, regression_8100_my_crt, (int)regression_8100_mid_crt_size, regression_8100_mid_crt); if (!ADBG_EXPECT_COMPARE_SIGNED(c, clen, !=, -1)) goto out; tlen = myasprintf(&trust, "%*s", (int)regression_8100_ca_crt_size, regression_8100_ca_crt); if (!ADBG_EXPECT_COMPARE_SIGNED(c, tlen, !=, -1)) goto out; op.params[0].tmpref.buffer = chain; op.params[0].tmpref.size = clen; op.params[1].tmpref.buffer = trust; op.params[1].tmpref.size = tlen; op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE); ADBG_EXPECT_TEEC_SUCCESS(c, TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_CHECK_CERT, &op, &ret_orig)); out: free(chain); free(trust); TEEC_CloseSession(&session); } ADBG_CASE_DEFINE(regression, 8102, test_8102, "TA mbedTLS test cert chain"); #ifdef OPENSSL_FOUND static void osslerr(void) { while (true) { unsigned long e = 0; char b[256] = { }; const char *f = NULL; int l = 0; e = ERR_get_error_line(&f, &l); if (!e) return; ERR_error_string_n(e, b, sizeof(b)); Do_ADBG_Log("%s:%d \"%s\"", f, l, b); } } static bool get_cert(ADBG_Case_t *c, const char *crt_str, X509 **crt) { bool ret = false; size_t slen = strlen(crt_str) + 1; BIO *buf = BIO_new(BIO_s_mem()); size_t b = 0; if (!ADBG_EXPECT_NOT_NULL(c, buf)) goto out; b = BIO_write(buf, crt_str, slen); if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, b, ==, slen)) goto out; if (!PEM_read_bio_X509(buf, crt, 0, NULL)) goto out; ret = true; out: if (!ret) osslerr(); BIO_free(buf); return ret; } static bool push_cert(ADBG_Case_t *c, const char *crt_str, STACK_OF(X509) *cs) { X509 *crt = NULL; int rc = 0; if (!get_cert(c, crt_str, &crt)) return false; rc = sk_X509_push(cs, crt); if (!ADBG_EXPECT_COMPARE_SIGNED(c, rc, >, 0)) { osslerr(); X509_free(crt); return false; } return true; } static bool check(ADBG_Case_t *c, STACK_OF(X509) *trusted, STACK_OF(X509) *untrusted, X509 *crt) { bool ret = false; X509_STORE *store = NULL; X509_STORE_CTX *csc = NULL; X509_VERIFY_PARAM *pm = NULL; int i = 0; time_t vfy_time = 0; pm = X509_VERIFY_PARAM_new(); vfy_time = 1526898005; /* Mon, 21 May 2018 10:20:05 +0000 */ X509_VERIFY_PARAM_set_time(pm, vfy_time); store = X509_STORE_new(); if (!ADBG_EXPECT_NOT_NULL(c, store)) goto out; X509_STORE_set_flags(store, 0); if (!ADBG_EXPECT_TRUE(c, X509_STORE_set1_param(store, pm))) goto out; csc = X509_STORE_CTX_new(); if (!ADBG_EXPECT_NOT_NULL(c, csc)) goto out; if (!ADBG_EXPECT_TRUE(c, X509_STORE_CTX_init(csc, store, crt, untrusted))) goto out; X509_STORE_CTX_trusted_stack(csc, trusted); i = X509_verify_cert(csc); if (!ADBG_EXPECT_COMPARE_SIGNED(c, i, >, 0)) goto out; i = X509_STORE_CTX_get_error(csc); if (!ADBG_EXPECT_COMPARE_SIGNED(c, i, ==, X509_V_OK)) goto out; ret = true; out: if (!ret) osslerr(); X509_VERIFY_PARAM_free(pm); X509_STORE_free(store); X509_STORE_CTX_free(csc); return ret; } static bool verify_cert(ADBG_Case_t *c, const char *ca, const char *mid, const char *cert) { bool ret = false; STACK_OF(X509) *trusted = NULL; STACK_OF(X509) *untrusted = NULL; X509 *crt = NULL; trusted = sk_X509_new_null(); if (!ADBG_EXPECT_NOT_NULL(c, trusted)) goto out; untrusted = sk_X509_new_null(); if (!ADBG_EXPECT_NOT_NULL(c, untrusted)) goto out; if (!ADBG_EXPECT_TRUE(c, get_cert(c, cert, &crt))) goto out; if (!ADBG_EXPECT_TRUE(c, push_cert(c, mid, untrusted))) goto out; if (!ADBG_EXPECT_TRUE(c, push_cert(c, ca, trusted))) goto out; ret = ADBG_EXPECT_TRUE(c, check(c, trusted, untrusted, crt)); out: if (!ret) osslerr(); X509_free(crt); sk_X509_pop_free(untrusted, X509_free); sk_X509_pop_free(trusted, X509_free); return ret; } #else /*!OPENSSL_FOUND*/ static bool verify_cert(ADBG_Case_t *c, const char *ca, const char *mid, const char *cert) { UNUSED(c); UNUSED(ca); UNUSED(mid); UNUSED(cert); Do_ADBG_Log("OpenSSL not available, skipping certificate verification"); return true; } #endif static void test_8103(ADBG_Case_t *c) { TEEC_Result res = TEEC_ERROR_GENERIC; TEEC_Session session = { }; TEEC_Operation op = TEEC_OPERATION_INITIALIZER; uint32_t ret_orig = 0; char *csr = NULL; int clen = 0; char cert[2048]; char chain[4096]; char *ca = NULL; if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( &session, &crypt_user_ta_uuid, NULL, &ret_orig))) return; clen = myasprintf(&csr, "%*s", (int)regression_8100_my_csr_size, regression_8100_my_csr); if (!ADBG_EXPECT_COMPARE_SIGNED(c, clen, >=, 0)) goto out; op.params[0].tmpref.buffer = csr; op.params[0].tmpref.size = clen; op.params[1].tmpref.buffer = cert; op.params[1].tmpref.size = sizeof(cert); op.params[2].tmpref.buffer = chain; op.params[2].tmpref.size = sizeof(chain); op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); res = TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_SIGN_CERT, &op, &ret_orig); if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) goto out; myasprintf(&ca, "%*s", (int)regression_8100_ca_crt_size, regression_8100_ca_crt); if (!ADBG_EXPECT_NOT_NULL(c, ca)) goto out; verify_cert(c, ca, op.params[2].tmpref.buffer, op.params[1].tmpref.buffer); out: free(ca); free(csr); TEEC_CloseSession(&session); } ADBG_CASE_DEFINE(regression, 8103, test_8103, "TA mbedTLS process certificate request"); #endif /*CFG_TA_MBEDTLS*/