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