image-host.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. #include "mkimage.h"
  28. #include <image.h>
  29. #include <version.h>
  30. /**
  31. * fit_set_hash_value - set hash value in requested has node
  32. * @fit: pointer to the FIT format image header
  33. * @noffset: hash node offset
  34. * @value: hash value to be set
  35. * @value_len: hash value length
  36. *
  37. * fit_set_hash_value() attempts to set hash value in a node at offset
  38. * given and returns operation status to the caller.
  39. *
  40. * returns
  41. * 0, on success
  42. * -1, on failure
  43. */
  44. static int fit_set_hash_value(void *fit, int noffset, uint8_t *value,
  45. int value_len)
  46. {
  47. int ret;
  48. ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
  49. if (ret) {
  50. printf("Can't set hash '%s' property for '%s' node(%s)\n",
  51. FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL),
  52. fdt_strerror(ret));
  53. return -1;
  54. }
  55. return 0;
  56. }
  57. /**
  58. * fit_image_process_hash - Process a single subnode of the images/ node
  59. *
  60. * Check each subnode and process accordingly. For hash nodes we generate
  61. * a hash of the supplised data and store it in the node.
  62. *
  63. * @fit: pointer to the FIT format image header
  64. * @image_name: name of image being processes (used to display errors)
  65. * @noffset: subnode offset
  66. * @data: data to process
  67. * @size: size of data in bytes
  68. * @return 0 if ok, -1 on error
  69. */
  70. static int fit_image_process_hash(void *fit, const char *image_name,
  71. int noffset, const void *data, size_t size)
  72. {
  73. uint8_t value[FIT_MAX_HASH_LEN];
  74. const char *node_name;
  75. int value_len;
  76. char *algo;
  77. node_name = fit_get_name(fit, noffset, NULL);
  78. if (fit_image_hash_get_algo(fit, noffset, &algo)) {
  79. printf("Can't get hash algo property for '%s' hash node in '%s' image node\n",
  80. node_name, image_name);
  81. return -1;
  82. }
  83. if (calculate_hash(data, size, algo, value, &value_len)) {
  84. printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n",
  85. algo, node_name, image_name);
  86. return -1;
  87. }
  88. if (fit_set_hash_value(fit, noffset, value, value_len)) {
  89. printf("Can't set hash value for '%s' hash node in '%s' image node\n",
  90. node_name, image_name);
  91. return -1;
  92. }
  93. return 0;
  94. }
  95. /**
  96. * fit_image_write_sig() - write the signature to a FIT
  97. *
  98. * This writes the signature and signer data to the FIT.
  99. *
  100. * @fit: pointer to the FIT format image header
  101. * @noffset: hash node offset
  102. * @value: signature value to be set
  103. * @value_len: signature value length
  104. * @comment: Text comment to write (NULL for none)
  105. *
  106. * returns
  107. * 0, on success
  108. * -FDT_ERR_..., on failure
  109. */
  110. static int fit_image_write_sig(void *fit, int noffset, uint8_t *value,
  111. int value_len, const char *comment, const char *region_prop,
  112. int region_proplen)
  113. {
  114. int string_size;
  115. int ret;
  116. /*
  117. * Get the current string size, before we update the FIT and add
  118. * more
  119. */
  120. string_size = fdt_size_dt_strings(fit);
  121. ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
  122. if (!ret) {
  123. ret = fdt_setprop_string(fit, noffset, "signer-name",
  124. "mkimage");
  125. }
  126. if (!ret) {
  127. ret = fdt_setprop_string(fit, noffset, "signer-version",
  128. PLAIN_VERSION);
  129. }
  130. if (comment && !ret)
  131. ret = fdt_setprop_string(fit, noffset, "comment", comment);
  132. if (!ret)
  133. ret = fit_set_timestamp(fit, noffset, time(NULL));
  134. if (region_prop && !ret) {
  135. uint32_t strdata[2];
  136. ret = fdt_setprop(fit, noffset, "hashed-nodes",
  137. region_prop, region_proplen);
  138. strdata[0] = 0;
  139. strdata[1] = cpu_to_fdt32(string_size);
  140. if (!ret) {
  141. ret = fdt_setprop(fit, noffset, "hashed-strings",
  142. strdata, sizeof(strdata));
  143. }
  144. }
  145. return ret;
  146. }
  147. static int fit_image_setup_sig(struct image_sign_info *info,
  148. const char *keydir, void *fit, const char *image_name,
  149. int noffset, const char *require_keys)
  150. {
  151. const char *node_name;
  152. char *algo_name;
  153. node_name = fit_get_name(fit, noffset, NULL);
  154. if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
  155. printf("Can't get algo property for '%s' signature node in '%s' image node\n",
  156. node_name, image_name);
  157. return -1;
  158. }
  159. memset(info, '\0', sizeof(*info));
  160. info->keydir = keydir;
  161. info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
  162. info->fit = fit;
  163. info->node_offset = noffset;
  164. info->algo = image_get_sig_algo(algo_name);
  165. info->require_keys = require_keys;
  166. if (!info->algo) {
  167. printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
  168. algo_name, node_name, image_name);
  169. return -1;
  170. }
  171. return 0;
  172. }
  173. /**
  174. * fit_image_process_sig- Process a single subnode of the images/ node
  175. *
  176. * Check each subnode and process accordingly. For signature nodes we
  177. * generate a signed hash of the supplised data and store it in the node.
  178. *
  179. * @keydir: Directory containing keys to use for signing
  180. * @keydest: Destination FDT blob to write public keys into
  181. * @fit: pointer to the FIT format image header
  182. * @image_name: name of image being processes (used to display errors)
  183. * @noffset: subnode offset
  184. * @data: data to process
  185. * @size: size of data in bytes
  186. * @comment: Comment to add to signature nodes
  187. * @require_keys: Mark all keys as 'required'
  188. * @return 0 if ok, -1 on error
  189. */
  190. static int fit_image_process_sig(const char *keydir, void *keydest,
  191. void *fit, const char *image_name,
  192. int noffset, const void *data, size_t size,
  193. const char *comment, int require_keys)
  194. {
  195. struct image_sign_info info;
  196. struct image_region region;
  197. const char *node_name;
  198. uint8_t *value;
  199. uint value_len;
  200. int ret;
  201. if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
  202. require_keys ? "image" : NULL))
  203. return -1;
  204. node_name = fit_get_name(fit, noffset, NULL);
  205. region.data = data;
  206. region.size = size;
  207. ret = info.algo->sign(&info, &region, 1, &value, &value_len);
  208. if (ret) {
  209. printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
  210. node_name, image_name, ret);
  211. /* We allow keys to be missing */
  212. if (ret == -ENOENT)
  213. return 0;
  214. return -1;
  215. }
  216. ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
  217. NULL, 0);
  218. if (ret) {
  219. printf("Can't write signature for '%s' signature node in '%s' image node: %s\n",
  220. node_name, image_name, fdt_strerror(ret));
  221. return -1;
  222. }
  223. free(value);
  224. /* Get keyname again, as FDT has changed and invalidated our pointer */
  225. info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
  226. /* Write the public key into the supplied FDT file */
  227. if (keydest && info.algo->add_verify_data(&info, keydest)) {
  228. printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
  229. node_name, image_name);
  230. return -1;
  231. }
  232. return 0;
  233. }
  234. /**
  235. * fit_image_add_verification_data() - calculate/set verig. data for image node
  236. *
  237. * This adds hash and signature values for an component image node.
  238. *
  239. * All existing hash subnodes are checked, if algorithm property is set to
  240. * one of the supported hash algorithms, hash value is computed and
  241. * corresponding hash node property is set, for example:
  242. *
  243. * Input component image node structure:
  244. *
  245. * o image@1 (at image_noffset)
  246. * | - data = [binary data]
  247. * o hash@1
  248. * |- algo = "sha1"
  249. *
  250. * Output component image node structure:
  251. *
  252. * o image@1 (at image_noffset)
  253. * | - data = [binary data]
  254. * o hash@1
  255. * |- algo = "sha1"
  256. * |- value = sha1(data)
  257. *
  258. * For signature details, please see doc/uImage.FIT/signature.txt
  259. *
  260. * @keydir Directory containing *.key and *.crt files (or NULL)
  261. * @keydest FDT Blob to write public keys into (NULL if none)
  262. * @fit: Pointer to the FIT format image header
  263. * @image_noffset: Requested component image node
  264. * @comment: Comment to add to signature nodes
  265. * @require_keys: Mark all keys as 'required'
  266. * @return: 0 on success, <0 on failure
  267. */
  268. int fit_image_add_verification_data(const char *keydir, void *keydest,
  269. void *fit, int image_noffset, const char *comment,
  270. int require_keys)
  271. {
  272. const char *image_name;
  273. const void *data;
  274. size_t size;
  275. int noffset;
  276. /* Get image data and data length */
  277. if (fit_image_get_data(fit, image_noffset, &data, &size)) {
  278. printf("Can't get image data/size\n");
  279. return -1;
  280. }
  281. image_name = fit_get_name(fit, image_noffset, NULL);
  282. /* Process all hash subnodes of the component image node */
  283. for (noffset = fdt_first_subnode(fit, image_noffset);
  284. noffset >= 0;
  285. noffset = fdt_next_subnode(fit, noffset)) {
  286. const char *node_name;
  287. int ret = 0;
  288. /*
  289. * Check subnode name, must be equal to "hash" or "signature".
  290. * Multiple hash nodes require unique unit node
  291. * names, e.g. hash@1, hash@2, signature@1, etc.
  292. */
  293. node_name = fit_get_name(fit, noffset, NULL);
  294. if (!strncmp(node_name, FIT_HASH_NODENAME,
  295. strlen(FIT_HASH_NODENAME))) {
  296. ret = fit_image_process_hash(fit, image_name, noffset,
  297. data, size);
  298. } else if (IMAGE_ENABLE_SIGN && keydir &&
  299. !strncmp(node_name, FIT_SIG_NODENAME,
  300. strlen(FIT_SIG_NODENAME))) {
  301. ret = fit_image_process_sig(keydir, keydest,
  302. fit, image_name, noffset, data, size,
  303. comment, require_keys);
  304. }
  305. if (ret)
  306. return -1;
  307. }
  308. return 0;
  309. }
  310. int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
  311. const char *comment, int require_keys)
  312. {
  313. int images_noffset;
  314. int noffset;
  315. int ret;
  316. /* Find images parent node offset */
  317. images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
  318. if (images_noffset < 0) {
  319. printf("Can't find images parent node '%s' (%s)\n",
  320. FIT_IMAGES_PATH, fdt_strerror(images_noffset));
  321. return images_noffset;
  322. }
  323. /* Process its subnodes, print out component images details */
  324. for (noffset = fdt_first_subnode(fit, images_noffset);
  325. noffset >= 0;
  326. noffset = fdt_next_subnode(fit, noffset)) {
  327. /*
  328. * Direct child node of the images parent node,
  329. * i.e. component image node.
  330. */
  331. ret = fit_image_add_verification_data(keydir, keydest,
  332. fit, noffset, comment, require_keys);
  333. if (ret)
  334. return ret;
  335. }
  336. return 0;
  337. }