main.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Copyright (c) 2019, Linaro Limited. All rights reserved.
  3. * Author: Sumit Garg <sumit.garg@linaro.org>
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. */
  7. #include <assert.h>
  8. #include <ctype.h>
  9. #include <getopt.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <stdbool.h>
  14. #include <openssl/conf.h>
  15. #include "cmd_opt.h"
  16. #include "debug.h"
  17. #include "encrypt.h"
  18. #include "firmware_encrypted.h"
  19. #define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0])))
  20. #define HELP_OPT_MAX_LEN 128
  21. /* Global options */
  22. /* Info messages created in the Makefile */
  23. extern const char build_msg[];
  24. static char *key_algs_str[] = {
  25. [KEY_ALG_GCM] = "gcm",
  26. };
  27. static void print_help(const char *cmd, const struct option *long_opt)
  28. {
  29. int rem, i = 0;
  30. const struct option *opt;
  31. char line[HELP_OPT_MAX_LEN];
  32. char *p;
  33. assert(cmd != NULL);
  34. assert(long_opt != NULL);
  35. printf("\n\n");
  36. printf("The firmware encryption tool loads the binary image and\n"
  37. "outputs encrypted binary image using an encryption key\n"
  38. "provided as an input hex string.\n");
  39. printf("\n");
  40. printf("Usage:\n");
  41. printf("\t%s [OPTIONS]\n\n", cmd);
  42. printf("Available options:\n");
  43. opt = long_opt;
  44. while (opt->name) {
  45. p = line;
  46. rem = HELP_OPT_MAX_LEN;
  47. if (isalpha(opt->val)) {
  48. /* Short format */
  49. sprintf(p, "-%c,", (char)opt->val);
  50. p += 3;
  51. rem -= 3;
  52. }
  53. snprintf(p, rem, "--%s %s", opt->name,
  54. (opt->has_arg == required_argument) ? "<arg>" : "");
  55. printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
  56. opt++;
  57. i++;
  58. }
  59. printf("\n");
  60. }
  61. static int get_key_alg(const char *key_alg_str)
  62. {
  63. int i;
  64. for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
  65. if (strcmp(key_alg_str, key_algs_str[i]) == 0) {
  66. return i;
  67. }
  68. }
  69. return -1;
  70. }
  71. static void parse_fw_enc_status_flag(const char *arg,
  72. unsigned short *fw_enc_status)
  73. {
  74. unsigned long flag;
  75. char *endptr;
  76. flag = strtoul(arg, &endptr, 16);
  77. if (*endptr != '\0' || flag > FW_ENC_WITH_BSSK) {
  78. ERROR("Invalid fw_enc_status flag '%s'\n", arg);
  79. exit(1);
  80. }
  81. *fw_enc_status = flag & FW_ENC_STATUS_FLAG_MASK;
  82. }
  83. /* Common command line options */
  84. static const cmd_opt_t common_cmd_opt[] = {
  85. {
  86. { "help", no_argument, NULL, 'h' },
  87. "Print this message and exit"
  88. },
  89. {
  90. { "fw-enc-status", required_argument, NULL, 'f' },
  91. "Firmware encryption status flag (with SSK=0 or BSSK=1)."
  92. },
  93. {
  94. { "key-alg", required_argument, NULL, 'a' },
  95. "Encryption key algorithm: 'gcm' (default)"
  96. },
  97. {
  98. { "key", required_argument, NULL, 'k' },
  99. "Encryption key (for supported algorithm)."
  100. },
  101. {
  102. { "nonce", required_argument, NULL, 'n' },
  103. "Nonce or Initialization Vector (for supported algorithm)."
  104. },
  105. {
  106. { "in", required_argument, NULL, 'i' },
  107. "Input filename to be encrypted."
  108. },
  109. {
  110. { "out", required_argument, NULL, 'o' },
  111. "Encrypted output filename."
  112. },
  113. };
  114. int main(int argc, char *argv[])
  115. {
  116. int i, key_alg, ret;
  117. int c, opt_idx = 0;
  118. const struct option *cmd_opt;
  119. char *key = NULL;
  120. char *nonce = NULL;
  121. char *in_fn = NULL;
  122. char *out_fn = NULL;
  123. unsigned short fw_enc_status = 0;
  124. NOTICE("Firmware Encryption Tool: %s\n", build_msg);
  125. /* Set default options */
  126. key_alg = KEY_ALG_GCM;
  127. /* Add common command line options */
  128. for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
  129. cmd_opt_add(&common_cmd_opt[i]);
  130. }
  131. /* Get the command line options populated during the initialization */
  132. cmd_opt = cmd_opt_get_array();
  133. while (1) {
  134. /* getopt_long stores the option index here. */
  135. c = getopt_long(argc, argv, "a:f:hi:k:n:o:", cmd_opt, &opt_idx);
  136. /* Detect the end of the options. */
  137. if (c == -1) {
  138. break;
  139. }
  140. switch (c) {
  141. case 'a':
  142. key_alg = get_key_alg(optarg);
  143. if (key_alg < 0) {
  144. ERROR("Invalid key algorithm '%s'\n", optarg);
  145. exit(1);
  146. }
  147. break;
  148. case 'f':
  149. parse_fw_enc_status_flag(optarg, &fw_enc_status);
  150. break;
  151. case 'k':
  152. key = optarg;
  153. break;
  154. case 'i':
  155. in_fn = optarg;
  156. break;
  157. case 'o':
  158. out_fn = optarg;
  159. break;
  160. case 'n':
  161. nonce = optarg;
  162. break;
  163. case 'h':
  164. print_help(argv[0], cmd_opt);
  165. exit(0);
  166. case '?':
  167. default:
  168. print_help(argv[0], cmd_opt);
  169. exit(1);
  170. }
  171. }
  172. if (!key) {
  173. ERROR("Key must not be NULL\n");
  174. exit(1);
  175. }
  176. if (!nonce) {
  177. ERROR("Nonce must not be NULL\n");
  178. exit(1);
  179. }
  180. if (!in_fn) {
  181. ERROR("Input filename must not be NULL\n");
  182. exit(1);
  183. }
  184. if (!out_fn) {
  185. ERROR("Output filename must not be NULL\n");
  186. exit(1);
  187. }
  188. ret = encrypt_file(fw_enc_status, key_alg, key, nonce, in_fn, out_fn);
  189. CRYPTO_cleanup_all_ex_data();
  190. return ret;
  191. }