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