Deny signed file without root CA 55/235255/1
authorKichan Kwon <k_c.kwon@samsung.com>
Wed, 3 Jun 2020 06:00:47 +0000 (15:00 +0900)
committerKichan Kwon <k_c.kwon@samsung.com>
Wed, 3 Jun 2020 06:19:48 +0000 (15:19 +0900)
- Signed file + Root CA : try to verify
- Unsigned file + Root CA : deny
- Only signed file : deny
- Only unsigned file : skip

Change-Id: I8a8e8eae0fee75396bd7c16a12027f295d084dcd
Signed-off-by: Kichan Kwon <k_c.kwon@samsung.com>
upg-verifier/upg-verifier.c
upg-verifier/upg-verifier.h

index bb641ae42805a956e08dcf2bc5381751445c54f0..c73de82ae767aa62707cd8d9eb451eb81b9eb9a1 100644 (file)
@@ -2,6 +2,7 @@
 #include <fcntl.h>
 #include <openssl/err.h>
 #include <openssl/x509.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
  */
 #define CA_FILE TZ_SYS_RO_SHARE "/cert/tota_root_ca.pem"
 
-#ifdef LOG_FILE
-static void close_fd(int *fd)
-{
-       if (fd && *fd >= 0)
-               close(*fd);
-}
-#endif
-
 static int check_argument(int argc, char *argv[])
 {
        _D("The number of argument : %d", argc);
@@ -31,36 +24,36 @@ static int check_argument(int argc, char *argv[])
        return SUCCEED;
 }
 
-static int signed_file_fd = -1;
 static struct signed_file signed_file;
 
