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