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" 15 static struct AvbOps *avb_ops; 16 17 static const char * const requested_partitions[] = {"boot", 18 "system", 19 "vendor", 20 NULL}; 21 22 int 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 41 int 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 71 int 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 115 int 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 144 int 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 167 int 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 190 int 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 216 int 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 302 int 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 326 static 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 338 static 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 356 U_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