1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2018, Linaro Limited 4 */ 5 6#include <avb_verify.h> 7#include <blk.h> 8#include <cpu_func.h> 9#include <image.h> 10#include <malloc.h> 11#include <part.h> 12#include <tee.h> 13#include <tee/optee_ta_avb.h> 14 15static const unsigned char avb_root_pub[1032] = { 16 0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4, 17 0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2, 18 0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e, 19 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94, 20 0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53, 21 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88, 22 0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf, 23 0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad, 24 0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3, 25 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7, 26 0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4, 27 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a, 28 0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93, 29 0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb, 30 0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47, 31 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c, 32 0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b, 33 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45, 34 0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7, 35 0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd, 36 0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27, 37 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f, 38 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7, 39 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a, 40 0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9, 41 0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3, 42 0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1, 43 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0, 44 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d, 45 0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16, 46 0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59, 47 0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a, 48 0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81, 49 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf, 50 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c, 51 0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2, 52 0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80, 53 0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf, 54 0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2, 55 0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89, 56 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe, 57 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb, 58 0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed, 59 0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd, 60 0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a, 61 0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5, 62 0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37, 63 0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91, 64 0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6, 65 0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a, 66 0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95, 67 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb, 68 0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7, 69 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4, 70 0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e, 71 0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc, 72 0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64, 73 0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6, 74 0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74, 75 0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f, 76 0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12, 77 0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2, 78 0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87, 79 0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89, 80 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5, 81 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3, 82 0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6, 83 0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6, 84 0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25, 85 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe, 86 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1, 87 0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15, 88 0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4, 89 0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2, 90 0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81, 91 0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86, 92 0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2, 93 0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7, 94 0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec, 95 0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c, 96 0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b, 97 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6, 98 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16, 99 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34, 100 0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5, 101 0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48, 102 0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f, 103 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c, 104 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc, 105 0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68, 106 0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2, 107 0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb, 108 0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7, 109 0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac, 110 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25, 111 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1, 112 0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea, 113 0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1, 114 0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda, 115 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13, 116 0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5, 117 0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77, 118 0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac, 119 0xd8, 0x7e, 120}; 121 122const char *str_avb_io_error(AvbIOResult res) 123{ 124 switch (res) { 125 case AVB_IO_RESULT_OK: 126 return "Requested operation was successful"; 127 case AVB_IO_RESULT_ERROR_IO: 128 return "Underlying hardware encountered an I/O error"; 129 case AVB_IO_RESULT_ERROR_OOM: 130 return "Unable to allocate memory"; 131 case AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION: 132 return "Requested partition does not exist"; 133 case AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION: 134 return "Bytes requested is outside the range of partition"; 135 case AVB_IO_RESULT_ERROR_NO_SUCH_VALUE: 136 return "Named persistent value does not exist"; 137 case AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE: 138 return "Named persistent value size is not supported"; 139 case AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE: 140 return "Buffer is too small for the requested operation"; 141 default: 142 return "Unknown AVB error"; 143 } 144} 145 146const char *str_avb_slot_error(AvbSlotVerifyResult res) 147{ 148 switch (res) { 149 case AVB_SLOT_VERIFY_RESULT_OK: 150 return "Verification passed successfully"; 151 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM: 152 return "Allocation of memory failed"; 153 case AVB_SLOT_VERIFY_RESULT_ERROR_IO: 154 return "I/O error occurred while trying to load data"; 155 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: 156 return "Digest didn't match or signature checks failed"; 157 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: 158 return "Rollback index is less than its stored value"; 159 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: 160 return "Public keys are not accepted"; 161 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA: 162 return "Metadata is invalid or inconsistent"; 163 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION: 164 return "Metadata requires a newer version of libavb"; 165 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT: 166 return "Invalid arguments are used"; 167 default: 168 return "Unknown AVB slot verification error"; 169 } 170} 171/** 172 * ============================================================================ 173 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity 174 * ============================================================================ 175 */ 176char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state) 177{ 178 struct AvbOpsData *data; 179 char *cmdline = NULL; 180 181 if (!ops) 182 return NULL; 183 184 data = (struct AvbOpsData *)ops->user_data; 185 if (!data) 186 return NULL; 187 188 data->boot_state = boot_state; 189 switch (boot_state) { 190 case AVB_GREEN: 191 cmdline = "androidboot.verifiedbootstate=green"; 192 break; 193 case AVB_YELLOW: 194 cmdline = "androidboot.verifiedbootstate=yellow"; 195 break; 196 case AVB_ORANGE: 197 cmdline = "androidboot.verifiedbootstate=orange"; 198 case AVB_RED: 199 break; 200 } 201 202 return cmdline; 203} 204 205char *append_cmd_line(char *cmdline_orig, char *cmdline_new) 206{ 207 char *cmd_line; 208 209 if (!cmdline_new) 210 return cmdline_orig; 211 212 if (cmdline_orig) 213 cmd_line = cmdline_orig; 214 else 215 cmd_line = " "; 216 217 cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL); 218 219 return cmd_line; 220} 221 222static int avb_find_dm_args(char **args, char *str) 223{ 224 int i; 225 226 if (!str) 227 return -1; 228 229 for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) { 230 if (strstr(args[i], str)) 231 return i; 232 } 233 234 return -1; 235} 236 237static char *avb_set_enforce_option(const char *cmdline, const char *option) 238{ 239 char *cmdarg[AVB_MAX_ARGS]; 240 char *newargs = NULL; 241 int i = 0; 242 int total_args; 243 244 memset(cmdarg, 0, sizeof(cmdarg)); 245 cmdarg[i++] = strtok((char *)cmdline, " "); 246 247 do { 248 cmdarg[i] = strtok(NULL, " "); 249 if (!cmdarg[i]) 250 break; 251 252 if (++i >= AVB_MAX_ARGS) { 253 printf("%s: Can't handle more then %d args\n", 254 __func__, i); 255 return NULL; 256 } 257 } while (true); 258 259 total_args = i; 260 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING); 261 if (i >= 0) { 262 cmdarg[i] = (char *)option; 263 } else { 264 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART); 265 if (i < 0) { 266 printf("%s: No verity options found\n", __func__); 267 return NULL; 268 } 269 270 cmdarg[i] = (char *)option; 271 } 272 273 for (i = 0; i <= total_args; i++) 274 newargs = append_cmd_line(newargs, cmdarg[i]); 275 276 return newargs; 277} 278 279char *avb_set_ignore_corruption(const char *cmdline) 280{ 281 char *newargs = NULL; 282 283 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING); 284 if (newargs) 285 newargs = append_cmd_line(newargs, 286 "androidboot.veritymode=eio"); 287 288 return newargs; 289} 290 291char *avb_set_enforce_verity(const char *cmdline) 292{ 293 char *newargs; 294 295 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART); 296 if (newargs) 297 newargs = append_cmd_line(newargs, 298 "androidboot.veritymode=enforcing"); 299 return newargs; 300} 301 302/** 303 * ============================================================================ 304 * IO(mmc) auxiliary functions 305 * ============================================================================ 306 */ 307static unsigned long mmc_read_and_flush(struct mmc_part *part, 308 lbaint_t start, 309 lbaint_t sectors, 310 void *buffer) 311{ 312 unsigned long blks; 313 void *tmp_buf; 314 size_t buf_size; 315 bool unaligned = is_buf_unaligned(buffer); 316 317 if (start < part->info.start) { 318 printf("%s: partition start out of bounds\n", __func__); 319 return 0; 320 } 321 if ((start + sectors) > (part->info.start + part->info.size)) { 322 sectors = part->info.start + part->info.size - start; 323 printf("%s: read sector aligned to partition bounds (%ld)\n", 324 __func__, sectors); 325 } 326 327 /* 328 * Reading fails on unaligned buffers, so we have to 329 * use aligned temporary buffer and then copy to destination 330 */ 331 if (unaligned) { 332 debug("%s: handling unaligned read buffer, addr = 0x%p\n", 333 __func__, buffer); 334 tmp_buf = get_sector_buf(); 335 buf_size = get_sector_buf_size(); 336 if (sectors > buf_size / part->info.blksz) 337 sectors = buf_size / part->info.blksz; 338 } else { 339 tmp_buf = buffer; 340 } 341 342 blks = blk_dread(part->mmc_blk, 343 start, sectors, tmp_buf); 344 /* flush cache after read */ 345 flush_cache((ulong)tmp_buf, sectors * part->info.blksz); 346 347 if (unaligned) 348 memcpy(buffer, tmp_buf, sectors * part->info.blksz); 349 350 return blks; 351} 352 353static unsigned long mmc_write(struct mmc_part *part, lbaint_t start, 354 lbaint_t sectors, void *buffer) 355{ 356 void *tmp_buf; 357 size_t buf_size; 358 bool unaligned = is_buf_unaligned(buffer); 359 360 if (start < part->info.start) { 361 printf("%s: partition start out of bounds\n", __func__); 362 return 0; 363 } 364 if ((start + sectors) > (part->info.start + part->info.size)) { 365 sectors = part->info.start + part->info.size - start; 366 printf("%s: sector aligned to partition bounds (%ld)\n", 367 __func__, sectors); 368 } 369 if (unaligned) { 370 tmp_buf = get_sector_buf(); 371 buf_size = get_sector_buf_size(); 372 debug("%s: handling unaligned read buffer, addr = 0x%p\n", 373 __func__, buffer); 374 if (sectors > buf_size / part->info.blksz) 375 sectors = buf_size / part->info.blksz; 376 377 memcpy(tmp_buf, buffer, sectors * part->info.blksz); 378 } else { 379 tmp_buf = buffer; 380 } 381 382 return blk_dwrite(part->mmc_blk, 383 start, sectors, tmp_buf); 384} 385 386static struct mmc_part *get_partition(AvbOps *ops, const char *partition) 387{ 388 int ret; 389 u8 dev_num; 390 int part_num = 0; 391 struct mmc_part *part; 392 struct blk_desc *mmc_blk; 393 394 part = malloc(sizeof(struct mmc_part)); 395 if (!part) 396 return NULL; 397 398 dev_num = get_boot_device(ops); 399 part->mmc = find_mmc_device(dev_num); 400 if (!part->mmc) { 401 printf("%s: no MMC device at slot %x\n", __func__, dev_num); 402 goto err; 403 } 404 405 ret = mmc_init(part->mmc); 406 if (ret) { 407 printf("%s: MMC initialization failed, err = %d\n", 408 __func__, ret); 409 goto err; 410 } 411 412 if (IS_MMC(part->mmc)) { 413 ret = mmc_switch_part(part->mmc, part_num); 414 if (ret) { 415 printf("%s: MMC part switch failed, err = %d\n", 416 __func__, ret); 417 goto err; 418 } 419 } 420 421 mmc_blk = mmc_get_blk_desc(part->mmc); 422 if (!mmc_blk) { 423 printf("%s: failed to obtain block descriptor\n", __func__); 424 goto err; 425 } 426 427 ret = part_get_info_by_name(mmc_blk, partition, &part->info); 428 if (ret < 0) { 429 printf("%s: can't find partition '%s'\n", __func__, partition); 430 goto err; 431 } 432 433 part->dev_num = dev_num; 434 part->mmc_blk = mmc_blk; 435 436 return part; 437err: 438 free(part); 439 return NULL; 440} 441 442static AvbIOResult mmc_byte_io(AvbOps *ops, 443 const char *partition, 444 s64 offset, 445 size_t num_bytes, 446 void *buffer, 447 size_t *out_num_read, 448 enum mmc_io_type io_type) 449{ 450 ulong ret; 451 struct mmc_part *part; 452 u64 start_offset, start_sector, sectors, residue; 453 u8 *tmp_buf; 454 size_t io_cnt = 0; 455 456 if (!partition || !buffer || io_type > IO_WRITE) 457 return AVB_IO_RESULT_ERROR_IO; 458 459 part = get_partition(ops, partition); 460 if (!part) 461 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 462 463 if (!part->info.blksz) 464 return AVB_IO_RESULT_ERROR_IO; 465 466 start_offset = calc_offset(part, offset); 467 while (num_bytes) { 468 start_sector = start_offset / part->info.blksz; 469 sectors = num_bytes / part->info.blksz; 470 /* handle non block-aligned reads */ 471 if (start_offset % part->info.blksz || 472 num_bytes < part->info.blksz) { 473 tmp_buf = get_sector_buf(); 474 if (start_offset % part->info.blksz) { 475 residue = part->info.blksz - 476 (start_offset % part->info.blksz); 477 if (residue > num_bytes) 478 residue = num_bytes; 479 } else { 480 residue = num_bytes; 481 } 482 483 if (io_type == IO_READ) { 484 ret = mmc_read_and_flush(part, 485 part->info.start + 486 start_sector, 487 1, tmp_buf); 488 489 if (ret != 1) { 490 printf("%s: read error (%ld, %lld)\n", 491 __func__, ret, start_sector); 492 return AVB_IO_RESULT_ERROR_IO; 493 } 494 /* 495 * if this is not aligned at sector start, 496 * we have to adjust the tmp buffer 497 */ 498 tmp_buf += (start_offset % part->info.blksz); 499 memcpy(buffer, (void *)tmp_buf, residue); 500 } else { 501 ret = mmc_read_and_flush(part, 502 part->info.start + 503 start_sector, 504 1, tmp_buf); 505 506 if (ret != 1) { 507 printf("%s: read error (%ld, %lld)\n", 508 __func__, ret, start_sector); 509 return AVB_IO_RESULT_ERROR_IO; 510 } 511 memcpy((void *)tmp_buf + 512 start_offset % part->info.blksz, 513 buffer, residue); 514 515 ret = mmc_write(part, part->info.start + 516 start_sector, 1, tmp_buf); 517 if (ret != 1) { 518 printf("%s: write error (%ld, %lld)\n", 519 __func__, ret, start_sector); 520 return AVB_IO_RESULT_ERROR_IO; 521 } 522 } 523 524 io_cnt += residue; 525 buffer += residue; 526 start_offset += residue; 527 num_bytes -= residue; 528 continue; 529 } 530 531 if (sectors) { 532 if (io_type == IO_READ) { 533 ret = mmc_read_and_flush(part, 534 part->info.start + 535 start_sector, 536 sectors, buffer); 537 } else { 538 ret = mmc_write(part, 539 part->info.start + 540 start_sector, 541 sectors, buffer); 542 } 543 544 if (!ret) { 545 printf("%s: sector read error\n", __func__); 546 return AVB_IO_RESULT_ERROR_IO; 547 } 548 549 io_cnt += ret * part->info.blksz; 550 buffer += ret * part->info.blksz; 551 start_offset += ret * part->info.blksz; 552 num_bytes -= ret * part->info.blksz; 553 } 554 } 555 556 /* Set counter for read operation */ 557 if (io_type == IO_READ && out_num_read) 558 *out_num_read = io_cnt; 559 560 return AVB_IO_RESULT_OK; 561} 562 563/** 564 * ============================================================================ 565 * AVB 2.0 operations 566 * ============================================================================ 567 */ 568 569/** 570 * read_from_partition() - reads @num_bytes from @offset from partition 571 * identified by a string name 572 * 573 * @ops: contains AVB ops handlers 574 * @partition_name: partition name, NUL-terminated UTF-8 string 575 * @offset: offset from the beginning of partition 576 * @num_bytes: amount of bytes to read 577 * @buffer: destination buffer to store data 578 * @out_num_read: 579 * 580 * @return: 581 * AVB_IO_RESULT_OK, if partition was found and read operation succeed 582 * AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o 583 * subsystem 584 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with 585 * the given name 586 */ 587static AvbIOResult read_from_partition(AvbOps *ops, 588 const char *partition_name, 589 s64 offset_from_partition, 590 size_t num_bytes, 591 void *buffer, 592 size_t *out_num_read) 593{ 594 return mmc_byte_io(ops, partition_name, offset_from_partition, 595 num_bytes, buffer, out_num_read, IO_READ); 596} 597 598/** 599 * write_to_partition() - writes N bytes to a partition identified by a string 600 * name 601 * 602 * @ops: AvbOps, contains AVB ops handlers 603 * @partition_name: partition name 604 * @offset_from_partition: offset from the beginning of partition 605 * @num_bytes: amount of bytes to write 606 * @buf: data to write 607 * @out_num_read: 608 * 609 * @return: 610 * AVB_IO_RESULT_OK, if partition was found and read operation succeed 611 * AVB_IO_RESULT_ERROR_IO, if input/output error occurred 612 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in 613 * @partition_name was not found 614 */ 615static AvbIOResult write_to_partition(AvbOps *ops, 616 const char *partition_name, 617 s64 offset_from_partition, 618 size_t num_bytes, 619 const void *buffer) 620{ 621 return mmc_byte_io(ops, partition_name, offset_from_partition, 622 num_bytes, (void *)buffer, NULL, IO_WRITE); 623} 624 625/** 626 * validate_vmbeta_public_key() - checks if the given public key used to sign 627 * the vbmeta partition is trusted 628 * 629 * @ops: AvbOps, contains AVB ops handlers 630 * @public_key_data: public key for verifying vbmeta partition signature 631 * @public_key_length: length of public key 632 * @public_key_metadata: 633 * @public_key_metadata_length: 634 * @out_key_is_trusted: 635 * 636 * @return: 637 * AVB_IO_RESULT_OK, if partition was found and read operation succeed 638 */ 639static AvbIOResult validate_vbmeta_public_key(AvbOps *ops, 640 const u8 *public_key_data, 641 size_t public_key_length, 642 const u8 643 *public_key_metadata, 644 size_t 645 public_key_metadata_length, 646 bool *out_key_is_trusted) 647{ 648 if (!public_key_length || !public_key_data || !out_key_is_trusted) 649 return AVB_IO_RESULT_ERROR_IO; 650 651 *out_key_is_trusted = false; 652 if (public_key_length != sizeof(avb_root_pub)) 653 return AVB_IO_RESULT_ERROR_IO; 654 655 if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0) 656 *out_key_is_trusted = true; 657 658 return AVB_IO_RESULT_OK; 659} 660 661#ifdef CONFIG_OPTEE_TA_AVB 662static int get_open_session(struct AvbOpsData *ops_data) 663{ 664 struct udevice *tee = NULL; 665 666 while (!ops_data->tee) { 667 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID; 668 struct tee_open_session_arg arg; 669 int rc; 670 671 tee = tee_find_device(tee, NULL, NULL, NULL); 672 if (!tee) 673 return -ENODEV; 674 675 memset(&arg, 0, sizeof(arg)); 676 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid); 677 rc = tee_open_session(tee, &arg, 0, NULL); 678 if (rc || arg.ret) 679 continue; 680 681 ops_data->tee = tee; 682 ops_data->session = arg.session; 683 } 684 685 return 0; 686} 687 688static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func, 689 ulong num_param, struct tee_param *param) 690{ 691 struct tee_invoke_arg arg; 692 693 if (get_open_session(ops_data)) 694 return AVB_IO_RESULT_ERROR_IO; 695 696 memset(&arg, 0, sizeof(arg)); 697 arg.func = func; 698 arg.session = ops_data->session; 699 700 if (tee_invoke_func(ops_data->tee, &arg, num_param, param)) 701 return AVB_IO_RESULT_ERROR_IO; 702 switch (arg.ret) { 703 case TEE_SUCCESS: 704 return AVB_IO_RESULT_OK; 705 case TEE_ERROR_OUT_OF_MEMORY: 706 return AVB_IO_RESULT_ERROR_OOM; 707 case TEE_ERROR_STORAGE_NO_SPACE: 708 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE; 709 case TEE_ERROR_ITEM_NOT_FOUND: 710 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; 711 case TEE_ERROR_TARGET_DEAD: 712 /* 713 * The TA has paniced, close the session to reload the TA 714 * for the next request. 715 */ 716 tee_close_session(ops_data->tee, ops_data->session); 717 ops_data->tee = NULL; 718 return AVB_IO_RESULT_ERROR_IO; 719 default: 720 return AVB_IO_RESULT_ERROR_IO; 721 } 722} 723#endif 724 725/** 726 * read_rollback_index() - gets the rollback index corresponding to the 727 * location of given by @out_rollback_index. 728 * 729 * @ops: contains AvbOps handlers 730 * @rollback_index_slot: 731 * @out_rollback_index: used to write a retrieved rollback index. 732 * 733 * @return 734 * AVB_IO_RESULT_OK, if the roolback index was retrieved 735 */ 736static AvbIOResult read_rollback_index(AvbOps *ops, 737 size_t rollback_index_slot, 738 u64 *out_rollback_index) 739{ 740#ifndef CONFIG_OPTEE_TA_AVB 741 /* For now we always return 0 as the stored rollback index. */ 742 debug("%s: rollback protection is not implemented\n", __func__); 743 744 if (out_rollback_index) 745 *out_rollback_index = 0; 746 747 return AVB_IO_RESULT_OK; 748#else 749 AvbIOResult rc; 750 struct tee_param param[2]; 751 752 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS) 753 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; 754 755 memset(param, 0, sizeof(param)); 756 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; 757 param[0].u.value.a = rollback_index_slot; 758 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; 759 760 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX, 761 ARRAY_SIZE(param), param); 762 if (rc) 763 return rc; 764 765 *out_rollback_index = (u64)param[1].u.value.a << 32 | 766 (u32)param[1].u.value.b; 767 return AVB_IO_RESULT_OK; 768#endif 769} 770 771/** 772 * write_rollback_index() - sets the rollback index corresponding to the 773 * location of given by @out_rollback_index. 774 * 775 * @ops: contains AvbOps handlers 776 * @rollback_index_slot: 777 * @rollback_index: rollback index to write. 778 * 779 * @return 780 * AVB_IO_RESULT_OK, if the roolback index was retrieved 781 */ 782static AvbIOResult write_rollback_index(AvbOps *ops, 783 size_t rollback_index_slot, 784 u64 rollback_index) 785{ 786#ifndef CONFIG_OPTEE_TA_AVB 787 /* For now this is a no-op. */ 788 debug("%s: rollback protection is not implemented\n", __func__); 789 790 return AVB_IO_RESULT_OK; 791#else 792 struct tee_param param[2]; 793 794 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS) 795 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; 796 797 memset(param, 0, sizeof(param)); 798 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; 799 param[0].u.value.a = rollback_index_slot; 800 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; 801 param[1].u.value.a = (u32)(rollback_index >> 32); 802 param[1].u.value.b = (u32)rollback_index; 803 804 return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX, 805 ARRAY_SIZE(param), param); 806#endif 807} 808 809/** 810 * read_is_device_unlocked() - gets whether the device is unlocked 811 * 812 * @ops: contains AVB ops handlers 813 * @out_is_unlocked: device unlock state is stored here, true if unlocked, 814 * false otherwise 815 * 816 * @return: 817 * AVB_IO_RESULT_OK: state is retrieved successfully 818 * AVB_IO_RESULT_ERROR_IO: an error occurred 819 */ 820static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) 821{ 822#ifndef CONFIG_OPTEE_TA_AVB 823 /* For now we always return that the device is unlocked. */ 824 debug("%s: device locking is not implemented\n", __func__); 825 826 *out_is_unlocked = true; 827 828 return AVB_IO_RESULT_OK; 829#else 830 AvbIOResult rc; 831 struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT }; 832 833 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, ¶m); 834 if (rc) 835 return rc; 836 *out_is_unlocked = !param.u.value.a; 837 return AVB_IO_RESULT_OK; 838#endif 839} 840 841/** 842 * get_unique_guid_for_partition() - gets the GUID for a partition identified 843 * by a string name 844 * 845 * @ops: contains AVB ops handlers 846 * @partition: partition name (NUL-terminated UTF-8 string) 847 * @guid_buf: buf, used to copy in GUID string. Example of value: 848 * 527c1c6d-6361-4593-8842-3c78fcd39219 849 * @guid_buf_size: @guid_buf buffer size 850 * 851 * @return: 852 * AVB_IO_RESULT_OK, on success (GUID found) 853 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was 854 * provided 855 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found 856 */ 857static AvbIOResult get_unique_guid_for_partition(AvbOps *ops, 858 const char *partition, 859 char *guid_buf, 860 size_t guid_buf_size) 861{ 862 struct mmc_part *part; 863 size_t uuid_size; 864 865 part = get_partition(ops, partition); 866 if (!part) 867 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 868 869 uuid_size = sizeof(part->info.uuid); 870 if (uuid_size > guid_buf_size) 871 return AVB_IO_RESULT_ERROR_IO; 872 873 memcpy(guid_buf, part->info.uuid, uuid_size); 874 guid_buf[uuid_size - 1] = 0; 875 876 return AVB_IO_RESULT_OK; 877} 878 879/** 880 * get_size_of_partition() - gets the size of a partition identified 881 * by a string name 882 * 883 * @ops: contains AVB ops handlers 884 * @partition: partition name (NUL-terminated UTF-8 string) 885 * @out_size_num_bytes: returns the value of a partition size 886 * 887 * @return: 888 * AVB_IO_RESULT_OK, on success (GUID found) 889 * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL 890 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found 891 */ 892static AvbIOResult get_size_of_partition(AvbOps *ops, 893 const char *partition, 894 u64 *out_size_num_bytes) 895{ 896 struct mmc_part *part; 897 898 if (!out_size_num_bytes) 899 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE; 900 901 part = get_partition(ops, partition); 902 if (!part) 903 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 904 905 *out_size_num_bytes = part->info.blksz * part->info.size; 906 907 return AVB_IO_RESULT_OK; 908} 909 910#ifdef CONFIG_OPTEE_TA_AVB 911static AvbIOResult read_persistent_value(AvbOps *ops, 912 const char *name, 913 size_t buffer_size, 914 u8 *out_buffer, 915 size_t *out_num_bytes_read) 916{ 917 AvbIOResult rc; 918 struct tee_shm *shm_name; 919 struct tee_shm *shm_buf; 920 struct tee_param param[2]; 921 struct udevice *tee; 922 size_t name_size = strlen(name) + 1; 923 924 if (get_open_session(ops->user_data)) 925 return AVB_IO_RESULT_ERROR_IO; 926 927 tee = ((struct AvbOpsData *)ops->user_data)->tee; 928 929 rc = tee_shm_alloc(tee, name_size, 930 TEE_SHM_ALLOC, &shm_name); 931 if (rc) 932 return AVB_IO_RESULT_ERROR_OOM; 933 934 rc = tee_shm_alloc(tee, buffer_size, 935 TEE_SHM_ALLOC, &shm_buf); 936 if (rc) { 937 rc = AVB_IO_RESULT_ERROR_OOM; 938 goto free_name; 939 } 940 941 memcpy(shm_name->addr, name, name_size); 942 943 memset(param, 0, sizeof(param)); 944 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; 945 param[0].u.memref.shm = shm_name; 946 param[0].u.memref.size = name_size; 947 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; 948 param[1].u.memref.shm = shm_buf; 949 param[1].u.memref.size = buffer_size; 950 951 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE, 952 2, param); 953 if (rc) 954 goto out; 955 956 if (param[1].u.memref.size > buffer_size) { 957 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; 958 goto out; 959 } 960 961 *out_num_bytes_read = param[1].u.memref.size; 962 963 memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read); 964 965out: 966 tee_shm_free(shm_buf); 967free_name: 968 tee_shm_free(shm_name); 969 970 return rc; 971} 972 973static AvbIOResult write_persistent_value(AvbOps *ops, 974 const char *name, 975 size_t value_size, 976 const u8 *value) 977{ 978 AvbIOResult rc; 979 struct tee_shm *shm_name; 980 struct tee_shm *shm_buf; 981 struct tee_param param[2]; 982 struct udevice *tee; 983 size_t name_size = strlen(name) + 1; 984 985 if (get_open_session(ops->user_data)) 986 return AVB_IO_RESULT_ERROR_IO; 987 988 tee = ((struct AvbOpsData *)ops->user_data)->tee; 989 990 if (!value_size) 991 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; 992 993 rc = tee_shm_alloc(tee, name_size, 994 TEE_SHM_ALLOC, &shm_name); 995 if (rc) 996 return AVB_IO_RESULT_ERROR_OOM; 997 998 rc = tee_shm_alloc(tee, value_size, 999 TEE_SHM_ALLOC, &shm_buf); 1000 if (rc) { 1001 rc = AVB_IO_RESULT_ERROR_OOM; 1002 goto free_name; 1003 } 1004 1005 memcpy(shm_name->addr, name, name_size); 1006 memcpy(shm_buf->addr, value, value_size); 1007 1008 memset(param, 0, sizeof(param)); 1009 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; 1010 param[0].u.memref.shm = shm_name; 1011 param[0].u.memref.size = name_size; 1012 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; 1013 param[1].u.memref.shm = shm_buf; 1014 param[1].u.memref.size = value_size; 1015 1016 rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE, 1017 2, param); 1018 if (rc) 1019 goto out; 1020 1021out: 1022 tee_shm_free(shm_buf); 1023free_name: 1024 tee_shm_free(shm_name); 1025 1026 return rc; 1027} 1028#endif 1029 1030/** 1031 * ============================================================================ 1032 * AVB2.0 AvbOps alloc/initialisation/free 1033 * ============================================================================ 1034 */ 1035AvbOps *avb_ops_alloc(int boot_device) 1036{ 1037 struct AvbOpsData *ops_data; 1038 1039 ops_data = avb_calloc(sizeof(struct AvbOpsData)); 1040 if (!ops_data) 1041 return NULL; 1042 1043 ops_data->ops.user_data = ops_data; 1044 1045 ops_data->ops.read_from_partition = read_from_partition; 1046 ops_data->ops.write_to_partition = write_to_partition; 1047 ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key; 1048 ops_data->ops.read_rollback_index = read_rollback_index; 1049 ops_data->ops.write_rollback_index = write_rollback_index; 1050 ops_data->ops.read_is_device_unlocked = read_is_device_unlocked; 1051 ops_data->ops.get_unique_guid_for_partition = 1052 get_unique_guid_for_partition; 1053#ifdef CONFIG_OPTEE_TA_AVB 1054 ops_data->ops.write_persistent_value = write_persistent_value; 1055 ops_data->ops.read_persistent_value = read_persistent_value; 1056#endif 1057 ops_data->ops.get_size_of_partition = get_size_of_partition; 1058 ops_data->mmc_dev = boot_device; 1059 1060 return &ops_data->ops; 1061} 1062 1063void avb_ops_free(AvbOps *ops) 1064{ 1065 struct AvbOpsData *ops_data; 1066 1067 if (!ops) 1068 return; 1069 1070 ops_data = ops->user_data; 1071 1072 if (ops_data) { 1073#ifdef CONFIG_OPTEE_TA_AVB 1074 if (ops_data->tee) 1075 tee_close_session(ops_data->tee, ops_data->session); 1076#endif 1077 avb_free(ops_data); 1078 } 1079} 1080