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