From 19e10a403bb74769ed6e8b98bcb7028dedab8d69 Mon Sep 17 00:00:00 2001 From: Kichan Kwon Date: Mon, 24 Aug 2020 14:58:49 +0900 Subject: [PATCH] Verify image with all root CAs - Each signer can use their own root CA - Root CA dir : TZ_SYS_RO_CA_DIR/img-verifier - TZ_SYS_RO_CA_DIR is defined in ca-certificates Change-Id: I4175957a24851af242836b96b6e7d4ac76cb8f77 Signed-off-by: Kichan Kwon --- img-verifier/CMakeLists.txt | 2 +- img-verifier/img-verifier.c | 79 +++++++++++++++++++++++++++++---------------- img-verifier/img-verifier.h | 7 ++++ packaging/tota-ua.spec | 9 +++--- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/img-verifier/CMakeLists.txt b/img-verifier/CMakeLists.txt index 4336f3c..7ad3158 100755 --- a/img-verifier/CMakeLists.txt +++ b/img-verifier/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -ADD_DEFINITIONS("-DTOTA_CA_DIR=\"${TOTA_CA_DIR}\"") +ADD_DEFINITIONS("-DIMG_VERIFIER_ROOT_CA_DIR=\"${IMG_VERIFIER_ROOT_CA_DIR}\"") SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(SBINDIR "${PREFIX}/sbin") diff --git a/img-verifier/img-verifier.c b/img-verifier/img-verifier.c index af12e68..042884e 100644 --- a/img-verifier/img-verifier.c +++ b/img-verifier/img-verifier.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -10,12 +11,6 @@ #include "img-verifier.h" -/** - * You must install CA_FILE in the RO section - * to prevent manipulation. - */ -#define CA_FILE TOTA_CA_DIR "/tota_root_ca.pem" - static int check_argument(int argc, char *argv[]) { _D("The number of argument : %d", argc); @@ -68,6 +63,50 @@ static bool check_signed_file(const char *path) return true; } +static int print_openssl_error(void) +{ + unsigned long err = ERR_get_error(); + + _E("OpenSSL error : %s", ERR_error_string(err, NULL)); + + return -EIO; +} + +static X509_STORE *x509_store; + +static int read_root_ca(void) +{ + int ret; + int num_root_ca = 0; + _CLEANUP_DIR_ DIR *dirp = NULL; + struct dirent *dirent = NULL; + const char *ext = NULL; + char root_ca_path[PATH_MAX]; + + _I("Read root CA..."); + + dirp = opendir(IMG_VERIFIER_ROOT_CA_DIR); + ASSERT_RETV(dirp, -errno, "Failed to open %s : %m", IMG_VERIFIER_ROOT_CA_DIR); + + x509_store = X509_STORE_new(); + ASSERT_RETV(x509_store, -ENOMEM, "X509_STORE_new failed"); + + _D("Root CA directory : %s", IMG_VERIFIER_ROOT_CA_DIR); + while ((dirent = readdir(dirp))) { + if ((ext = strrchr(dirent->d_name, '.')) && !strncmp(ext + 1, "pem", 4)) { + snprintf(root_ca_path, sizeof(root_ca_path), "%s/%s", + IMG_VERIFIER_ROOT_CA_DIR, dirent->d_name); + _D("Find root CA : %s", dirent->d_name); + ret = X509_STORE_load_locations(x509_store, root_ca_path, NULL); + ASSERT_RETV(ret == 1, print_openssl_error(), + "X509_STORE_load_locations for %s failed", root_ca_path); + ++num_root_ca; + } + } + + return num_root_ca; +} + static int read_signed_file(const char *path) { int ret = -1; @@ -103,17 +142,7 @@ static int read_signed_file(const char *path) return SUCCEED; } -static int print_openssl_error(void) -{ - unsigned long err = ERR_get_error(); - - _E("OpenSSL error : %s", ERR_error_string(err, NULL)); - - return EIO; -} - static X509 *x509; -static X509_STORE *x509_store; static X509_STORE_CTX *x509_store_ctx; static int verify_certificate(void) @@ -129,12 +158,6 @@ static int verify_certificate(void) x509 = d2i_X509(NULL, (const unsigned char **)&pcert, signed_file.certificate_size); ASSERT_RETV(x509, print_openssl_error(), "d2i_X509 failed"); - x509_store = X509_STORE_new(); - ASSERT_RETV(x509_store, ENOMEM, "X509_STORE_new failed"); - - ret = X509_STORE_load_locations(x509_store, CA_FILE, NULL); - ASSERT_RETV(ret == 1, print_openssl_error(), "X509_STORE_load_locations failed"); - x509_store_ctx = X509_STORE_CTX_new(); ASSERT_RETV(x509_store_ctx, ENOMEM, "X509_STORE_CTX_new failed"); @@ -225,7 +248,7 @@ int main(int argc, char *argv[]) { int ret; bool is_signed_file; - bool has_root_ca; + int num_root_ca; #ifdef LOG_FILE _CLEANUP_CLOSE_ int log_fd; @@ -244,8 +267,8 @@ int main(int argc, char *argv[]) is_signed_file = check_signed_file(argv[1]); - _D("CA file : %s", CA_FILE); - has_root_ca = (access(CA_FILE, F_OK) == 0) ? true : false; + num_root_ca = read_root_ca(); + ASSERT_RETV(num_root_ca >= 0, free_data(num_root_ca), "Failed to read root CA (%d)", num_root_ca); /** * Root CA / Signed File | Action @@ -255,14 +278,14 @@ int main(int argc, char *argv[]) * O X | Deny * O O | Try to verify */ - _D("Signed(%d), Root CA(%d)", is_signed_file, has_root_ca); + _D("Signed(%d), Root CA(%d)", is_signed_file, num_root_ca); if (is_signed_file) { - if (!has_root_ca) { + if (num_root_ca <= 0) { _E("Root CA not exist"); return EPERM; } } else { - if (has_root_ca) { + if (num_root_ca > 0) { _E("%s isn't signed file", argv[1]); return EPERM; } else { diff --git a/img-verifier/img-verifier.h b/img-verifier/img-verifier.h index ae60de1..34df4cf 100644 --- a/img-verifier/img-verifier.h +++ b/img-verifier/img-verifier.h @@ -36,7 +36,14 @@ static void close_fd(int *fd) close(*fd); } +static void close_dir(DIR **dirp) +{ + if (dirp && *dirp) + closedir(*dirp); +} + #define _CLEANUP_CLOSE_ __attribute__((__cleanup__(close_fd))) +#define _CLEANUP_DIR_ __attribute__((__cleanup__(close_dir))) #define MAGIC_NUMBER "IMG_SIGNED_V1" #define MAGIC_NUMBER_SIZE (sizeof(MAGIC_NUMBER) - 1) diff --git a/packaging/tota-ua.spec b/packaging/tota-ua.spec index 7137a24..a390178 100755 --- a/packaging/tota-ua.spec +++ b/packaging/tota-ua.spec @@ -30,14 +30,15 @@ LDFLAGS="$LDFLAGS" %define system_bus_services_dir /usr/share/dbus-1/system-services %define systemd_dbus_conf_dir /etc/dbus-1/system.d -%define tota_ca_dir %{TZ_SYS_RO_CA_DIR}/tota +# You must set CA directory in the RO section to prevent manipulation +%define img_verifier_root_ca_dir %{TZ_SYS_RO_CA_DIR}/img-verifier %define tota_ua_list_dir %{_datadir}/initrd-recovery/initrd.list.d %cmake \ -DCMAKE_INSTALL_PREFIX=%{_prefix} \ -DSYSTEM_BUS_SERVICES_DIR=%{system_bus_services_dir} \ -DSYSTEMD_DBUS_CONF_DIR=%{systemd_dbus_conf_dir} \ - -DTOTA_CA_DIR=%{tota_ca_dir} \ + -DIMG_VERIFIER_ROOT_CA_DIR=%{img_verifier_root_ca_dir} \ -DTOTA_UA_LIB_DIR=%{_libdir} \ -DTOTA_UA_LIST_DIR=%{tota_ua_list_dir} \ -DTOTA_UA_SCRIPTS_DIR=scripts @@ -52,7 +53,7 @@ cp scripts/40-tota-ua.list %{buildroot}%{tota_ua_list_dir}/40-tota-ua.list install -m 755 scripts/upgrade-trigger.sh %{buildroot}%{_bindir} %define fota_dir /opt/usr/data/fota mkdir -p %{buildroot}%{fota_dir} -mkdir -p %{buildroot}%{tota_ca_dir} +mkdir -p %{buildroot}%{img_verifier_root_ca_dir} %post @@ -66,4 +67,4 @@ mkdir -p %{buildroot}%{tota_ca_dir} %{_bindir}/upgrade-trigger.sh %attr(700,-,-) %{tota_ua_list_dir}/40-tota-ua.list %{_sbindir}/img-verifier -%attr(755,root,root) %{tota_ca_dir} +%attr(755,root,root) %{img_verifier_root_ca_dir} -- 2.7.4