-static int read_signed_file(const char *path)
+static bool check_signed_file(const char *path)
 {
+       const int metadata_size = sizeof(signed_file.delta_size) + sizeof(signed_file.signature_size) + sizeof(signed_file.certificate_size) + MAGIC_NUMBER_SIZE;
        int ret = -1;
+       _CLEANUP_CLOSE_ int signed_file_fd = -1;
        off_t offset = (off_t)-1;
        unsigned int data_size = 0;
-       const int metadata_size = sizeof(signed_file.delta_size) + sizeof(signed_file.signature_size) + sizeof(signed_file.certificate_size) + MAGIC_NUMBER_SIZE;
 
-       _I("Read signed file...");
+       _I("Check signed file...");
 
        ASSERT_RETV(path, EINVAL, "Invalid parameter");
        _D("Signed file path : %s", path);
 
        signed_file_fd = open(path, O_RDONLY);
-       ASSERT_RETV(signed_file_fd > 0, errno, "Failed to open %s : %m", path);
+       ASSERT_RETV(signed_file_fd > 0, false, "Failed to open %s : %m", path);
 
        // Read metadata
        offset = lseek(signed_file_fd, -metadata_size, SEEK_END);
-       ASSERT_RETV(offset != (off_t)-1, errno, "Failed to move file offset : %m");
+       ASSERT_RETV(offset != (off_t)-1, false, "Failed to move file offset : %m");
 
        ret = read(signed_file_fd, &signed_file.delta_size, metadata_size);
-       ASSERT_RETV(ret == metadata_size, errno, "Failed to read metadata : %m");
+       ASSERT_RETV(ret == metadata_size, false, "Failed to read metadata : %m");
 
        // Check magic number
        _D("Magic number : %s", signed_file.magic_number);
 
        ret = memcmp(signed_file.magic_number, MAGIC_NUMBER, MAGIC_NUMBER_SIZE);
-       ASSERT_RETV(ret == 0, ENODATA, "Invalid magic number");
+       ASSERT_RETV(ret == 0, false, "Invalid magic number");
 
        // Check file size
        _D("Delta size : %d", signed_file.delta_size);
@@ -70,12 +63,26 @@ static int read_signed_file(const char *path)
        data_size = signed_file.delta_size + signed_file.signature_size + signed_file.certificate_size;
 
        offset = lseek(signed_file_fd, -metadata_size, SEEK_END);
-       ASSERT_RETV(offset == data_size, offset, "Invalid file size : Expected(%u), Real(%llu)", data_size, offset);
+       ASSERT_RETV(offset == data_size, false, "Invalid file size : Expected(%u), Real(%llu)", data_size, offset);
 
-       // Read data
-       offset = lseek(signed_file_fd, 0, SEEK_SET);
-       ASSERT_RETV(offset != (off_t)-1, errno, "Failed to move file offset : %m");
+       return true;
+}
+
+static int read_signed_file(const char *path)
+{
+       int ret = -1;
+       _CLEANUP_CLOSE_ int signed_file_fd = -1;
+       off_t offset = (off_t)-1;
+
+       _I("Read signed file...");
 
+       ASSERT_RETV(path, EINVAL, "Invalid parameter");
+       _D("Signed file path : %s", path);
+
+       signed_file_fd = open(path, O_RDONLY);
+       ASSERT_RETV(signed_file_fd > 0, errno, "Failed to open %s : %m", path);
+
+       // Read data
        signed_file.delta = malloc(signed_file.delta_size);
        ASSERT_RETV(signed_file.delta, ENOMEM, "Not enough memory");
 
@@ -189,9 +196,6 @@ static int free_data(int ret)
 {
        _I("Free data...");
 
-       if (signed_file_fd >= 0)
-               close(signed_file_fd);
-
        if (signed_file.delta)
                free(signed_file.delta);
 
@@ -219,9 +223,11 @@ static int free_data(int ret)
 int main(int argc, char *argv[])
 {
        int ret;
+       bool is_signed_file;
+       bool has_root_ca;
 
 #ifdef LOG_FILE
-       __attribute__ ((__cleanup__(close_fd))) int log_fd;
+       _CLEANUP_CLOSE_ int log_fd;
 
        log_fd = open("/opt/var/log/last_uv.log", O_WRONLY | O_CREAT, 0644);
        ASSERT_RETV(log_fd >= 0, errno, "Failed to open log file fd : %m");
@@ -232,23 +238,32 @@ int main(int argc, char *argv[])
 
        _I("Start to verify upg");
 
-       /**
-        * We have to skip verification without root CA
-        * because TOTA root CA not exists in the public image.
-        *
-        * To verify upg, you must insert root CA.
-        */
-       _D("CA file : %s", CA_FILE);
-       if (access(CA_FILE, F_OK) != 0) {
-               _W("Root CA not exist. Skip verification");
-               return SUCCEED;
-       }
-
        ret = check_argument(argc, argv);
        ASSERT_RETV(ret == SUCCEED, EINVAL, "Failed to check argument (%d)", ret);
 
+       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;
+
+       _D("Signed(%d), Root CA(%d)", is_signed_file, has_root_ca);
+       if (is_signed_file) {
+               if (!has_root_ca) {
+                       _E("Root CA not exist");
+                       return EPERM;
+               }
+       } else {
+               if (has_root_ca) {
+                       _E("%s isn't signed file", argv[1]);
+                       return EPERM;
+               } else {
+                       _W("Skip verification");
+                       return SUCCEED;
+               }
+       }
+
        ret = read_signed_file(argv[1]);
-       ASSERT_RETV(ret == SUCCEED, free_data(ret), "Failed to read signed file (%d)", ret);
+       ASSERT_RETV(ret == SUCCEED, free_data(ret), "Failed to read data (%d)", ret);
 
        ret = verify_certificate();
        ASSERT_RETV(ret == SUCCEED, free_data(ret), "Failed to verify certificate (%d)", ret);
index 09577c43769341903f8ccd5127abc90a33af3525..b2e9c5c81c4b8a2bac6cf17deba10134b180ed09 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __UPG_VERIFIER_H__
 #define __UPG_VERIFIER_H__
 
+#include <unistd.h>
+
 //#define LOG_STDOUT
 #define LOG_FILE
 
        }       \
 }
 
+static void close_fd(int *fd)
+{
+       if (fd && *fd >= 0)
+               close(*fd);
+}
+
+#define _CLEANUP_CLOSE_ __attribute__((__cleanup__(close_fd)))
+
 #define MAGIC_NUMBER "TOTA_SIGNED_V1"
 #define MAGIC_NUMBER_SIZE (sizeof(MAGIC_NUMBER) - 1)