xref: /rk3399_ARM-atf/tools/encrypt_fw/src/main.c (revision 415049a25f5908e7682d13c2b65cd4dda15c5d22)
190aa901fSSumit Garg /*
2*415049a2SChris Kay  * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
390aa901fSSumit Garg  * Copyright (c) 2019, Linaro Limited. All rights reserved.
490aa901fSSumit Garg  * Author: Sumit Garg <sumit.garg@linaro.org>
590aa901fSSumit Garg  *
690aa901fSSumit Garg  * SPDX-License-Identifier: BSD-3-Clause
790aa901fSSumit Garg  */
890aa901fSSumit Garg 
990aa901fSSumit Garg #include <assert.h>
1090aa901fSSumit Garg #include <ctype.h>
1190aa901fSSumit Garg #include <getopt.h>
1290aa901fSSumit Garg #include <stdio.h>
1390aa901fSSumit Garg #include <stdlib.h>
1490aa901fSSumit Garg #include <string.h>
1590aa901fSSumit Garg #include <stdbool.h>
1690aa901fSSumit Garg 
1790aa901fSSumit Garg #include <openssl/conf.h>
1890aa901fSSumit Garg 
1990aa901fSSumit Garg #include "cmd_opt.h"
2090aa901fSSumit Garg #include "debug.h"
2190aa901fSSumit Garg #include "encrypt.h"
2290aa901fSSumit Garg #include "firmware_encrypted.h"
2390aa901fSSumit Garg 
2490aa901fSSumit Garg #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
2590aa901fSSumit Garg #define HELP_OPT_MAX_LEN		128
2690aa901fSSumit Garg 
2790aa901fSSumit Garg /* Global options */
2890aa901fSSumit Garg 
29*415049a2SChris Kay static const char build_msg[] = "Built : " __TIME__ ", " __DATE__;
3090aa901fSSumit Garg 
3190aa901fSSumit Garg static char *key_algs_str[] = {
3290aa901fSSumit Garg 	[KEY_ALG_GCM] = "gcm",
3390aa901fSSumit Garg };
3490aa901fSSumit Garg 
3590aa901fSSumit Garg static void print_help(const char *cmd, const struct option *long_opt)
3690aa901fSSumit Garg {
3790aa901fSSumit Garg 	int rem, i = 0;
3890aa901fSSumit Garg 	const struct option *opt;
3990aa901fSSumit Garg 	char line[HELP_OPT_MAX_LEN];
4090aa901fSSumit Garg 	char *p;
4190aa901fSSumit Garg 
4290aa901fSSumit Garg 	assert(cmd != NULL);
4390aa901fSSumit Garg 	assert(long_opt != NULL);
4490aa901fSSumit Garg 
4590aa901fSSumit Garg 	printf("\n\n");
4690aa901fSSumit Garg 	printf("The firmware encryption tool loads the binary image and\n"
4790aa901fSSumit Garg 	       "outputs encrypted binary image using an encryption key\n"
4890aa901fSSumit Garg 	       "provided as an input hex string.\n");
4990aa901fSSumit Garg 	printf("\n");
5090aa901fSSumit Garg 	printf("Usage:\n");
5190aa901fSSumit Garg 	printf("\t%s [OPTIONS]\n\n", cmd);
5290aa901fSSumit Garg 
5390aa901fSSumit Garg 	printf("Available options:\n");
5490aa901fSSumit Garg 	opt = long_opt;
5590aa901fSSumit Garg 	while (opt->name) {
5690aa901fSSumit Garg 		p = line;
5790aa901fSSumit Garg 		rem = HELP_OPT_MAX_LEN;
5890aa901fSSumit Garg 		if (isalpha(opt->val)) {
5990aa901fSSumit Garg 			/* Short format */
6090aa901fSSumit Garg 			sprintf(p, "-%c,", (char)opt->val);
6190aa901fSSumit Garg 			p += 3;
6290aa901fSSumit Garg 			rem -= 3;
6390aa901fSSumit Garg 		}
6490aa901fSSumit Garg 		snprintf(p, rem, "--%s %s", opt->name,
6590aa901fSSumit Garg 			 (opt->has_arg == required_argument) ? "<arg>" : "");
6690aa901fSSumit Garg 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
6790aa901fSSumit Garg 		opt++;
6890aa901fSSumit Garg 		i++;
6990aa901fSSumit Garg 	}
7090aa901fSSumit Garg 	printf("\n");
7190aa901fSSumit Garg }
7290aa901fSSumit Garg 
7390aa901fSSumit Garg static int get_key_alg(const char *key_alg_str)
7490aa901fSSumit Garg {
7590aa901fSSumit Garg 	int i;
7690aa901fSSumit Garg 
7790aa901fSSumit Garg 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
7890aa901fSSumit Garg 		if (strcmp(key_alg_str, key_algs_str[i]) == 0) {
7990aa901fSSumit Garg 			return i;
8090aa901fSSumit Garg 		}
8190aa901fSSumit Garg 	}
8290aa901fSSumit Garg 
8390aa901fSSumit Garg 	return -1;
8490aa901fSSumit Garg }
8590aa901fSSumit Garg 
8690aa901fSSumit Garg static void parse_fw_enc_status_flag(const char *arg,
8790aa901fSSumit Garg 				     unsigned short *fw_enc_status)
8890aa901fSSumit Garg {
8990aa901fSSumit Garg 	unsigned long flag;
9090aa901fSSumit Garg 	char *endptr;
9190aa901fSSumit Garg 
9290aa901fSSumit Garg 	flag = strtoul(arg, &endptr, 16);
9390aa901fSSumit Garg 	if (*endptr != '\0' || flag > FW_ENC_WITH_BSSK) {
9490aa901fSSumit Garg 		ERROR("Invalid fw_enc_status flag '%s'\n", arg);
9590aa901fSSumit Garg 		exit(1);
9690aa901fSSumit Garg 	}
9790aa901fSSumit Garg 
9890aa901fSSumit Garg 	*fw_enc_status = flag & FW_ENC_STATUS_FLAG_MASK;
9990aa901fSSumit Garg }
10090aa901fSSumit Garg 
10190aa901fSSumit Garg /* Common command line options */
10290aa901fSSumit Garg static const cmd_opt_t common_cmd_opt[] = {
10390aa901fSSumit Garg 	{
10490aa901fSSumit Garg 		{ "help", no_argument, NULL, 'h' },
10590aa901fSSumit Garg 		"Print this message and exit"
10690aa901fSSumit Garg 	},
10790aa901fSSumit Garg 	{
10890aa901fSSumit Garg 		{ "fw-enc-status", required_argument, NULL, 'f' },
10990aa901fSSumit Garg 		"Firmware encryption status flag (with SSK=0 or BSSK=1)."
11090aa901fSSumit Garg 	},
11190aa901fSSumit Garg 	{
11290aa901fSSumit Garg 		{ "key-alg", required_argument, NULL, 'a' },
11390aa901fSSumit Garg 		"Encryption key algorithm: 'gcm' (default)"
11490aa901fSSumit Garg 	},
11590aa901fSSumit Garg 	{
11690aa901fSSumit Garg 		{ "key", required_argument, NULL, 'k' },
11790aa901fSSumit Garg 		"Encryption key (for supported algorithm)."
11890aa901fSSumit Garg 	},
11990aa901fSSumit Garg 	{
12090aa901fSSumit Garg 		{ "nonce", required_argument, NULL, 'n' },
12190aa901fSSumit Garg 		"Nonce or Initialization Vector (for supported algorithm)."
12290aa901fSSumit Garg 	},
12390aa901fSSumit Garg 	{
12490aa901fSSumit Garg 		{ "in", required_argument, NULL, 'i' },
12590aa901fSSumit Garg 		"Input filename to be encrypted."
12690aa901fSSumit Garg 	},
12790aa901fSSumit Garg 	{
12890aa901fSSumit Garg 		{ "out", required_argument, NULL, 'o' },
12990aa901fSSumit Garg 		"Encrypted output filename."
13090aa901fSSumit Garg 	},
13190aa901fSSumit Garg };
13290aa901fSSumit Garg 
13390aa901fSSumit Garg int main(int argc, char *argv[])
13490aa901fSSumit Garg {
13590aa901fSSumit Garg 	int i, key_alg, ret;
13690aa901fSSumit Garg 	int c, opt_idx = 0;
13790aa901fSSumit Garg 	const struct option *cmd_opt;
13890aa901fSSumit Garg 	char *key = NULL;
13990aa901fSSumit Garg 	char *nonce = NULL;
14090aa901fSSumit Garg 	char *in_fn = NULL;
14190aa901fSSumit Garg 	char *out_fn = NULL;
14290aa901fSSumit Garg 	unsigned short fw_enc_status = 0;
14390aa901fSSumit Garg 
14490aa901fSSumit Garg 	NOTICE("Firmware Encryption Tool: %s\n", build_msg);
14590aa901fSSumit Garg 
14690aa901fSSumit Garg 	/* Set default options */
14790aa901fSSumit Garg 	key_alg = KEY_ALG_GCM;
14890aa901fSSumit Garg 
14990aa901fSSumit Garg 	/* Add common command line options */
15090aa901fSSumit Garg 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
15190aa901fSSumit Garg 		cmd_opt_add(&common_cmd_opt[i]);
15290aa901fSSumit Garg 	}
15390aa901fSSumit Garg 
15490aa901fSSumit Garg 	/* Get the command line options populated during the initialization */
15590aa901fSSumit Garg 	cmd_opt = cmd_opt_get_array();
15690aa901fSSumit Garg 
15790aa901fSSumit Garg 	while (1) {
15890aa901fSSumit Garg 		/* getopt_long stores the option index here. */
15990aa901fSSumit Garg 		c = getopt_long(argc, argv, "a:f:hi:k:n:o:", cmd_opt, &opt_idx);
16090aa901fSSumit Garg 
16190aa901fSSumit Garg 		/* Detect the end of the options. */
16290aa901fSSumit Garg 		if (c == -1) {
16390aa901fSSumit Garg 			break;
16490aa901fSSumit Garg 		}
16590aa901fSSumit Garg 
16690aa901fSSumit Garg 		switch (c) {
16790aa901fSSumit Garg 		case 'a':
16890aa901fSSumit Garg 			key_alg = get_key_alg(optarg);
16990aa901fSSumit Garg 			if (key_alg < 0) {
17090aa901fSSumit Garg 				ERROR("Invalid key algorithm '%s'\n", optarg);
17190aa901fSSumit Garg 				exit(1);
17290aa901fSSumit Garg 			}
17390aa901fSSumit Garg 			break;
17490aa901fSSumit Garg 		case 'f':
17590aa901fSSumit Garg 			parse_fw_enc_status_flag(optarg, &fw_enc_status);
17690aa901fSSumit Garg 			break;
17790aa901fSSumit Garg 		case 'k':
17890aa901fSSumit Garg 			key = optarg;
17990aa901fSSumit Garg 			break;
18090aa901fSSumit Garg 		case 'i':
18190aa901fSSumit Garg 			in_fn = optarg;
18290aa901fSSumit Garg 			break;
18390aa901fSSumit Garg 		case 'o':
18490aa901fSSumit Garg 			out_fn = optarg;
18590aa901fSSumit Garg 			break;
18690aa901fSSumit Garg 		case 'n':
18790aa901fSSumit Garg 			nonce = optarg;
18890aa901fSSumit Garg 			break;
18990aa901fSSumit Garg 		case 'h':
19090aa901fSSumit Garg 			print_help(argv[0], cmd_opt);
19190aa901fSSumit Garg 			exit(0);
19290aa901fSSumit Garg 		case '?':
19390aa901fSSumit Garg 		default:
19490aa901fSSumit Garg 			print_help(argv[0], cmd_opt);
19590aa901fSSumit Garg 			exit(1);
19690aa901fSSumit Garg 		}
19790aa901fSSumit Garg 	}
19890aa901fSSumit Garg 
19990aa901fSSumit Garg 	if (!key) {
20090aa901fSSumit Garg 		ERROR("Key must not be NULL\n");
20190aa901fSSumit Garg 		exit(1);
20290aa901fSSumit Garg 	}
20390aa901fSSumit Garg 
20490aa901fSSumit Garg 	if (!nonce) {
20590aa901fSSumit Garg 		ERROR("Nonce must not be NULL\n");
20690aa901fSSumit Garg 		exit(1);
20790aa901fSSumit Garg 	}
20890aa901fSSumit Garg 
20990aa901fSSumit Garg 	if (!in_fn) {
21090aa901fSSumit Garg 		ERROR("Input filename must not be NULL\n");
21190aa901fSSumit Garg 		exit(1);
21290aa901fSSumit Garg 	}
21390aa901fSSumit Garg 
21490aa901fSSumit Garg 	if (!out_fn) {
21590aa901fSSumit Garg 		ERROR("Output filename must not be NULL\n");
21690aa901fSSumit Garg 		exit(1);
21790aa901fSSumit Garg 	}
21890aa901fSSumit Garg 
21990aa901fSSumit Garg 	ret = encrypt_file(fw_enc_status, key_alg, key, nonce, in_fn, out_fn);
22090aa901fSSumit Garg 
22190aa901fSSumit Garg 	CRYPTO_cleanup_all_ex_data();
22290aa901fSSumit Garg 
22390aa901fSSumit Garg 	return ret;
22490aa901fSSumit Garg }
225