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