1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2018, Linaro Limited 4 */ 5 6#include <avb_verify.h> 7#include <command.h> 8#include <env.h> 9#include <image.h> 10#include <malloc.h> 11#include <mmc.h> 12 13#define AVB_BOOTARGS "avb_bootargs" 14 15static struct AvbOps *avb_ops; 16 17int do_avb_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 18{ 19 unsigned long mmc_dev; 20 21 if (argc != 2) 22 return CMD_RET_USAGE; 23 24 mmc_dev = hextoul(argv[1], NULL); 25 26 if (avb_ops) 27 avb_ops_free(avb_ops); 28 29 avb_ops = avb_ops_alloc(mmc_dev); 30 if (avb_ops) 31 return CMD_RET_SUCCESS; 32 else 33 printf("Can't allocate AvbOps"); 34 35 printf("Failed to initialize AVB\n"); 36 37 return CMD_RET_FAILURE; 38} 39 40int do_avb_read_part(struct cmd_tbl *cmdtp, int flag, int argc, 41 char *const argv[]) 42{ 43 const char *part; 44 s64 offset; 45 size_t bytes, bytes_read = 0; 46 void *buffer; 47 int ret; 48 49 if (!avb_ops) { 50 printf("AVB is not initialized, please run 'avb init <id>'\n"); 51 return CMD_RET_FAILURE; 52 } 53 54 if (argc != 5) 55 return CMD_RET_USAGE; 56 57 part = argv[1]; 58 offset = hextoul(argv[2], NULL); 59 bytes = hextoul(argv[3], NULL); 60 buffer = (void *)hextoul(argv[4], NULL); 61 62 ret = avb_ops->read_from_partition(avb_ops, part, offset, 63 bytes, buffer, &bytes_read); 64 if (ret == AVB_IO_RESULT_OK) { 65 printf("Read %zu bytes\n", bytes_read); 66 return CMD_RET_SUCCESS; 67 } 68 69 printf("Failed to read from partition '%s', err = %d\n", 70 part, ret); 71 72 return CMD_RET_FAILURE; 73} 74 75int do_avb_read_part_hex(struct cmd_tbl *cmdtp, int flag, int argc, 76 char *const argv[]) 77{ 78 const char *part; 79 s64 offset; 80 size_t bytes, bytes_read = 0; 81 char *buffer; 82 int ret; 83 84 if (!avb_ops) { 85 printf("AVB is not initialized, please run 'avb init <id>'\n"); 86 return CMD_RET_FAILURE; 87 } 88 89 if (argc != 4) 90 return CMD_RET_USAGE; 91 92 part = argv[1]; 93 offset = hextoul(argv[2], NULL); 94 bytes = hextoul(argv[3], NULL); 95 96 buffer = malloc(bytes); 97 if (!buffer) { 98 printf("Failed to tlb_allocate buffer for data\n"); 99 return CMD_RET_FAILURE; 100 } 101 memset(buffer, 0, bytes); 102 103 ret = avb_ops->read_from_partition(avb_ops, part, offset, 104 bytes, buffer, &bytes_read); 105 if (ret == AVB_IO_RESULT_OK) { 106 printf("Requested %zu, read %zu bytes\n", bytes, bytes_read); 107 printf("Data: "); 108 for (int i = 0; i < bytes_read; i++) 109 printf("%02X", buffer[i]); 110 111 printf("\n"); 112 113 free(buffer); 114 return CMD_RET_SUCCESS; 115 } 116 117 printf("Failed to read from partition '%s', err = %d\n", 118 part, ret); 119 120 free(buffer); 121 return CMD_RET_FAILURE; 122} 123 124int do_avb_write_part(struct cmd_tbl *cmdtp, int flag, int argc, 125 char *const argv[]) 126{ 127 const char *part; 128 s64 offset; 129 size_t bytes; 130 void *buffer; 131 int ret; 132 133 if (!avb_ops) { 134 printf("AVB is not initialized, please run 'avb init <id>'\n"); 135 return CMD_RET_FAILURE; 136 } 137 138 if (argc != 5) 139 return CMD_RET_USAGE; 140 141 part = argv[1]; 142 offset = hextoul(argv[2], NULL); 143 bytes = hextoul(argv[3], NULL); 144 buffer = (void *)hextoul(argv[4], NULL); 145 146 ret = avb_ops->write_to_partition(avb_ops, part, offset, 147 bytes, buffer); 148 if (ret == AVB_IO_RESULT_OK) { 149 printf("Wrote %zu bytes\n", bytes); 150 return CMD_RET_SUCCESS; 151 } 152 153 printf("Failed to write in partition '%s', err = %d\n", 154 part, ret); 155 156 return CMD_RET_FAILURE; 157} 158 159int do_avb_read_rb(struct cmd_tbl *cmdtp, int flag, int argc, 160 char *const argv[]) 161{ 162 size_t index; 163 u64 rb_idx; 164 int ret; 165 166 if (!avb_ops) { 167 printf("AVB is not initialized, please run 'avb init <id>'\n"); 168 return CMD_RET_FAILURE; 169 } 170 171 if (argc != 2) 172 return CMD_RET_USAGE; 173 174 index = (size_t)hextoul(argv[1], NULL); 175 176 ret = avb_ops->read_rollback_index(avb_ops, index, &rb_idx); 177 if (ret == AVB_IO_RESULT_OK) { 178 printf("Rollback index: %llx\n", rb_idx); 179 return CMD_RET_SUCCESS; 180 } 181 182 printf("Failed to read rollback index id = %zu, err = %d\n", 183 index, ret); 184 185 return CMD_RET_FAILURE; 186} 187 188int do_avb_write_rb(struct cmd_tbl *cmdtp, int flag, int argc, 189 char *const argv[]) 190{ 191 size_t index; 192 u64 rb_idx; 193 int ret; 194 195 if (!avb_ops) { 196 printf("AVB is not initialized, please run 'avb init <id>'\n"); 197 return CMD_RET_FAILURE; 198 } 199 200 if (argc != 3) 201 return CMD_RET_USAGE; 202 203 index = (size_t)hextoul(argv[1], NULL); 204 rb_idx = hextoul(argv[2], NULL); 205 206 ret = avb_ops->write_rollback_index(avb_ops, index, rb_idx); 207 if (ret == AVB_IO_RESULT_OK) 208 return CMD_RET_SUCCESS; 209 210 printf("Failed to write rollback index id = %zu, err = %d\n", 211 index, ret); 212 213 return CMD_RET_FAILURE; 214} 215 216int do_avb_get_uuid(struct cmd_tbl *cmdtp, int flag, 217 int argc, char *const argv[]) 218{ 219 const char *part; 220 char buffer[UUID_STR_LEN + 1]; 221 int ret; 222 223 if (!avb_ops) { 224 printf("AVB is not initialized, please run 'avb init <id>'\n"); 225 return CMD_RET_FAILURE; 226 } 227 228 if (argc != 2) 229 return CMD_RET_USAGE; 230 231 part = argv[1]; 232 233 ret = avb_ops->get_unique_guid_for_partition(avb_ops, part, 234 buffer, 235 UUID_STR_LEN + 1); 236 if (ret == AVB_IO_RESULT_OK) { 237 printf("'%s' UUID: %s\n", part, buffer); 238 return CMD_RET_SUCCESS; 239 } 240 241 printf("Failed to read partition '%s' UUID, err = %d\n", 242 part, ret); 243 244 return CMD_RET_FAILURE; 245} 246 247int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag, 248 int argc, char *const argv[]) 249{ 250 const char * const requested_partitions[] = {"boot", NULL}; 251 AvbSlotVerifyResult slot_result; 252 AvbSlotVerifyData *out_data; 253 enum avb_boot_state boot_state; 254 char *cmdline; 255 char *extra_args; 256 char *slot_suffix = ""; 257 int ret; 258 259 bool unlocked = false; 260 int res = CMD_RET_FAILURE; 261 262 if (!avb_ops) { 263 printf("AVB is not initialized, please run 'avb init <id>'\n"); 264 return CMD_RET_FAILURE; 265 } 266 267 if (argc < 1 || argc > 2) 268 return CMD_RET_USAGE; 269 270 if (argc == 2) 271 slot_suffix = argv[1]; 272 273 printf("## Android Verified Boot 2.0 version %s\n", 274 avb_version_string()); 275 276 ret = avb_ops->read_is_device_unlocked(avb_ops, &unlocked); 277 if (ret != AVB_IO_RESULT_OK) { 278 printf("Can't determine device lock state, err = %d\n", 279 ret); 280 return CMD_RET_FAILURE; 281 } 282 283 slot_result = 284 avb_slot_verify(avb_ops, 285 requested_partitions, 286 slot_suffix, 287 unlocked, 288 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 289 &out_data); 290 291 /* 292 * LOCKED devices with custom root of trust setup is not supported (YELLOW) 293 */ 294 if (slot_result == AVB_SLOT_VERIFY_RESULT_OK) { 295 printf("Verification passed successfully\n"); 296 297 /* 298 * ORANGE state indicates that device may be freely modified. 299 * Device integrity is left to the user to verify out-of-band. 300 */ 301 if (unlocked) 302 boot_state = AVB_ORANGE; 303 else 304 boot_state = AVB_GREEN; 305 306 /* export boot state to AVB_BOOTARGS env var */ 307 extra_args = avb_set_state(avb_ops, boot_state); 308 if (extra_args) 309 cmdline = append_cmd_line(out_data->cmdline, 310 extra_args); 311 else 312 cmdline = out_data->cmdline; 313 314 env_set(AVB_BOOTARGS, cmdline); 315 316 res = CMD_RET_SUCCESS; 317 } else { 318 printf("Verification failed, reason: %s\n", str_avb_slot_error(slot_result)); 319 } 320 321 if (out_data) 322 avb_slot_verify_data_free(out_data); 323 324 return res; 325} 326 327int do_avb_is_unlocked(struct cmd_tbl *cmdtp, int flag, 328 int argc, char *const argv[]) 329{ 330 bool unlock; 331 int ret; 332 333 if (!avb_ops) { 334 printf("AVB is not initialized, please run 'avb init <id>'\n"); 335 return CMD_RET_FAILURE; 336 } 337 338 if (argc != 1) { 339 printf("--%s(-1)\n", __func__); 340 return CMD_RET_USAGE; 341 } 342 343 ret = avb_ops->read_is_device_unlocked(avb_ops, &unlock); 344 if (ret == AVB_IO_RESULT_OK) { 345 printf("Unlocked = %d\n", unlock); 346 return CMD_RET_SUCCESS; 347 } 348 349 printf("Can't determine device lock state, err = %d\n", 350 ret); 351 352 return CMD_RET_FAILURE; 353} 354 355int do_avb_read_pvalue(struct cmd_tbl *cmdtp, int flag, int argc, 356 char *const argv[]) 357{ 358 const char *name; 359 size_t bytes; 360 size_t bytes_read; 361 void *buffer; 362 char *endp; 363 int ret; 364 365 if (!avb_ops) { 366 printf("AVB is not initialized, please run 'avb init <id>'\n"); 367 return CMD_RET_FAILURE; 368 } 369 370 if (argc != 3) 371 return CMD_RET_USAGE; 372 373 name = argv[1]; 374 bytes = dectoul(argv[2], &endp); 375 if (*endp && *endp != '\n') 376 return CMD_RET_USAGE; 377 378 buffer = malloc(bytes); 379 if (!buffer) 380 return CMD_RET_FAILURE; 381 382 ret = avb_ops->read_persistent_value(avb_ops, name, bytes, 383 buffer, &bytes_read); 384 if (ret == AVB_IO_RESULT_OK) { 385 printf("Read %zu bytes, value = %s\n", bytes_read, 386 (char *)buffer); 387 free(buffer); 388 return CMD_RET_SUCCESS; 389 } 390 391 printf("Failed to read persistent value, err = %d\n", ret); 392 393 free(buffer); 394 395 return CMD_RET_FAILURE; 396} 397 398int do_avb_write_pvalue(struct cmd_tbl *cmdtp, int flag, int argc, 399 char *const argv[]) 400{ 401 const char *name; 402 const char *value; 403 int ret; 404 405 if (!avb_ops) { 406 printf("AVB is not initialized, please run 'avb init <id>'\n"); 407 return CMD_RET_FAILURE; 408 } 409 410 if (argc != 3) 411 return CMD_RET_USAGE; 412 413 name = argv[1]; 414 value = argv[2]; 415 416 ret = avb_ops->write_persistent_value(avb_ops, name, 417 strlen(value) + 1, 418 (const uint8_t *)value); 419 if (ret == AVB_IO_RESULT_OK) { 420 printf("Wrote %zu bytes\n", strlen(value) + 1); 421 return CMD_RET_SUCCESS; 422 } 423 424 printf("Failed to write persistent value `%s` = `%s`, err = %d\n", 425 name, value, ret); 426 427 return CMD_RET_FAILURE; 428} 429 430static struct cmd_tbl cmd_avb[] = { 431 U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""), 432 U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""), 433 U_BOOT_CMD_MKENT(write_rb, 3, 0, do_avb_write_rb, "", ""), 434 U_BOOT_CMD_MKENT(is_unlocked, 1, 0, do_avb_is_unlocked, "", ""), 435 U_BOOT_CMD_MKENT(get_uuid, 2, 0, do_avb_get_uuid, "", ""), 436 U_BOOT_CMD_MKENT(read_part, 5, 0, do_avb_read_part, "", ""), 437 U_BOOT_CMD_MKENT(read_part_hex, 4, 0, do_avb_read_part_hex, "", ""), 438 U_BOOT_CMD_MKENT(write_part, 5, 0, do_avb_write_part, "", ""), 439 U_BOOT_CMD_MKENT(verify, 2, 0, do_avb_verify_part, "", ""), 440#ifdef CONFIG_OPTEE_TA_AVB 441 U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_avb_read_pvalue, "", ""), 442 U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_avb_write_pvalue, "", ""), 443#endif 444}; 445 446static int do_avb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 447{ 448 struct cmd_tbl *cp; 449 450 cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb)); 451 452 argc--; 453 argv++; 454 455 if (!cp || argc > cp->maxargs) 456 return CMD_RET_USAGE; 457 458 if (flag == CMD_FLAG_REPEAT) 459 return CMD_RET_FAILURE; 460 461 return cp->cmd(cmdtp, flag, argc, argv); 462} 463 464U_BOOT_CMD( 465 avb, 29, 0, do_avb, 466 "Provides commands for testing Android Verified Boot 2.0 functionality", 467 "init <dev> - initialize avb2 for <dev>\n" 468 "avb read_rb <num> - read rollback index at location <num>\n" 469 "avb write_rb <num> <rb> - write rollback index <rb> to <num>\n" 470 "avb is_unlocked - returns unlock status of the device\n" 471 "avb get_uuid <partname> - read and print uuid of partition <part>\n" 472 "avb read_part <partname> <offset> <num> <addr> - read <num> bytes from\n" 473 " partition <partname> to buffer <addr>\n" 474 "avb read_part_hex <partname> <offset> <num> - read <num> bytes from\n" 475 " partition <partname> and print to stdout\n" 476 "avb write_part <partname> <offset> <num> <addr> - write <num> bytes to\n" 477 " <partname> by <offset> using data from <addr>\n" 478#ifdef CONFIG_OPTEE_TA_AVB 479 "avb read_pvalue <name> <bytes> - read a persistent value <name>\n" 480 "avb write_pvalue <name> <value> - write a persistent value <name>\n" 481#endif 482 "avb verify [slot_suffix] - run verification process using hash data\n" 483 " from vbmeta structure\n" 484 " [slot_suffix] - _a, _b, etc (if vbmeta partition is slotted)\n" 485 ); 486