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