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