All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sam Protsenko <semen.protsenko@linaro.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 4/8] cmd: avb2.0: avb command for performing verification
Date: Wed, 2 May 2018 21:52:09 +0300	[thread overview]
Message-ID: <CAKaJLVtS-0-FT6zPZxrixF7hiEqTbEZyof+3eLkf5rx0CfR0ew@mail.gmail.com> (raw)
In-Reply-To: <1524662285-19617-5-git-send-email-igor.opaniuk@linaro.org>

On 25 April 2018 at 16:18, Igor Opaniuk <igor.opaniuk@linaro.org> wrote:
> Enable a "avb" command to execute Android Verified
> Boot 2.0 operations. It includes such subcommands:
>   avb init - initialize avb2 subsystem
>   avb read_rb - read rollback index
>   avb write_rb - write rollback index
>   avb is_unlocked - check device lock state
>   avb get_uuid - read and print uuid of a partition
>   avb read_part - read data from partition
>   avb read_part_hex - read data from partition and output to stdout
>   avb write_part - write data to partition
>   avb verify - run full verification chain
>
> Signed-off-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> ---
>  cmd/Kconfig  |  15 +++
>  cmd/Makefile |   3 +
>  cmd/avb.c    | 351 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 369 insertions(+)
>  create mode 100644 cmd/avb.c
>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index bc1d2f3..96695ff 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -1675,6 +1675,21 @@ config CMD_TRACE
>           for analsys (e.g. using bootchart). See doc/README.trace for full
>           details.
>
> +config CMD_AVB
> +       bool "avb - Android Verified Boot 2.0 operations"
> +       depends on LIBAVB_AB
> +       help
> +         Enables a "avb" command to perform verification of partitions using
> +         Android Verified Boot 2.0 functionality. It includes such subcommands:
> +           avb init - initialize avb2 subsystem
> +           avb read_rb - read rollback index
> +           avb write_rb - write rollback index
> +           avb is_unlocked - check device lock state
> +           avb get_uuid - read and print uuid of a partition
> +           avb read_part - read data from partition
> +           avb read_part_hex - read data from partition and output to stdout
> +           avb write_part - write data to partition
> +           avb verify - run full verification chain
>  endmenu
>
>  config CMD_UBI
> diff --git a/cmd/Makefile b/cmd/Makefile
> index c4269ac..bbf6c2a 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -151,6 +151,9 @@ obj-$(CONFIG_CMD_REGULATOR) += regulator.o
>
>  obj-$(CONFIG_CMD_BLOB) += blob.o
>
> +# Android Verified Boot 2.0
> +obj-$(CONFIG_CMD_AVB) += avb.o
> +
>  obj-$(CONFIG_X86) += x86/
>  endif # !CONFIG_SPL_BUILD
>
> diff --git a/cmd/avb.c b/cmd/avb.c
> new file mode 100644
> index 0000000..d040906
> --- /dev/null
> +++ b/cmd/avb.c
> @@ -0,0 +1,351 @@
> +
> +/*
> + * (C) Copyright 2018, Linaro Limited
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <avb_verify.h>
> +#include <command.h>
> +#include <image.h>
> +#include <malloc.h>
> +#include <mmc.h>
> +
> +#define AVB_BOOTARGS   "avb_bootargs"
> +static struct AvbOps *avb_ops;
> +
> +static const char * const requested_partitions[] = {"boot",
> +                                            "system",
> +                                            "vendor",
> +                                            NULL};
> +
> +int do_avb_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       unsigned long mmc_dev;
> +
> +       if (argc != 2)
> +               return CMD_RET_USAGE;
> +
> +       mmc_dev = simple_strtoul(argv[1], NULL, 16);
> +
> +       if (avb_ops)
> +               avb_ops_free(avb_ops);
> +
> +       avb_ops = avb_ops_alloc(mmc_dev);
> +       if (avb_ops)
> +               return CMD_RET_SUCCESS;
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +int do_avb_read_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       const char *part;
> +       s64 offset;
> +       size_t bytes, bytes_read = 0;
> +       void *buffer;
> +
> +       if (!avb_ops) {
> +               printf("AVB 2.0 is not initialized, please run 'avb init'\n");
> +               return CMD_RET_USAGE;
> +       }
> +
> +       if (argc != 5)
> +               return CMD_RET_USAGE;
> +
> +       part = argv[1];
> +       offset = simple_strtoul(argv[2], NULL, 16);
> +       bytes = simple_strtoul(argv[3], NULL, 16);
> +       buffer = (void *)simple_strtoul(argv[4], NULL, 16);

+ Simon Glass

AFAIU, to make it possible to run this command on "sandbox", you
should use map_sysmem() and friends.

> +
> +       if (avb_ops->read_from_partition(avb_ops, part, offset, bytes,
> +                                        buffer, &bytes_read) ==
> +                                        AVB_IO_RESULT_OK) {
> +               printf("Read %zu bytes\n", bytes_read);
> +               return CMD_RET_SUCCESS;
> +       }
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +int do_avb_read_part_hex(cmd_tbl_t *cmdtp, int flag, int argc,
> +                        char *const argv[])
> +{
> +       const char *part;
> +       s64 offset;
> +       size_t bytes, bytes_read = 0;
> +       char *buffer;
> +
> +       if (!avb_ops) {
> +               printf("AVB 2.0 is not initialized, please run 'avb init'\n");
> +               return CMD_RET_USAGE;
> +       }
> +
> +       if (argc != 4)
> +               return CMD_RET_USAGE;
> +
> +       part = argv[1];
> +       offset = simple_strtoul(argv[2], NULL, 16);
> +       bytes = simple_strtoul(argv[3], NULL, 16);
> +
> +       buffer = malloc(bytes);
> +       if (!buffer) {
> +               printf("Failed to tlb_allocate buffer for data\n");
> +               return CMD_RET_FAILURE;
> +       }
> +       memset(buffer, 0, bytes);
> +
> +       if (avb_ops->read_from_partition(avb_ops, part, offset, bytes, buffer,
> +                                        &bytes_read) == AVB_IO_RESULT_OK) {
> +               printf("Requested %zu, read %zu bytes\n", bytes, bytes_read);
> +               printf("Data: ");
> +               for (int i = 0; i < bytes_read; i++)
> +                       printf("%02X", buffer[i]);
> +
> +               printf("\n");
> +
> +               free(buffer);
> +               return CMD_RET_SUCCESS;
> +       }
> +
> +       free(buffer);
> +       return CMD_RET_FAILURE;
> +}
> +
> +int do_avb_write_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       const char *part;
> +       s64 offset;
> +       size_t bytes;
> +       void *buffer;
> +
> +       if (!avb_ops) {
> +               printf("AVB 2.0 is not initialized, run 'avb init' first\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       if (argc != 5)
> +               return CMD_RET_USAGE;
> +
> +       part = argv[1];
> +       offset = simple_strtoul(argv[2], NULL, 16);
> +       bytes = simple_strtoul(argv[3], NULL, 16);
> +       buffer = (void *)simple_strtoul(argv[4], NULL, 16);
> +
> +       if (avb_ops->write_to_partition(avb_ops, part, offset, bytes, buffer) ==
> +           AVB_IO_RESULT_OK) {
> +               printf("Wrote %zu bytes\n", bytes);
> +               return CMD_RET_SUCCESS;
> +       }
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +int do_avb_read_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       size_t index;
> +       u64 rb_idx;
> +
> +       if (!avb_ops) {
> +               printf("AVB 2.0 is not initialized, run 'avb init' first\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       if (argc != 2)
> +               return CMD_RET_USAGE;
> +
> +       index = (size_t)simple_strtoul(argv[1], NULL, 16);
> +
> +       if (avb_ops->read_rollback_index(avb_ops, index, &rb_idx) ==
> +           AVB_IO_RESULT_OK) {
> +               printf("Rollback index: %llu\n", rb_idx);
> +               return CMD_RET_SUCCESS;
> +       }
> +       return CMD_RET_FAILURE;
> +}
> +
> +int do_avb_write_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       size_t index;
> +       u64 rb_idx;
> +
> +       if (!avb_ops) {
> +               printf("AVB 2.0 is not initialized, run 'avb init' first\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       if (argc != 3)
> +               return CMD_RET_USAGE;
> +
> +       index = (size_t)simple_strtoul(argv[1], NULL, 16);
> +       rb_idx = simple_strtoul(argv[2], NULL, 16);
> +
> +       if (avb_ops->write_rollback_index(avb_ops, index, rb_idx) ==
> +           AVB_IO_RESULT_OK)
> +               return CMD_RET_SUCCESS;
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +int do_avb_get_uuid(cmd_tbl_t *cmdtp, int flag,
> +                   int argc, char * const argv[])
> +{
> +       const char *part;
> +       char buffer[UUID_STR_LEN + 1];
> +
> +       if (!avb_ops) {
> +               printf("AVB 2.0 is not initialized, run 'avb init' first\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       if (argc != 2)
> +               return CMD_RET_USAGE;
> +
> +       part = argv[1];
> +
> +       if (avb_ops->get_unique_guid_for_partition(avb_ops, part, buffer,
> +                                                  UUID_STR_LEN + 1) ==
> +                                                  AVB_IO_RESULT_OK) {
> +               printf("'%s' UUID: %s\n", part, buffer);
> +               return CMD_RET_SUCCESS;
> +       }
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +int do_avb_verify_part(cmd_tbl_t *cmdtp, int flag,
> +                      int argc, char *const argv[])
> +{
> +       AvbSlotVerifyResult slot_result;
> +       AvbSlotVerifyData *out_data;
> +
> +       bool unlocked = false;
> +       int res = CMD_RET_FAILURE;
> +
> +       if (!avb_ops) {
> +               printf("AVB 2.0 is not initialized, run 'avb init' first\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       if (argc != 1)
> +               return CMD_RET_USAGE;
> +
> +       printf("## Android Verified Boot 2.0 version %s\n",
> +              avb_version_string());
> +
> +       if (avb_ops->read_is_device_unlocked(avb_ops, &unlocked) !=
> +           AVB_IO_RESULT_OK) {
> +               printf("Can't determine device lock state.\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       slot_result = avb_slot_verify(avb_ops, requested_partitions,
> +                                     "", unlocked, &out_data);
> +       switch (slot_result) {
> +       case AVB_SLOT_VERIFY_RESULT_OK:
> +               printf("Verification passed successfully\n");
> +
> +               /* export additional bootargs to AVB_BOOTARGS env var */
> +               env_set(AVB_BOOTARGS, out_data->cmdline);
> +
> +               res = CMD_RET_SUCCESS;
> +               break;
> +       case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
> +               printf("Verification failed\n");
> +               break;
> +       case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
> +               printf("I/O error occurred during verification\n");
> +               break;
> +       case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
> +               printf("OOM error occurred during verification\n");
> +               break;
> +       case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
> +               printf("Corrupted dm-verity metadata detected\n");
> +               break;
> +       case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
> +               printf("Unsupported version avbtool was used\n");
> +               break;
> +       case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
> +               printf("Checking rollback index failed\n");
> +               break;
> +       case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
> +               printf("Public key was rejected\n");
> +               break;
> +       default:
> +               printf("Unknown error occurred\n");
> +       }
> +
> +       return res;
> +}
> +
> +int do_avb_is_unlocked(cmd_tbl_t *cmdtp, int flag,
> +                      int argc, char * const argv[])
> +{
> +       bool unlock;
> +
> +       if (!avb_ops) {
> +               printf("AVB not initialized, run 'avb init' first\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       if (argc != 1) {
> +               printf("--%s(-1)\n", __func__);
> +               return CMD_RET_USAGE;
> +       }
> +
> +       if (avb_ops->read_is_device_unlocked(avb_ops, &unlock) ==
> +           AVB_IO_RESULT_OK) {
> +               printf("Unlocked = %d\n", unlock);
> +               return CMD_RET_SUCCESS;
> +       }
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +static cmd_tbl_t cmd_avb[] = {
> +       U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""),
> +       U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""),
> +       U_BOOT_CMD_MKENT(write_rb, 3, 0, do_avb_write_rb, "", ""),
> +       U_BOOT_CMD_MKENT(is_unlocked, 1, 0, do_avb_is_unlocked, "", ""),
> +       U_BOOT_CMD_MKENT(get_uuid, 2, 0, do_avb_get_uuid, "", ""),
> +       U_BOOT_CMD_MKENT(read_part, 5, 0, do_avb_read_part, "", ""),
> +       U_BOOT_CMD_MKENT(read_part_hex, 4, 0, do_avb_read_part_hex, "", ""),
> +       U_BOOT_CMD_MKENT(write_part, 5, 0, do_avb_write_part, "", ""),
> +       U_BOOT_CMD_MKENT(verify, 1, 0, do_avb_verify_part, "", ""),
> +};
> +
> +static int do_avb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       cmd_tbl_t *cp;
> +
> +       cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb));
> +
> +       argc--;
> +       argv++;
> +
> +       if (!cp || argc > cp->maxargs)
> +               return CMD_RET_USAGE;
> +
> +       if (flag == CMD_FLAG_REPEAT)
> +               return CMD_RET_FAILURE;
> +
> +       return cp->cmd(cmdtp, flag, argc, argv);
> +}
> +
> +U_BOOT_CMD(
> +       avb, 29, 0, do_avb,
> +       "Provides commands for testing Android Verified Boot 2.0 functionality",
> +       "init <dev> - initialize avb2 for <dev>\n"
> +       "avb read_rb <num> - read rollback index at location <num>\n"
> +       "avb write_rb <num> <rb> - write rollback index <rb> to <num>\n"
> +       "avb is_unlocked - returns unlock status of the device\n"
> +       "avb get_uuid <partname> - read and print uuid of partition <part>\n"
> +       "avb read_part <partname> <offset> <num> <addr> - read <num> bytes from\n"
> +       "    partition <partname> to buffer <addr>\n"
> +       "avb read_part_hex <partname> <offset> <num> - read <num> bytes from\n"
> +       "    partition <partname> and print to stdout\n"
> +       "avb write_part <partname> <offset> <num> <addr> - write <num> bytes to\n"
> +       "    <partname> by <offset> using data from <addr>\n"
> +       "avb verify - run verification process using hash data\n"
> +       "    from vbmeta structure\n"
> +       );
> --
> 2.7.4
>

  reply	other threads:[~2018-05-02 18:52 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-25 13:17 [U-Boot] [PATCH 0/8] Initial integration of AVB2.0 Igor Opaniuk
2018-04-25 13:17 ` [U-Boot] [PATCH 1/8] avb2.0: add Android Verified Boot 2.0 libraries Igor Opaniuk
2018-04-25 13:17 ` [U-Boot] [PATCH 2/8] avb2.0: integrate avb 2.0 into the build system Igor Opaniuk
2018-04-25 13:18 ` [U-Boot] [PATCH 3/8] avb2.0: implement AVB ops Igor Opaniuk
2018-04-25 13:18 ` [U-Boot] [PATCH 4/8] cmd: avb2.0: avb command for performing verification Igor Opaniuk
2018-05-02 18:52   ` Sam Protsenko [this message]
2018-05-03  2:31   ` Simon Glass
2018-05-15 15:44     ` Igor Opaniuk
2018-05-15 16:26       ` Simon Glass
2018-05-15 17:31         ` Igor Opaniuk
2018-05-15 18:28           ` Simon Glass
2018-05-16  8:20             ` Igor Opaniuk
2018-05-16 15:40               ` Simon Glass
2018-04-25 13:18 ` [U-Boot] [PATCH 5/8] avb2.0: add boot states and dm-verity support Igor Opaniuk
2018-05-02 18:59   ` Sam Protsenko
2018-04-25 13:18 ` [U-Boot] [PATCH 6/8] am57xx_hs: avb2.0: add support of AVB 2.0 Igor Opaniuk
2018-05-02 19:06   ` Sam Protsenko
2018-04-25 13:18 ` [U-Boot] [PATCH 7/8] test/py: avb2.0: add tests for avb commands Igor Opaniuk
2018-04-25 13:18 ` [U-Boot] [PATCH 8/8] doc: avb2.0: add README about AVB2.0 integration Igor Opaniuk
2018-05-02 19:12   ` Sam Protsenko
2018-05-16  9:20     ` Igor Opaniuk
2018-04-26  3:05 ` [U-Boot] [PATCH 0/8] Initial integration of AVB2.0 Kever Yang
2018-04-26 13:00   ` Igor Opaniuk
2018-04-26 18:35   ` Alex Deymo
2018-04-27  9:53     ` Igor Opaniuk
2018-04-30 10:47       ` Alex Deymo
2018-05-06 11:31 ` Eugeniu Rosca
2018-05-15 15:31   ` Eugeniu Rosca
2018-05-15 16:58     ` Igor Opaniuk
2018-05-15 17:10       ` Eugeniu Rosca

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAKaJLVtS-0-FT6zPZxrixF7hiEqTbEZyof+3eLkf5rx0CfR0ew@mail.gmail.com \
    --to=semen.protsenko@linaro.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.