Verify image with all root CAs 88/242088/2 submit/tizen/20200826.021327 submit/tizen/20200826.021413
authorKichan Kwon <k_c.kwon@samsung.com>
Mon, 24 Aug 2020 05:58:49 +0000 (14:58 +0900)
committerKichan Kwon <k_c.kwon@samsung.com>
Tue, 25 Aug 2020 01:52:36 +0000 (10:52 +0900)
- 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 <k_c.kwon@samsung.com>
img-verifier/CMakeLists.txt
img-verifier/img-verifier.c
img-verifier/img-verifier.h
packaging/tota-ua.spec

index 4336f3c..7ad3158 100755 (executable)
@@ -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")
index af12e68..042884e 100644 (file)
@@ -1,3 +1,4 @@
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <openssl/err.h>
 
 #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 {
index ae60de1..34df4cf 100644 (file)
@@ -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)
index 7137a24..a390178 100755 (executable)
@@ -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}