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