1 /* 2 * (C) Copyright 2018, Linaro Limited 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <avb_verify.h> 8 #include <fastboot.h> 9 #include <image.h> 10 #include <malloc.h> 11 #include <part.h> 12 13 const unsigned char avb_root_pub[1032] = { 14 0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4, 15 0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2, 16 0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e, 17 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94, 18 0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53, 19 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88, 20 0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf, 21 0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad, 22 0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3, 23 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7, 24 0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4, 25 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a, 26 0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93, 27 0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb, 28 0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47, 29 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c, 30 0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b, 31 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45, 32 0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7, 33 0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd, 34 0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27, 35 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f, 36 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7, 37 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a, 38 0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9, 39 0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3, 40 0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1, 41 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0, 42 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d, 43 0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16, 44 0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59, 45 0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a, 46 0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81, 47 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf, 48 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c, 49 0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2, 50 0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80, 51 0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf, 52 0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2, 53 0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89, 54 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe, 55 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb, 56 0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed, 57 0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd, 58 0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a, 59 0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5, 60 0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37, 61 0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91, 62 0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6, 63 0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a, 64 0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95, 65 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb, 66 0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7, 67 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4, 68 0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e, 69 0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc, 70 0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64, 71 0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6, 72 0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74, 73 0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f, 74 0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12, 75 0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2, 76 0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87, 77 0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89, 78 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5, 79 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3, 80 0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6, 81 0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6, 82 0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25, 83 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe, 84 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1, 85 0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15, 86 0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4, 87 0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2, 88 0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81, 89 0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86, 90 0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2, 91 0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7, 92 0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec, 93 0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c, 94 0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b, 95 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6, 96 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16, 97 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34, 98 0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5, 99 0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48, 100 0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f, 101 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c, 102 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc, 103 0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68, 104 0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2, 105 0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb, 106 0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7, 107 0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac, 108 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25, 109 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1, 110 0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea, 111 0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1, 112 0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda, 113 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13, 114 0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5, 115 0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77, 116 0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac, 117 0xd8, 0x7e, 118 }; 119 120 /** 121 * ============================================================================ 122 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity 123 * ============================================================================ 124 */ 125 char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state) 126 { 127 struct AvbOpsData *data; 128 char *cmdline = NULL; 129 130 if (!ops) 131 return NULL; 132 133 data = (struct AvbOpsData *)ops->user_data; 134 if (!data) 135 return NULL; 136 137 data->boot_state = boot_state; 138 switch (boot_state) { 139 case AVB_GREEN: 140 cmdline = "androidboot.verifiedbootstate=green"; 141 break; 142 case AVB_YELLOW: 143 cmdline = "androidboot.verifiedbootstate=yellow"; 144 break; 145 case AVB_ORANGE: 146 cmdline = "androidboot.verifiedbootstate=orange"; 147 case AVB_RED: 148 break; 149 } 150 151 return cmdline; 152 } 153 154 char *append_cmd_line(char *cmdline_orig, char *cmdline_new) 155 { 156 char *cmd_line; 157 158 if (!cmdline_new) 159 return cmdline_orig; 160 161 if (cmdline_orig) 162 cmd_line = cmdline_orig; 163 else 164 cmd_line = " "; 165 166 cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL); 167 168 return cmd_line; 169 } 170 171 static int avb_find_dm_args(char **args, char *str) 172 { 173 int i; 174 175 if (!str) 176 return -1; 177 178 for (i = 0; i < AVB_MAX_ARGS, args[i]; ++i) { 179 if (strstr(args[i], str)) 180 return i; 181 } 182 183 return -1; 184 } 185 186 static char *avb_set_enforce_option(const char *cmdline, const char *option) 187 { 188 char *cmdarg[AVB_MAX_ARGS]; 189 char *newargs = NULL; 190 int i = 0; 191 int total_args; 192 193 memset(cmdarg, 0, sizeof(cmdarg)); 194 cmdarg[i++] = strtok((char *)cmdline, " "); 195 196 do { 197 cmdarg[i] = strtok(NULL, " "); 198 if (!cmdarg[i]) 199 break; 200 201 if (++i >= AVB_MAX_ARGS) { 202 printf("%s: Can't handle more then %d args\n", 203 __func__, i); 204 return NULL; 205 } 206 } while (true); 207 208 total_args = i; 209 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING); 210 if (i >= 0) { 211 cmdarg[i] = (char *)option; 212 } else { 213 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART); 214 if (i < 0) { 215 printf("%s: No verity options found\n", __func__); 216 return NULL; 217 } 218 219 cmdarg[i] = (char *)option; 220 } 221 222 for (i = 0; i <= total_args; i++) 223 newargs = append_cmd_line(newargs, cmdarg[i]); 224 225 return newargs; 226 } 227 228 char *avb_set_ignore_corruption(const char *cmdline) 229 { 230 char *newargs = NULL; 231 232 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING); 233 if (newargs) 234 newargs = append_cmd_line(newargs, 235 "androidboot.veritymode=eio"); 236 237 return newargs; 238 } 239 240 char *avb_set_enforce_verity(const char *cmdline) 241 { 242 char *newargs; 243 244 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART); 245 if (newargs) 246 newargs = append_cmd_line(newargs, 247 "androidboot.veritymode=enforcing"); 248 return newargs; 249 } 250 251 /** 252 * ============================================================================ 253 * IO(mmc) auxiliary functions 254 * ============================================================================ 255 */ 256 static unsigned long mmc_read_and_flush(struct mmc_part *part, 257 lbaint_t start, 258 lbaint_t sectors, 259 void *buffer) 260 { 261 unsigned long blks; 262 void *tmp_buf; 263 size_t buf_size; 264 bool unaligned = is_buf_unaligned(buffer); 265 266 if (start < part->info.start) { 267 printf("%s: partition start out of bounds\n", __func__); 268 return 0; 269 } 270 if ((start + sectors) > (part->info.start + part->info.size)) { 271 sectors = part->info.start + part->info.size - start; 272 printf("%s: read sector aligned to partition bounds (%ld)\n", 273 __func__, sectors); 274 } 275 276 /* 277 * Reading fails on unaligned buffers, so we have to 278 * use aligned temporary buffer and then copy to destination 279 */ 280 281 if (unaligned) { 282 printf("Handling unaligned read buffer..\n"); 283 tmp_buf = get_sector_buf(); 284 buf_size = get_sector_buf_size(); 285 if (sectors > buf_size / part->info.blksz) 286 sectors = buf_size / part->info.blksz; 287 } else { 288 tmp_buf = buffer; 289 } 290 291 blks = part->mmc->block_dev.block_read(part->mmc_blk, 292 start, sectors, tmp_buf); 293 /* flush cache after read */ 294 flush_cache((ulong)tmp_buf, sectors * part->info.blksz); 295 296 if (unaligned) 297 memcpy(buffer, tmp_buf, sectors * part->info.blksz); 298 299 return blks; 300 } 301 302 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start, 303 lbaint_t sectors, void *buffer) 304 { 305 void *tmp_buf; 306 size_t buf_size; 307 bool unaligned = is_buf_unaligned(buffer); 308 309 if (start < part->info.start) { 310 printf("%s: partition start out of bounds\n", __func__); 311 return 0; 312 } 313 if ((start + sectors) > (part->info.start + part->info.size)) { 314 sectors = part->info.start + part->info.size - start; 315 printf("%s: sector aligned to partition bounds (%ld)\n", 316 __func__, sectors); 317 } 318 if (unaligned) { 319 tmp_buf = get_sector_buf(); 320 buf_size = get_sector_buf_size(); 321 printf("Handling unaligned wrire buffer..\n"); 322 if (sectors > buf_size / part->info.blksz) 323 sectors = buf_size / part->info.blksz; 324 325 memcpy(tmp_buf, buffer, sectors * part->info.blksz); 326 } else { 327 tmp_buf = buffer; 328 } 329 330 return part->mmc->block_dev.block_write(part->mmc_blk, 331 start, sectors, tmp_buf); 332 } 333 334 static struct mmc_part *get_partition(AvbOps *ops, const char *partition) 335 { 336 int ret; 337 u8 dev_num; 338 int part_num = 0; 339 struct mmc_part *part; 340 struct blk_desc *mmc_blk; 341 342 part = malloc(sizeof(struct mmc_part)); 343 if (!part) 344 return NULL; 345 346 dev_num = get_boot_device(ops); 347 part->mmc = find_mmc_device(dev_num); 348 if (!part->mmc) { 349 printf("No MMC device at slot %x\n", dev_num); 350 return NULL; 351 } 352 353 if (mmc_init(part->mmc)) { 354 printf("MMC initialization failed\n"); 355 return NULL; 356 } 357 358 ret = mmc_switch_part(part->mmc, part_num); 359 if (ret) 360 return NULL; 361 362 mmc_blk = mmc_get_blk_desc(part->mmc); 363 if (!mmc_blk) { 364 printf("Error - failed to obtain block descriptor\n"); 365 return NULL; 366 } 367 368 ret = part_get_info_by_name(mmc_blk, partition, &part->info); 369 if (!ret) { 370 printf("Can't find partition '%s'\n", partition); 371 return NULL; 372 } 373 374 part->dev_num = dev_num; 375 part->mmc_blk = mmc_blk; 376 377 return part; 378 } 379 380 static AvbIOResult mmc_byte_io(AvbOps *ops, 381 const char *partition, 382 s64 offset, 383 size_t num_bytes, 384 void *buffer, 385 size_t *out_num_read, 386 enum mmc_io_type io_type) 387 { 388 ulong ret; 389 struct mmc_part *part; 390 u64 start_offset, start_sector, sectors, residue; 391 u8 *tmp_buf; 392 size_t io_cnt = 0; 393 394 if (!partition || !buffer || io_type > IO_WRITE) 395 return AVB_IO_RESULT_ERROR_IO; 396 397 part = get_partition(ops, partition); 398 if (!part) 399 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 400 401 start_offset = calc_offset(part, offset); 402 while (num_bytes) { 403 start_sector = start_offset / part->info.blksz; 404 sectors = num_bytes / part->info.blksz; 405 /* handle non block-aligned reads */ 406 if (start_offset % part->info.blksz || 407 num_bytes < part->info.blksz) { 408 tmp_buf = get_sector_buf(); 409 if (start_offset % part->info.blksz) { 410 residue = part->info.blksz - 411 (start_offset % part->info.blksz); 412 if (residue > num_bytes) 413 residue = num_bytes; 414 } else { 415 residue = num_bytes; 416 } 417 418 if (io_type == IO_READ) { 419 ret = mmc_read_and_flush(part, 420 part->info.start + 421 start_sector, 422 1, tmp_buf); 423 424 if (ret != 1) { 425 printf("%s: read error (%ld, %lld)\n", 426 __func__, ret, start_sector); 427 return AVB_IO_RESULT_ERROR_IO; 428 } 429 /* 430 * if this is not aligned at sector start, 431 * we have to adjust the tmp buffer 432 */ 433 tmp_buf += (start_offset % part->info.blksz); 434 memcpy(buffer, (void *)tmp_buf, residue); 435 } else { 436 ret = mmc_read_and_flush(part, 437 part->info.start + 438 start_sector, 439 1, tmp_buf); 440 441 if (ret != 1) { 442 printf("%s: read error (%ld, %lld)\n", 443 __func__, ret, start_sector); 444 return AVB_IO_RESULT_ERROR_IO; 445 } 446 memcpy((void *)tmp_buf + 447 start_offset % part->info.blksz, 448 buffer, residue); 449 450 ret = mmc_write(part, part->info.start + 451 start_sector, 1, tmp_buf); 452 if (ret != 1) { 453 printf("%s: write error (%ld, %lld)\n", 454 __func__, ret, start_sector); 455 return AVB_IO_RESULT_ERROR_IO; 456 } 457 } 458 459 io_cnt += residue; 460 buffer += residue; 461 start_offset += residue; 462 num_bytes -= residue; 463 continue; 464 } 465 466 if (sectors) { 467 if (io_type == IO_READ) { 468 ret = mmc_read_and_flush(part, 469 part->info.start + 470 start_sector, 471 sectors, buffer); 472 } else { 473 ret = mmc_write(part, 474 part->info.start + 475 start_sector, 476 sectors, buffer); 477 } 478 479 if (!ret) { 480 printf("%s: sector read error\n", __func__); 481 return AVB_IO_RESULT_ERROR_IO; 482 } 483 484 io_cnt += ret * part->info.blksz; 485 buffer += ret * part->info.blksz; 486 start_offset += ret * part->info.blksz; 487 num_bytes -= ret * part->info.blksz; 488 } 489 } 490 491 /* Set counter for read operation */ 492 if (io_type == IO_READ && out_num_read) 493 *out_num_read = io_cnt; 494 495 return AVB_IO_RESULT_OK; 496 } 497 498 /** 499 * ============================================================================ 500 * AVB 2.0 operations 501 * ============================================================================ 502 */ 503 504 /** 505 * read_from_partition() - reads @num_bytes from @offset from partition 506 * identified by a string name 507 * 508 * @ops: contains AVB ops handlers 509 * @partition_name: partition name, NUL-terminated UTF-8 string 510 * @offset: offset from the beginning of partition 511 * @num_bytes: amount of bytes to read 512 * @buffer: destination buffer to store data 513 * @out_num_read: 514 * 515 * @return: 516 * AVB_IO_RESULT_OK, if partition was found and read operation succeed 517 * AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o 518 * subsystem 519 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with 520 * the given name 521 */ 522 static AvbIOResult read_from_partition(AvbOps *ops, 523 const char *partition_name, 524 s64 offset_from_partition, 525 size_t num_bytes, 526 void *buffer, 527 size_t *out_num_read) 528 { 529 return mmc_byte_io(ops, partition_name, offset_from_partition, 530 num_bytes, buffer, out_num_read, IO_READ); 531 } 532 533 /** 534 * write_to_partition() - writes N bytes to a partition identified by a string 535 * name 536 * 537 * @ops: AvbOps, contains AVB ops handlers 538 * @partition_name: partition name 539 * @offset_from_partition: offset from the beginning of partition 540 * @num_bytes: amount of bytes to write 541 * @buf: data to write 542 * @out_num_read: 543 * 544 * @return: 545 * AVB_IO_RESULT_OK, if partition was found and read operation succeed 546 * AVB_IO_RESULT_ERROR_IO, if input/output error occurred 547 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in 548 * @partition_name was not found 549 */ 550 static AvbIOResult write_to_partition(AvbOps *ops, 551 const char *partition_name, 552 s64 offset_from_partition, 553 size_t num_bytes, 554 const void *buffer) 555 { 556 return mmc_byte_io(ops, partition_name, offset_from_partition, 557 num_bytes, (void *)buffer, NULL, IO_WRITE); 558 } 559 560 /** 561 * validate_vmbeta_public_key() - checks if the given public key used to sign 562 * the vbmeta partition is trusted 563 * 564 * @ops: AvbOps, contains AVB ops handlers 565 * @public_key_data: public key for verifying vbmeta partition signature 566 * @public_key_length: length of public key 567 * @public_key_metadata: 568 * @public_key_metadata_length: 569 * @out_key_is_trusted: 570 * 571 * @return: 572 * AVB_IO_RESULT_OK, if partition was found and read operation succeed 573 */ 574 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops, 575 const u8 *public_key_data, 576 size_t public_key_length, 577 const u8 578 *public_key_metadata, 579 size_t 580 public_key_metadata_length, 581 bool *out_key_is_trusted) 582 { 583 if (!public_key_length || !public_key_data || !out_key_is_trusted) 584 return AVB_IO_RESULT_ERROR_IO; 585 586 *out_key_is_trusted = false; 587 if (public_key_length != sizeof(avb_root_pub)) 588 return AVB_IO_RESULT_ERROR_IO; 589 590 if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0) 591 *out_key_is_trusted = true; 592 593 return AVB_IO_RESULT_OK; 594 } 595 596 /** 597 * read_rollback_index() - gets the rollback index corresponding to the 598 * location of given by @out_rollback_index. 599 * 600 * @ops: contains AvbOps handlers 601 * @rollback_index_slot: 602 * @out_rollback_index: used to write a retrieved rollback index. 603 * 604 * @return 605 * AVB_IO_RESULT_OK, if the roolback index was retrieved 606 */ 607 static AvbIOResult read_rollback_index(AvbOps *ops, 608 size_t rollback_index_slot, 609 u64 *out_rollback_index) 610 { 611 /* For now we always return 0 as the stored rollback index. */ 612 printf("%s not supported yet\n", __func__); 613 614 if (out_rollback_index) 615 *out_rollback_index = 0; 616 617 return AVB_IO_RESULT_OK; 618 } 619 620 /** 621 * write_rollback_index() - sets the rollback index corresponding to the 622 * location of given by @out_rollback_index. 623 * 624 * @ops: contains AvbOps handlers 625 * @rollback_index_slot: 626 * @rollback_index: rollback index to write. 627 * 628 * @return 629 * AVB_IO_RESULT_OK, if the roolback index was retrieved 630 */ 631 static AvbIOResult write_rollback_index(AvbOps *ops, 632 size_t rollback_index_slot, 633 u64 rollback_index) 634 { 635 /* For now this is a no-op. */ 636 printf("%s not supported yet\n", __func__); 637 638 return AVB_IO_RESULT_OK; 639 } 640 641 /** 642 * read_is_device_unlocked() - gets whether the device is unlocked 643 * 644 * @ops: contains AVB ops handlers 645 * @out_is_unlocked: device unlock state is stored here, true if unlocked, 646 * false otherwise 647 * 648 * @return: 649 * AVB_IO_RESULT_OK: state is retrieved successfully 650 * AVB_IO_RESULT_ERROR_IO: an error occurred 651 */ 652 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) 653 { 654 /* For now we always return that the device is unlocked. */ 655 656 printf("%s not supported yet\n", __func__); 657 658 *out_is_unlocked = true; 659 660 return AVB_IO_RESULT_OK; 661 } 662 663 /** 664 * get_unique_guid_for_partition() - gets the GUID for a partition identified 665 * by a string name 666 * 667 * @ops: contains AVB ops handlers 668 * @partition: partition name (NUL-terminated UTF-8 string) 669 * @guid_buf: buf, used to copy in GUID string. Example of value: 670 * 527c1c6d-6361-4593-8842-3c78fcd39219 671 * @guid_buf_size: @guid_buf buffer size 672 * 673 * @return: 674 * AVB_IO_RESULT_OK, on success (GUID found) 675 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was 676 * provided 677 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found 678 */ 679 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops, 680 const char *partition, 681 char *guid_buf, 682 size_t guid_buf_size) 683 { 684 struct mmc_part *part; 685 size_t uuid_size; 686 687 part = get_partition(ops, partition); 688 if (!part) 689 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 690 691 uuid_size = sizeof(part->info.uuid); 692 if (uuid_size > guid_buf_size) 693 return AVB_IO_RESULT_ERROR_IO; 694 695 memcpy(guid_buf, part->info.uuid, uuid_size); 696 guid_buf[uuid_size - 1] = 0; 697 698 return AVB_IO_RESULT_OK; 699 } 700 701 /** 702 * ============================================================================ 703 * AVB2.0 AvbOps alloc/initialisation/free 704 * ============================================================================ 705 */ 706 AvbOps *avb_ops_alloc(int boot_device) 707 { 708 struct AvbOpsData *ops_data; 709 710 ops_data = avb_calloc(sizeof(struct AvbOpsData)); 711 if (!ops_data) 712 return NULL; 713 714 ops_data->ops.user_data = ops_data; 715 716 ops_data->ops.read_from_partition = read_from_partition; 717 ops_data->ops.write_to_partition = write_to_partition; 718 ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key; 719 ops_data->ops.read_rollback_index = read_rollback_index; 720 ops_data->ops.write_rollback_index = write_rollback_index; 721 ops_data->ops.read_is_device_unlocked = read_is_device_unlocked; 722 ops_data->ops.get_unique_guid_for_partition = 723 get_unique_guid_for_partition; 724 725 ops_data->mmc_dev = boot_device; 726 727 return &ops_data->ops; 728 } 729 730 void avb_ops_free(AvbOps *ops) 731 { 732 struct AvbOpsData *ops_data; 733 734 if (ops) 735 return; 736 737 ops_data = ops->user_data; 738 739 if (ops_data) 740 avb_free(ops_data); 741 } 742