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_set_hash_value - set hash value in requested has node 83 * @fit: pointer to the FIT format image header 84 * @noffset: hash node offset 85 * @value: hash value to be set 86 * @value_len: hash value length 87 * 88 * fit_set_hash_value() attempts to set hash value in a node at offset 89 * given and returns operation status to the caller. 90 * 91 * returns 92 * 0, on success 93 * -1, on failure 94 */ 95 static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, 96 int value_len) 97 { 98 int ret; 99 100 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); 101 if (ret) { 102 printf("Can't set hash '%s' property for '%s' node(%s)\n", 103 FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), 104 fdt_strerror(ret)); 105 return -1; 106 } 107 108 return 0; 109 } 110 111 /** 112 * fit_image_process_hash - Process a single subnode of the images/ node 113 * 114 * Check each subnode and process accordingly. For hash nodes we generate 115 * a hash of the supplised data and store it in the node. 116 * 117 * @fit: pointer to the FIT format image header 118 * @image_name: name of image being processes (used to display errors) 119 * @noffset: subnode offset 120 * @data: data to process 121 * @size: size of data in bytes 122 * @return 0 if ok, -1 on error 123 */ 124 static int fit_image_process_hash(void *fit, const char *image_name, 125 int noffset, const void *data, size_t size) 126 { 127 uint8_t value[FIT_MAX_HASH_LEN]; 128 int value_len; 129 char *algo; 130 131 /* 132 * Check subnode name, must be equal to "hash". 133 * Multiple hash nodes require unique unit node 134 * names, e.g. hash@1, hash@2, etc. 135 */ 136 if (strncmp(fit_get_name(fit, noffset, NULL), 137 FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)) != 0) 138 return 0; 139 140 if (fit_image_hash_get_algo(fit, noffset, &algo)) { 141 printf("Can't get hash algo property for '%s' hash node in '%s' image node\n", 142 fit_get_name(fit, noffset, NULL), image_name); 143 return -1; 144 } 145 146 if (calculate_hash(data, size, algo, value, &value_len)) { 147 printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", 148 algo, fit_get_name(fit, noffset, NULL), image_name); 149 return -1; 150 } 151 152 if (fit_set_hash_value(fit, noffset, value, value_len)) { 153 printf("Can't set hash value for '%s' hash node in '%s' image node\n", 154 fit_get_name(fit, noffset, NULL), image_name); 155 return -1; 156 } 157 158 return 0; 159 } 160 161 /** 162 * fit_image_set_hashes - calculate/set hashes for given component image node 163 * @fit: pointer to the FIT format image header 164 * @image_noffset: requested component image node 165 * 166 * fit_image_set_hashes() adds hash values for an component image node. All 167 * existing hash subnodes are checked, if algorithm property is set to one of 168 * the supported hash algorithms, hash value is computed and corresponding 169 * hash node property is set, for example: 170 * 171 * Input component image node structure: 172 * 173 * o image@1 (at image_noffset) 174 * | - data = [binary data] 175 * o hash@1 176 * |- algo = "sha1" 177 * 178 * Output component image node structure: 179 * 180 * o image@1 (at image_noffset) 181 * | - data = [binary data] 182 * o hash@1 183 * |- algo = "sha1" 184 * |- value = sha1(data) 185 * 186 * returns: 187 * 0 on sucess 188 * <0 on failure 189 */ 190 int fit_image_set_hashes(void *fit, int image_noffset) 191 { 192 const void *data; 193 size_t size; 194 int noffset; 195 int ndepth; 196 const char *image_name; 197 198 /* Get image data and data length */ 199 if (fit_image_get_data(fit, image_noffset, &data, &size)) { 200 printf("Can't get image data/size\n"); 201 return -1; 202 } 203 204 image_name = fit_get_name(fit, image_noffset, NULL); 205 206 /* Process all hash subnodes of the component image node */ 207 for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); 208 (noffset >= 0) && (ndepth > 0); 209 noffset = fdt_next_node(fit, noffset, &ndepth)) { 210 if (ndepth == 1) { 211 /* Direct child node of the component image node */ 212 if (fit_image_process_hash(fit, image_name, noffset, 213 data, size)) 214 return -1; 215 } 216 } 217 218 return 0; 219 } 220