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