1 /* 2 * Copyright (c) 2013, Google Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #ifdef USE_HOSTCC 8 #include "mkimage.h" 9 #include <time.h> 10 #else 11 #include <common.h> 12 #include <malloc.h> 13 DECLARE_GLOBAL_DATA_PTR; 14 #endif /* !USE_HOSTCC*/ 15 #include <image.h> 16 #include <rsa.h> 17 #include <rsa-checksum.h> 18 19 #define IMAGE_MAX_HASHED_NODES 100 20 21 #ifdef USE_HOSTCC 22 void *host_blob; 23 void image_set_host_blob(void *blob) 24 { 25 host_blob = blob; 26 } 27 void *image_get_host_blob(void) 28 { 29 return host_blob; 30 } 31 #endif 32 33 struct checksum_algo checksum_algos[] = { 34 { 35 "sha1", 36 SHA1_SUM_LEN, 37 RSA2048_BYTES, 38 #if IMAGE_ENABLE_SIGN 39 EVP_sha1, 40 #endif 41 sha1_calculate, 42 padding_sha1_rsa2048, 43 }, 44 { 45 "sha256", 46 SHA256_SUM_LEN, 47 RSA2048_BYTES, 48 #if IMAGE_ENABLE_SIGN 49 EVP_sha256, 50 #endif 51 sha256_calculate, 52 padding_sha256_rsa2048, 53 }, 54 { 55 "sha256", 56 SHA256_SUM_LEN, 57 RSA4096_BYTES, 58 #if IMAGE_ENABLE_SIGN 59 EVP_sha256, 60 #endif 61 sha256_calculate, 62 padding_sha256_rsa4096, 63 } 64 65 }; 66 67 struct image_sig_algo image_sig_algos[] = { 68 { 69 "sha1,rsa2048", 70 rsa_sign, 71 rsa_add_verify_data, 72 rsa_verify, 73 &checksum_algos[0], 74 }, 75 { 76 "sha256,rsa2048", 77 rsa_sign, 78 rsa_add_verify_data, 79 rsa_verify, 80 &checksum_algos[1], 81 }, 82 { 83 "sha256,rsa4096", 84 rsa_sign, 85 rsa_add_verify_data, 86 rsa_verify, 87 &checksum_algos[2], 88 } 89 90 }; 91 92 struct image_sig_algo *image_get_sig_algo(const char *name) 93 { 94 int i; 95 96 for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) { 97 if (!strcmp(image_sig_algos[i].name, name)) 98 return &image_sig_algos[i]; 99 } 100 101 return NULL; 102 } 103 104 /** 105 * fit_region_make_list() - Make a list of image regions 106 * 107 * Given a list of fdt_regions, create a list of image_regions. This is a 108 * simple conversion routine since the FDT and image code use different 109 * structures. 110 * 111 * @fit: FIT image 112 * @fdt_regions: Pointer to FDT regions 113 * @count: Number of FDT regions 114 * @region: Pointer to image regions, which must hold @count records. If 115 * region is NULL, then (except for an SPL build) the array will be 116 * allocated. 117 * @return: Pointer to image regions 118 */ 119 struct image_region *fit_region_make_list(const void *fit, 120 struct fdt_region *fdt_regions, int count, 121 struct image_region *region) 122 { 123 int i; 124 125 debug("Hash regions:\n"); 126 debug("%10s %10s\n", "Offset", "Size"); 127 128 /* 129 * Use malloc() except in SPL (to save code size). In SPL the caller 130 * must allocate the array. 131 */ 132 #ifndef CONFIG_SPL_BUILD 133 if (!region) 134 region = calloc(sizeof(*region), count); 135 #endif 136 if (!region) 137 return NULL; 138 for (i = 0; i < count; i++) { 139 debug("%10x %10x\n", fdt_regions[i].offset, 140 fdt_regions[i].size); 141 region[i].data = fit + fdt_regions[i].offset; 142 region[i].size = fdt_regions[i].size; 143 } 144 145 return region; 146 } 147 148 static int fit_image_setup_verify(struct image_sign_info *info, 149 const void *fit, int noffset, int required_keynode, 150 char **err_msgp) 151 { 152 char *algo_name; 153 154 if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { 155 *err_msgp = "Can't get hash algo property"; 156 return -1; 157 } 158 memset(info, '\0', sizeof(*info)); 159 info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL); 160 info->fit = (void *)fit; 161 info->node_offset = noffset; 162 info->algo = image_get_sig_algo(algo_name); 163 info->fdt_blob = gd_fdt_blob(); 164 info->required_keynode = required_keynode; 165 printf("%s:%s", algo_name, info->keyname); 166 167 if (!info->algo) { 168 *err_msgp = "Unknown signature algorithm"; 169 return -1; 170 } 171 172 return 0; 173 } 174 175 int fit_image_check_sig(const void *fit, int noffset, const void *data, 176 size_t size, int required_keynode, char **err_msgp) 177 { 178 struct image_sign_info info; 179 struct image_region region; 180 uint8_t *fit_value; 181 int fit_value_len; 182 183 *err_msgp = NULL; 184 if (fit_image_setup_verify(&info, fit, noffset, required_keynode, 185 err_msgp)) 186 return -1; 187 188 if (fit_image_hash_get_value(fit, noffset, &fit_value, 189 &fit_value_len)) { 190 *err_msgp = "Can't get hash value property"; 191 return -1; 192 } 193 194 region.data = data; 195 region.size = size; 196 197 if (info.algo->verify(&info, ®ion, 1, fit_value, fit_value_len)) { 198 *err_msgp = "Verification failed"; 199 return -1; 200 } 201 202 return 0; 203 } 204 205 static int fit_image_verify_sig(const void *fit, int image_noffset, 206 const char *data, size_t size, const void *sig_blob, 207 int sig_offset) 208 { 209 int noffset; 210 char *err_msg = ""; 211 int verified = 0; 212 int ret; 213 214 /* Process all hash subnodes of the component image node */ 215 for (noffset = fdt_first_subnode(fit, image_noffset); 216 noffset >= 0; 217 noffset = fdt_next_subnode(fit, noffset)) { 218 const char *name = fit_get_name(fit, noffset, NULL); 219 220 if (!strncmp(name, FIT_SIG_NODENAME, 221 strlen(FIT_SIG_NODENAME))) { 222 ret = fit_image_check_sig(fit, noffset, data, 223 size, -1, &err_msg); 224 if (ret) { 225 puts("- "); 226 } else { 227 puts("+ "); 228 verified = 1; 229 break; 230 } 231 } 232 } 233 234 if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { 235 err_msg = "Corrupted or truncated tree"; 236 goto error; 237 } 238 239 return verified ? 0 : -EPERM; 240 241 error: 242 printf(" error!\n%s for '%s' hash node in '%s' image node\n", 243 err_msg, fit_get_name(fit, noffset, NULL), 244 fit_get_name(fit, image_noffset, NULL)); 245 return -1; 246 } 247 248 int fit_image_verify_required_sigs(const void *fit, int image_noffset, 249 const char *data, size_t size, const void *sig_blob, 250 int *no_sigsp) 251 { 252 int verify_count = 0; 253 int noffset; 254 int sig_node; 255 256 /* Work out what we need to verify */ 257 *no_sigsp = 1; 258 sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); 259 if (sig_node < 0) { 260 debug("%s: No signature node found: %s\n", __func__, 261 fdt_strerror(sig_node)); 262 return 0; 263 } 264 265 for (noffset = fdt_first_subnode(sig_blob, sig_node); 266 noffset >= 0; 267 noffset = fdt_next_subnode(sig_blob, noffset)) { 268 const char *required; 269 int ret; 270 271 required = fdt_getprop(sig_blob, noffset, "required", NULL); 272 if (!required || strcmp(required, "image")) 273 continue; 274 ret = fit_image_verify_sig(fit, image_noffset, data, size, 275 sig_blob, noffset); 276 if (ret) { 277 printf("Failed to verify required signature '%s'\n", 278 fit_get_name(sig_blob, noffset, NULL)); 279 return ret; 280 } 281 verify_count++; 282 } 283 284 if (verify_count) 285 *no_sigsp = 0; 286 287 return 0; 288 } 289 290 int fit_config_check_sig(const void *fit, int noffset, int required_keynode, 291 char **err_msgp) 292 { 293 char * const exc_prop[] = {"data"}; 294 const char *prop, *end, *name; 295 struct image_sign_info info; 296 const uint32_t *strings; 297 uint8_t *fit_value; 298 int fit_value_len; 299 int max_regions; 300 int i, prop_len; 301 char path[200]; 302 int count; 303 304 debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(), 305 fit_get_name(fit, noffset, NULL), 306 fit_get_name(gd_fdt_blob(), required_keynode, NULL)); 307 *err_msgp = NULL; 308 if (fit_image_setup_verify(&info, fit, noffset, required_keynode, 309 err_msgp)) 310 return -1; 311 312 if (fit_image_hash_get_value(fit, noffset, &fit_value, 313 &fit_value_len)) { 314 *err_msgp = "Can't get hash value property"; 315 return -1; 316 } 317 318 /* Count the number of strings in the property */ 319 prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len); 320 end = prop ? prop + prop_len : prop; 321 for (name = prop, count = 0; name < end; name++) 322 if (!*name) 323 count++; 324 if (!count) { 325 *err_msgp = "Can't get hashed-nodes property"; 326 return -1; 327 } 328 329 /* Add a sanity check here since we are using the stack */ 330 if (count > IMAGE_MAX_HASHED_NODES) { 331 *err_msgp = "Number of hashed nodes exceeds maximum"; 332 return -1; 333 } 334 335 /* Create a list of node names from those strings */ 336 char *node_inc[count]; 337 338 debug("Hash nodes (%d):\n", count); 339 for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) { 340 debug(" '%s'\n", name); 341 node_inc[i] = (char *)name; 342 } 343 344 /* 345 * Each node can generate one region for each sub-node. Allow for 346 * 7 sub-nodes (hash@1, signature@1, etc.) and some extra. 347 */ 348 max_regions = 20 + count * 7; 349 struct fdt_region fdt_regions[max_regions]; 350 351 /* Get a list of regions to hash */ 352 count = fdt_find_regions(fit, node_inc, count, 353 exc_prop, ARRAY_SIZE(exc_prop), 354 fdt_regions, max_regions - 1, 355 path, sizeof(path), 0); 356 if (count < 0) { 357 *err_msgp = "Failed to hash configuration"; 358 return -1; 359 } 360 if (count == 0) { 361 *err_msgp = "No data to hash"; 362 return -1; 363 } 364 if (count >= max_regions - 1) { 365 *err_msgp = "Too many hash regions"; 366 return -1; 367 } 368 369 /* Add the strings */ 370 strings = fdt_getprop(fit, noffset, "hashed-strings", NULL); 371 if (strings) { 372 fdt_regions[count].offset = fdt_off_dt_strings(fit) + 373 fdt32_to_cpu(strings[0]); 374 fdt_regions[count].size = fdt32_to_cpu(strings[1]); 375 count++; 376 } 377 378 /* Allocate the region list on the stack */ 379 struct image_region region[count]; 380 381 fit_region_make_list(fit, fdt_regions, count, region); 382 if (info.algo->verify(&info, region, count, fit_value, 383 fit_value_len)) { 384 *err_msgp = "Verification failed"; 385 return -1; 386 } 387 388 return 0; 389 } 390 391 static int fit_config_verify_sig(const void *fit, int conf_noffset, 392 const void *sig_blob, int sig_offset) 393 { 394 int noffset; 395 char *err_msg = ""; 396 int verified = 0; 397 int ret; 398 399 /* Process all hash subnodes of the component conf node */ 400 for (noffset = fdt_first_subnode(fit, conf_noffset); 401 noffset >= 0; 402 noffset = fdt_next_subnode(fit, noffset)) { 403 const char *name = fit_get_name(fit, noffset, NULL); 404 405 if (!strncmp(name, FIT_SIG_NODENAME, 406 strlen(FIT_SIG_NODENAME))) { 407 ret = fit_config_check_sig(fit, noffset, sig_offset, 408 &err_msg); 409 if (ret) { 410 puts("- "); 411 } else { 412 puts("+ "); 413 verified = 1; 414 break; 415 } 416 } 417 } 418 419 if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { 420 err_msg = "Corrupted or truncated tree"; 421 goto error; 422 } 423 424 return verified ? 0 : -EPERM; 425 426 error: 427 printf(" error!\n%s for '%s' hash node in '%s' config node\n", 428 err_msg, fit_get_name(fit, noffset, NULL), 429 fit_get_name(fit, conf_noffset, NULL)); 430 return -1; 431 } 432 433 int fit_config_verify_required_sigs(const void *fit, int conf_noffset, 434 const void *sig_blob) 435 { 436 int noffset; 437 int sig_node; 438 439 /* Work out what we need to verify */ 440 sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); 441 if (sig_node < 0) { 442 debug("%s: No signature node found: %s\n", __func__, 443 fdt_strerror(sig_node)); 444 return 0; 445 } 446 447 for (noffset = fdt_first_subnode(sig_blob, sig_node); 448 noffset >= 0; 449 noffset = fdt_next_subnode(sig_blob, noffset)) { 450 const char *required; 451 int ret; 452 453 required = fdt_getprop(sig_blob, noffset, "required", NULL); 454 if (!required || strcmp(required, "conf")) 455 continue; 456 ret = fit_config_verify_sig(fit, conf_noffset, sig_blob, 457 noffset); 458 if (ret) { 459 printf("Failed to verify required signature '%s'\n", 460 fit_get_name(sig_blob, noffset, NULL)); 461 return ret; 462 } 463 } 464 465 return 0; 466 } 467 468 int fit_config_verify(const void *fit, int conf_noffset) 469 { 470 return !fit_config_verify_required_sigs(fit, conf_noffset, 471 gd_fdt_blob()); 472 } 473