uboot/cmd/avb.c
<<
>>
Prefs
   1
   2/*
   3 * (C) Copyright 2018, Linaro Limited
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <avb_verify.h>
   9#include <command.h>
  10#include <image.h>
  11#include <malloc.h>
  12#include <mmc.h>
  13
  14#define AVB_BOOTARGS    "avb_bootargs"
  15static struct AvbOps *avb_ops;
  16
  17static const char * const requested_partitions[] = {"boot",
  18                                             "system",
  19                                             "vendor",
  20                                             NULL};
  21
  22int do_avb_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  23{
  24        unsigned long mmc_dev;
  25
  26        if (argc != 2)
  27                return CMD_RET_USAGE;
  28
  29        mmc_dev = simple_strtoul(argv[1], NULL, 16);
  30
  31        if (avb_ops)
  32                avb_ops_free(avb_ops);
  33
  34        avb_ops = avb_ops_alloc(mmc_dev);
  35        if (avb_ops)
  36                return CMD_RET_SUCCESS;
  37
  38        return CMD_RET_FAILURE;
  39}
  40
  41int do_avb_read_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  42{
  43        const char *part;
  44        s64 offset;
  45        size_t bytes, bytes_read = 0;
  46        void *buffer;
  47
  48        if (!avb_ops) {
  49                printf("AVB 2.0 is not initialized, please run 'avb init'\n");
  50                return CMD_RET_USAGE;
  51        }
  52
  53        if (argc != 5)
  54                return CMD_RET_USAGE;
  55
  56        part = argv[1];
  57        offset = simple_strtoul(argv[2], NULL, 16);
  58        bytes = simple_strtoul(argv[3], NULL, 16);
  59        buffer = (void *)simple_strtoul(argv[4], NULL, 16);
  60
  61        if (avb_ops->read_from_partition(avb_ops, part, offset, bytes,
  62                                         buffer, &bytes_read) ==
  63                                         AVB_IO_RESULT_OK) {
  64                printf("Read %zu bytes\n", bytes_read);
  65                return CMD_RET_SUCCESS;
  66        }
  67
  68        return CMD_RET_FAILURE;
  69}
  70
  71int do_avb_read_part_hex(cmd_tbl_t *cmdtp, int flag, int argc,
  72                         char *const argv[])
  73{
  74        const char *part;
  75        s64 offset;
  76        size_t bytes, bytes_read = 0;
  77        char *buffer;
  78
  79        if (!avb_ops) {
  80                printf("AVB 2.0 is not initialized, please run 'avb init'\n");
  81                return CMD_RET_USAGE;
  82        }
  83
  84        if (argc != 4)
  85                return CMD_RET_USAGE;
  86
  87        part = argv[1];
  88        offset = simple_strtoul(argv[2], NULL, 16);
  89        bytes = simple_strtoul(argv[3], NULL, 16);
  90
  91        buffer = malloc(bytes);
  92        if (!buffer) {
  93                printf("Failed to tlb_allocate buffer for data\n");
  94                return CMD_RET_FAILURE;
  95        }
  96        memset(buffer, 0, bytes);
  97
  98        if (avb_ops->read_from_partition(avb_ops, part, offset, bytes, buffer,
  99                                         &bytes_read) == AVB_IO_RESULT_OK) {
 100                printf("Requested %zu, read %zu bytes\n", bytes, bytes_read);
 101                printf("Data: ");
 102                for (int i = 0; i < bytes_read; i++)
 103                        printf("%02X", buffer[i]);
 104
 105                printf("\n");
 106
 107                free(buffer);
 108                return CMD_RET_SUCCESS;
 109        }
 110
 111        free(buffer);
 112        return CMD_RET_FAILURE;
 113}
 114
 115int do_avb_write_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 116{
 117        const char *part;
 118        s64 offset;
 119        size_t bytes;
 120        void *buffer;
 121
 122        if (!avb_ops) {
 123                printf("AVB 2.0 is not initialized, run 'avb init' first\n");
 124                return CMD_RET_FAILURE;
 125        }
 126
 127        if (argc != 5)
 128                return CMD_RET_USAGE;
 129
 130        part = argv[1];
 131        offset = simple_strtoul(argv[2], NULL, 16);
 132        bytes = simple_strtoul(argv[3], NULL, 16);
 133        buffer = (void *)simple_strtoul(argv[4], NULL, 16);
 134
 135        if (avb_ops->write_to_partition(avb_ops, part, offset, bytes, buffer) ==
 136            AVB_IO_RESULT_OK) {
 137                printf("Wrote %zu bytes\n", bytes);
 138                return CMD_RET_SUCCESS;
 139        }
 140
 141        return CMD_RET_FAILURE;
 142}
 143
 144int do_avb_read_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 145{
 146        size_t index;
 147        u64 rb_idx;
 148
 149        if (!avb_ops) {
 150                printf("AVB 2.0 is not initialized, run 'avb init' first\n");
 151                return CMD_RET_FAILURE;
 152        }
 153
 154        if (argc != 2)
 155                return CMD_RET_USAGE;
 156
 157        index = (size_t)simple_strtoul(argv[1], NULL, 16);
 158
 159        if (avb_ops->read_rollback_index(avb_ops, index, &rb_idx) ==
 160            AVB_IO_RESULT_OK) {
 161                printf("Rollback index: %llu\n", rb_idx);
 162                return CMD_RET_SUCCESS;
 163        }
 164        return CMD_RET_FAILURE;
 165}
 166
 167int do_avb_write_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 168{
 169        size_t index;
 170        u64 rb_idx;
 171
 172        if (!avb_ops) {
 173                printf("AVB 2.0 is not initialized, run 'avb init' first\n");
 174                return CMD_RET_FAILURE;
 175        }
 176
 177        if (argc != 3)
 178                return CMD_RET_USAGE;
 179
 180        index = (size_t)simple_strtoul(argv[1], NULL, 16);
 181        rb_idx = simple_strtoul(argv[2], NULL, 16);
 182
 183        if (avb_ops->write_rollback_index(avb_ops, index, rb_idx) ==
 184            AVB_IO_RESULT_OK)
 185                return CMD_RET_SUCCESS;
 186
 187        return CMD_RET_FAILURE;
 188}
 189
 190int do_avb_get_uuid(cmd_tbl_t *cmdtp, int flag,
 191                    int argc, char * const argv[])
 192{
 193        const char *part;
 194        char buffer[UUID_STR_LEN + 1];
 195
 196        if (!avb_ops) {
 197                printf("AVB 2.0 is not initialized, run 'avb init' first\n");
 198                return CMD_RET_FAILURE;
 199        }
 200
 201        if (argc != 2)
 202                return CMD_RET_USAGE;
 203
 204        part = argv[1];
 205
 206        if (avb_ops->get_unique_guid_for_partition(avb_ops, part, buffer,
 207                                                   UUID_STR_LEN + 1) ==
 208                                                   AVB_IO_RESULT_OK) {
 209                printf("'%s' UUID: %s\n", part, buffer);
 210                return CMD_RET_SUCCESS;
 211        }
 212
 213        return CMD_RET_FAILURE;
 214}
 215
 216int do_avb_verify_part(cmd_tbl_t *cmdtp, int flag,
 217                       int argc, char *const argv[])
 218{
 219        AvbSlotVerifyResult slot_result;
 220        AvbSlotVerifyData *out_data;
 221        char *cmdline;
 222        char *extra_args;
 223
 224        bool unlocked = false;
 225        int res = CMD_RET_FAILURE;
 226
 227        if (!avb_ops) {
 228                printf("AVB 2.0 is not initialized, run 'avb init' first\n");
 229                return CMD_RET_FAILURE;
 230        }
 231
 232        if (argc != 1)
 233                return CMD_RET_USAGE;
 234
 235        printf("## Android Verified Boot 2.0 version %s\n",
 236               avb_version_string());
 237
 238        if (avb_ops->read_is_device_unlocked(avb_ops, &unlocked) !=
 239            AVB_IO_RESULT_OK) {
 240                printf("Can't determine device lock state.\n");
 241                return CMD_RET_FAILURE;
 242        }
 243
 244        slot_result =
 245                avb_slot_verify(avb_ops,
 246                                requested_partitions,
 247                                "",
 248                                unlocked,
 249                                AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
 250                                &out_data);
 251
 252        switch (slot_result) {
 253        case AVB_SLOT_VERIFY_RESULT_OK:
 254                /* Until we don't have support of changing unlock states, we
 255                 * assume that we are by default in locked state.
 256                 * So in this case we can boot only when verification is
 257                 * successful; we also supply in cmdline GREEN boot state
 258                 */
 259                printf("Verification passed successfully\n");
 260
 261                /* export additional bootargs to AVB_BOOTARGS env var */
 262
 263                extra_args = avb_set_state(avb_ops, AVB_GREEN);
 264                if (extra_args)
 265                        cmdline = append_cmd_line(out_data->cmdline,
 266                                                  extra_args);
 267                else
 268                        cmdline = out_data->cmdline;
 269
 270                env_set(AVB_BOOTARGS, cmdline);
 271
 272                res = CMD_RET_SUCCESS;
 273                break;
 274        case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
 275                printf("Verification failed\n");
 276                break;
 277        case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
 278                printf("I/O error occurred during verification\n");
 279                break;
 280        case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
 281                printf("OOM error occurred during verification\n");
 282                break;
 283        case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
 284                printf("Corrupted dm-verity metadata detected\n");
 285                break;
 286        case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
 287                printf("Unsupported version avbtool was used\n");
 288                break;
 289        case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
 290                printf("Checking rollback index failed\n");
 291                break;
 292        case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
 293                printf("Public key was rejected\n");
 294                break;
 295        default:
 296                printf("Unknown error occurred\n");
 297        }
 298
 299        return res;
 300}
 301
 302int do_avb_is_unlocked(cmd_tbl_t *cmdtp, int flag,
 303                       int argc, char * const argv[])
 304{
 305        bool unlock;
 306
 307        if (!avb_ops) {
 308                printf("AVB not initialized, run 'avb init' first\n");
 309                return CMD_RET_FAILURE;
 310        }
 311
 312        if (argc != 1) {
 313                printf("--%s(-1)\n", __func__);
 314                return CMD_RET_USAGE;
 315        }
 316
 317        if (avb_ops->read_is_device_unlocked(avb_ops, &unlock) ==
 318            AVB_IO_RESULT_OK) {
 319                printf("Unlocked = %d\n", unlock);
 320                return CMD_RET_SUCCESS;
 321        }
 322
 323        return CMD_RET_FAILURE;
 324}
 325
 326static cmd_tbl_t cmd_avb[] = {
 327        U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""),
 328        U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""),
 329        U_BOOT_CMD_MKENT(write_rb, 3, 0, do_avb_write_rb, "", ""),
 330        U_BOOT_CMD_MKENT(is_unlocked, 1, 0, do_avb_is_unlocked, "", ""),
 331        U_BOOT_CMD_MKENT(get_uuid, 2, 0, do_avb_get_uuid, "", ""),
 332        U_BOOT_CMD_MKENT(read_part, 5, 0, do_avb_read_part, "", ""),
 333        U_BOOT_CMD_MKENT(read_part_hex, 4, 0, do_avb_read_part_hex, "", ""),
 334        U_BOOT_CMD_MKENT(write_part, 5, 0, do_avb_write_part, "", ""),
 335        U_BOOT_CMD_MKENT(verify, 1, 0, do_avb_verify_part, "", ""),
 336};
 337
 338static int do_avb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 339{
 340        cmd_tbl_t *cp;
 341
 342        cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb));
 343
 344        argc--;
 345        argv++;
 346
 347        if (!cp || argc > cp->maxargs)
 348                return CMD_RET_USAGE;
 349
 350        if (flag == CMD_FLAG_REPEAT)
 351                return CMD_RET_FAILURE;
 352
 353        return cp->cmd(cmdtp, flag, argc, argv);
 354}
 355
 356U_BOOT_CMD(
 357        avb, 29, 0, do_avb,
 358        "Provides commands for testing Android Verified Boot 2.0 functionality",
 359        "init <dev> - initialize avb2 for <dev>\n"
 360        "avb read_rb <num> - read rollback index at location <num>\n"
 361        "avb write_rb <num> <rb> - write rollback index <rb> to <num>\n"
 362        "avb is_unlocked - returns unlock status of the device\n"
 363        "avb get_uuid <partname> - read and print uuid of partition <part>\n"
 364        "avb read_part <partname> <offset> <num> <addr> - read <num> bytes from\n"
 365        "    partition <partname> to buffer <addr>\n"
 366        "avb read_part_hex <partname> <offset> <num> - read <num> bytes from\n"
 367        "    partition <partname> and print to stdout\n"
 368        "avb write_part <partname> <offset> <num> <addr> - write <num> bytes to\n"
 369        "    <partname> by <offset> using data from <addr>\n"
 370        "avb verify - run verification process using hash data\n"
 371        "    from vbmeta structure\n"
 372        );
 373