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