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