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