1 /* 2 * Copyright (c) 2013, Google Inc. 3 * 4 * (C) Copyright 2008 Semihalf 5 * 6 * (C) Copyright 2000-2006 7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 8 * 9 * See file CREDITS for list of people who contributed to this 10 * project. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; either version 2 of 15 * the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 * MA 02111-1307 USA 26 */ 27 28 #include "mkimage.h" 29 #include <bootstage.h> 30 #include <image.h> 31 #include <sha1.h> 32 #include <time.h> 33 #include <u-boot/crc.h> 34 #include <u-boot/md5.h> 35 36 /** 37 * fit_set_hashes - process FIT component image nodes and calculate hashes 38 * @fit: pointer to the FIT format image header 39 * 40 * fit_set_hashes() adds hash values for all component images in the FIT blob. 41 * Hashes are calculated for all component images which have hash subnodes 42 * with algorithm property set to one of the supported hash algorithms. 43 * 44 * returns 45 * 0, on success 46 * libfdt error code, on failure 47 */ 48 int fit_set_hashes(void *fit) 49 { 50 int images_noffset; 51 int noffset; 52 int ndepth; 53 int ret; 54 55 /* Find images parent node offset */ 56 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); 57 if (images_noffset < 0) { 58 printf("Can't find images parent node '%s' (%s)\n", 59 FIT_IMAGES_PATH, fdt_strerror(images_noffset)); 60 return images_noffset; 61 } 62 63 /* Process its subnodes, print out component images details */ 64 for (ndepth = 0, noffset = fdt_next_node(fit, images_noffset, &ndepth); 65 (noffset >= 0) && (ndepth > 0); 66 noffset = fdt_next_node(fit, noffset, &ndepth)) { 67 if (ndepth == 1) { 68 /* 69 * Direct child node of the images parent node, 70 * i.e. component image node. 71 */ 72 ret = fit_image_set_hashes(fit, noffset); 73 if (ret) 74 return ret; 75 } 76 } 77 78 return 0; 79 } 80 81 /** 82 * fit_image_set_hashes - calculate/set hashes for given component image node 83 * @fit: pointer to the FIT format image header 84 * @image_noffset: requested component image node 85 * 86 * fit_image_set_hashes() adds hash values for an component image node. All 87 * existing hash subnodes are checked, if algorithm property is set to one of 88 * the supported hash algorithms, hash value is computed and corresponding 89 * hash node property is set, for example: 90 * 91 * Input component image node structure: 92 * 93 * o image@1 (at image_noffset) 94 * | - data = [binary data] 95 * o hash@1 96 * |- algo = "sha1" 97 * 98 * Output component image node structure: 99 * 100 * o image@1 (at image_noffset) 101 * | - data = [binary data] 102 * o hash@1 103 * |- algo = "sha1" 104 * |- value = sha1(data) 105 * 106 * returns: 107 * 0 on sucess 108 * <0 on failure 109 */ 110 int fit_image_set_hashes(void *fit, int image_noffset) 111 { 112 const void *data; 113 size_t size; 114 char *algo; 115 uint8_t value[FIT_MAX_HASH_LEN]; 116 int value_len; 117 int noffset; 118 int ndepth; 119 120 /* Get image data and data length */ 121 if (fit_image_get_data(fit, image_noffset, &data, &size)) { 122 printf("Can't get image data/size\n"); 123 return -1; 124 } 125 126 /* Process all hash subnodes of the component image node */ 127 for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); 128 (noffset >= 0) && (ndepth > 0); 129 noffset = fdt_next_node(fit, noffset, &ndepth)) { 130 if (ndepth == 1) { 131 /* Direct child node of the component image node */ 132 133 /* 134 * Check subnode name, must be equal to "hash". 135 * Multiple hash nodes require unique unit node 136 * names, e.g. hash@1, hash@2, etc. 137 */ 138 if (strncmp(fit_get_name(fit, noffset, NULL), 139 FIT_HASH_NODENAME, 140 strlen(FIT_HASH_NODENAME)) != 0) { 141 /* Not a hash subnode, skip it */ 142 continue; 143 } 144 145 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 146 printf("Can't get hash algo property for '%s' hash node in '%s' image node\n", 147 fit_get_name(fit, noffset, NULL), 148 fit_get_name(fit, image_noffset, NULL)); 149 return -1; 150 } 151 152 if (calculate_hash(data, size, algo, value, 153 &value_len)) { 154 printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", 155 algo, fit_get_name(fit, noffset, NULL), 156 fit_get_name(fit, image_noffset, NULL)); 157 return -1; 158 } 159 160 if (fit_image_hash_set_value(fit, noffset, value, 161 value_len)) { 162 printf("Can't set hash value for '%s' hash node in '%s' image node\n", 163 fit_get_name(fit, noffset, NULL), 164 fit_get_name(fit, image_noffset, NULL)); 165 return -1; 166 } 167 } 168 } 169 170 return 0; 171 } 172 173 /** 174 * fit_image_hash_set_value - set hash value in requested has node 175 * @fit: pointer to the FIT format image header 176 * @noffset: hash node offset 177 * @value: hash value to be set 178 * @value_len: hash value length 179 * 180 * fit_image_hash_set_value() attempts to set hash value in a node at offset 181 * given and returns operation status to the caller. 182 * 183 * returns 184 * 0, on success 185 * -1, on failure 186 */ 187 int fit_image_hash_set_value(void *fit, int noffset, uint8_t *value, 188 int value_len) 189 { 190 int ret; 191 192 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); 193 if (ret) { 194 printf("Can't set hash '%s' property for '%s' node(%s)\n", 195 FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), 196 fdt_strerror(ret)); 197 return -1; 198 } 199 200 return 0; 201 } 202