Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ccecfd2 authored by Szymon Starzycki's avatar Szymon Starzycki
Browse files

Fastbootd: flashing certification

Change-Id: I564086908942463eebee69449d484ba03effc50e
parent bc7cbfd4
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
    commands/virtual_partitions.c \
    fastbootd.c \
    protocol.c \
    secure.c \
    transport.c \
    trigger.c \
    usb_linux_client.c \
@@ -37,11 +38,12 @@ LOCAL_SRC_FILES := \

LOCAL_MODULE := fastbootd
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter -DFLASH_CERT
LOCAL_LDFLAGS := -ldl

LOCAL_SHARED_LIBRARIES := \
    libhardware \
    libcrypto \
    libhardware_legacy

LOCAL_STATIC_LIBRARIES := \
+32 −7
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@

static void cmd_boot(struct protocol_handle *phandle, const char *arg)
{
    int sz, atags_sz, new_atags_sz;
    int rv;
    unsigned kernel_actual;
    unsigned ramdisk_actual;
    unsigned second_actual;
@@ -59,9 +61,11 @@ static void cmd_boot(struct protocol_handle *phandle, const char *arg)
    void *ramdisk_ptr;
    void *second_ptr;
    struct boot_img_hdr *hdr;
    int sz, atags_sz, new_atags_sz;
    int rv;
    char *ptr = NULL, *atags_ptr = NULL, *new_atags = NULL;
    char *ptr = NULL;
    char *atags_ptr = NULL;
    char *new_atags = NULL;
    int data_fd = 0;

    D(DEBUG, "cmd_boot %s\n", arg);

    if (phandle->download_fd < 0) {
@@ -75,9 +79,18 @@ static void cmd_boot(struct protocol_handle *phandle, const char *arg)
        goto error;
    }

    sz = get_file_size(phandle->download_fd);
    // TODO: With cms we can also verify partition name included as
    // cms signed attribute
    if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
        fastboot_fail(phandle, "Access forbiden you need the certificate");
        return;
    }

    sz = get_file_size(data_fd);

    ptr = (char *) mmap(NULL, sz, PROT_READ,
                        MAP_POPULATE | MAP_PRIVATE, phandle->download_fd, 0);
                        MAP_POPULATE | MAP_PRIVATE, data_fd, 0);

    hdr = (struct boot_img_hdr *) ptr;

    if (ptr == MAP_FAILED) {
@@ -130,6 +143,7 @@ static void cmd_boot(struct protocol_handle *phandle, const char *arg)
    free(atags_ptr);
    munmap(ptr, sz);
    free(new_atags);
    close(data_fd);

    D(INFO, "Kexec going to reboot");
    reboot(LINUX_REBOOT_CMD_KEXEC);
@@ -256,6 +270,7 @@ static void cmd_flash(struct protocol_handle *phandle, const char *arg)
    char data[BOOT_MAGIC_SIZE];
    char path[PATH_MAX];
    ssize_t header_sz = 0;
    int data_fd = 0;

    D(DEBUG, "cmd_flash %s\n", arg);

@@ -273,9 +288,14 @@ static void cmd_flash(struct protocol_handle *phandle, const char *arg)
        return;
    }

    if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
        fastboot_fail(phandle, "Access forbiden you need certificate");
        return;
    }

    // TODO: Maybe its goot idea to check whether the partition is just bootable partition
    if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
        if (read_data_once(phandle->download_fd, data, BOOT_MAGIC_SIZE) < BOOT_MAGIC_SIZE) {
        if (read_data_once(data_fd, data, BOOT_MAGIC_SIZE) < BOOT_MAGIC_SIZE) {
            fastboot_fail(phandle, "incoming data read error, cannot read boot header");
            return;
        }
@@ -287,7 +307,10 @@ static void cmd_flash(struct protocol_handle *phandle, const char *arg)

    partition = flash_get_partiton(path);

    sz = get_file_size64(phandle->download_fd);
    sz = get_file_size64(data_fd);

    sz -= header_sz;

    if (sz > get_file_size64(partition)) {
        flash_close(partition);
        D(WARN, "size of file too large");
@@ -304,6 +327,8 @@ static void cmd_flash(struct protocol_handle *phandle, const char *arg)
    D(INFO, "partition '%s' updated\n", arg);

    flash_close(partition);
    close(data_fd);
    //TODO: check who is closing phandle->download_fd

    fastboot_okay(phandle, "");
}
+47 −0
Original line number Diff line number Diff line
@@ -39,6 +39,9 @@
#include "utils.h"
#include "commands/partitions.h"

#ifdef FLASH_CERT
#include "secure.h"
#endif

#define ALLOWED_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."
#define BUFFER_SIZE 1024 * 1024
@@ -112,3 +115,47 @@ int flash_write(int partition_fd, int data_fd, ssize_t size, ssize_t skip)

    return 0;
}

#ifdef FLASH_CERT

int flash_validate_certificate(int signed_fd, int *data_fd) {
    int ret = 0;
    const char *cert_path;
    X509_STORE *store = NULL;
    CMS_ContentInfo *content_info;
    BIO *content;

    cert_path = fastboot_getvar("certificate-path");
    if (!strcmp(cert_path, "")) {
        D(ERR, "could not find cert-key value in config file");
        goto finish;
    }

    store = cert_store_from_path(cert_path);
    if (store == NULL) {
        D(ERR, "unable to create certification store");
        goto finish;
    }

    if (cert_read(signed_fd, &content_info, &content)) {
        D(ERR, "reading data failed");
        goto finish;
    }

    ret = cert_verify(content, content_info, store, data_fd);
    cert_release(content, content_info);

    return ret;

finish:
    if (store != NULL)
        cert_release_store(store);

    return ret;
}

#else
int flash_validate_certificate(int signed_fd, int *data_fd) {
    return 1;
}
#endif
+2 −0
Original line number Diff line number Diff line
@@ -58,5 +58,7 @@ static inline ssize_t read_data_once(int fd, char *buffer, ssize_t size) {
    return readcount;
}

int flash_validate_certificate(int signed_fd, int *data_fd);

#endif
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include "debug.h"
#include "trigger.h"
#include "secure.h"

unsigned int debug_level = DEBUG;

@@ -36,6 +37,7 @@ int main(int argc, char **argv)
    klog_init();
    klog_set_level(6);

    cert_init_crypto();
    config_init();
    load_trigger();
    commands_init();
Loading