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