xref: /aosp_15_r20/external/arm-trusted-firmware/tools/cert_create/src/main.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <ctype.h>
9*54fd6939SJiyong Park #include <getopt.h>
10*54fd6939SJiyong Park #include <stdio.h>
11*54fd6939SJiyong Park #include <stdlib.h>
12*54fd6939SJiyong Park #include <string.h>
13*54fd6939SJiyong Park #include <stdbool.h>
14*54fd6939SJiyong Park 
15*54fd6939SJiyong Park #include <openssl/conf.h>
16*54fd6939SJiyong Park #include <openssl/engine.h>
17*54fd6939SJiyong Park #include <openssl/err.h>
18*54fd6939SJiyong Park #include <openssl/pem.h>
19*54fd6939SJiyong Park #include <openssl/sha.h>
20*54fd6939SJiyong Park #include <openssl/x509v3.h>
21*54fd6939SJiyong Park 
22*54fd6939SJiyong Park #include "cert.h"
23*54fd6939SJiyong Park #include "cmd_opt.h"
24*54fd6939SJiyong Park #include "debug.h"
25*54fd6939SJiyong Park #include "ext.h"
26*54fd6939SJiyong Park #include "key.h"
27*54fd6939SJiyong Park #include "sha.h"
28*54fd6939SJiyong Park 
29*54fd6939SJiyong Park /*
30*54fd6939SJiyong Park  * Helper macros to simplify the code. This macro assigns the return value of
31*54fd6939SJiyong Park  * the 'fn' function to 'v' and exits if the value is NULL.
32*54fd6939SJiyong Park  */
33*54fd6939SJiyong Park #define CHECK_NULL(v, fn) \
34*54fd6939SJiyong Park 	do { \
35*54fd6939SJiyong Park 		v = fn; \
36*54fd6939SJiyong Park 		if (v == NULL) { \
37*54fd6939SJiyong Park 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
38*54fd6939SJiyong Park 			exit(1); \
39*54fd6939SJiyong Park 		} \
40*54fd6939SJiyong Park 	} while (0)
41*54fd6939SJiyong Park 
42*54fd6939SJiyong Park /*
43*54fd6939SJiyong Park  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
44*54fd6939SJiyong Park  * NID is undefined.
45*54fd6939SJiyong Park  */
46*54fd6939SJiyong Park #define CHECK_OID(v, oid) \
47*54fd6939SJiyong Park 	do { \
48*54fd6939SJiyong Park 		v = OBJ_txt2nid(oid); \
49*54fd6939SJiyong Park 		if (v == NID_undef) { \
50*54fd6939SJiyong Park 			ERROR("Cannot find extension %s\n", oid); \
51*54fd6939SJiyong Park 			exit(1); \
52*54fd6939SJiyong Park 		} \
53*54fd6939SJiyong Park 	} while (0)
54*54fd6939SJiyong Park 
55*54fd6939SJiyong Park #define MAX_FILENAME_LEN		1024
56*54fd6939SJiyong Park #define VAL_DAYS			7300
57*54fd6939SJiyong Park #define ID_TO_BIT_MASK(id)		(1 << id)
58*54fd6939SJiyong Park #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
59*54fd6939SJiyong Park #define HELP_OPT_MAX_LEN		128
60*54fd6939SJiyong Park 
61*54fd6939SJiyong Park /* Global options */
62*54fd6939SJiyong Park static int key_alg;
63*54fd6939SJiyong Park static int hash_alg;
64*54fd6939SJiyong Park static int key_size;
65*54fd6939SJiyong Park static int new_keys;
66*54fd6939SJiyong Park static int save_keys;
67*54fd6939SJiyong Park static int print_cert;
68*54fd6939SJiyong Park 
69*54fd6939SJiyong Park /* Info messages created in the Makefile */
70*54fd6939SJiyong Park extern const char build_msg[];
71*54fd6939SJiyong Park extern const char platform_msg[];
72*54fd6939SJiyong Park 
73*54fd6939SJiyong Park 
strdup(const char * str)74*54fd6939SJiyong Park static char *strdup(const char *str)
75*54fd6939SJiyong Park {
76*54fd6939SJiyong Park 	int n = strlen(str) + 1;
77*54fd6939SJiyong Park 	char *dup = malloc(n);
78*54fd6939SJiyong Park 	if (dup) {
79*54fd6939SJiyong Park 		strcpy(dup, str);
80*54fd6939SJiyong Park 	}
81*54fd6939SJiyong Park 	return dup;
82*54fd6939SJiyong Park }
83*54fd6939SJiyong Park 
84*54fd6939SJiyong Park static const char *key_algs_str[] = {
85*54fd6939SJiyong Park 	[KEY_ALG_RSA] = "rsa",
86*54fd6939SJiyong Park #ifndef OPENSSL_NO_EC
87*54fd6939SJiyong Park 	[KEY_ALG_ECDSA] = "ecdsa"
88*54fd6939SJiyong Park #endif /* OPENSSL_NO_EC */
89*54fd6939SJiyong Park };
90*54fd6939SJiyong Park 
91*54fd6939SJiyong Park static const char *hash_algs_str[] = {
92*54fd6939SJiyong Park 	[HASH_ALG_SHA256] = "sha256",
93*54fd6939SJiyong Park 	[HASH_ALG_SHA384] = "sha384",
94*54fd6939SJiyong Park 	[HASH_ALG_SHA512] = "sha512",
95*54fd6939SJiyong Park };
96*54fd6939SJiyong Park 
print_help(const char * cmd,const struct option * long_opt)97*54fd6939SJiyong Park static void print_help(const char *cmd, const struct option *long_opt)
98*54fd6939SJiyong Park {
99*54fd6939SJiyong Park 	int rem, i = 0;
100*54fd6939SJiyong Park 	const struct option *opt;
101*54fd6939SJiyong Park 	char line[HELP_OPT_MAX_LEN];
102*54fd6939SJiyong Park 	char *p;
103*54fd6939SJiyong Park 
104*54fd6939SJiyong Park 	assert(cmd != NULL);
105*54fd6939SJiyong Park 	assert(long_opt != NULL);
106*54fd6939SJiyong Park 
107*54fd6939SJiyong Park 	printf("\n\n");
108*54fd6939SJiyong Park 	printf("The certificate generation tool loads the binary images and\n"
109*54fd6939SJiyong Park 	       "optionally the RSA keys, and outputs the key and content\n"
110*54fd6939SJiyong Park 	       "certificates properly signed to implement the chain of trust.\n"
111*54fd6939SJiyong Park 	       "If keys are provided, they must be in PEM format.\n"
112*54fd6939SJiyong Park 	       "Certificates are generated in DER format.\n");
113*54fd6939SJiyong Park 	printf("\n");
114*54fd6939SJiyong Park 	printf("Usage:\n");
115*54fd6939SJiyong Park 	printf("\t%s [OPTIONS]\n\n", cmd);
116*54fd6939SJiyong Park 
117*54fd6939SJiyong Park 	printf("Available options:\n");
118*54fd6939SJiyong Park 	opt = long_opt;
119*54fd6939SJiyong Park 	while (opt->name) {
120*54fd6939SJiyong Park 		p = line;
121*54fd6939SJiyong Park 		rem = HELP_OPT_MAX_LEN;
122*54fd6939SJiyong Park 		if (isalpha(opt->val)) {
123*54fd6939SJiyong Park 			/* Short format */
124*54fd6939SJiyong Park 			sprintf(p, "-%c,", (char)opt->val);
125*54fd6939SJiyong Park 			p += 3;
126*54fd6939SJiyong Park 			rem -= 3;
127*54fd6939SJiyong Park 		}
128*54fd6939SJiyong Park 		snprintf(p, rem, "--%s %s", opt->name,
129*54fd6939SJiyong Park 			 (opt->has_arg == required_argument) ? "<arg>" : "");
130*54fd6939SJiyong Park 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
131*54fd6939SJiyong Park 		opt++;
132*54fd6939SJiyong Park 		i++;
133*54fd6939SJiyong Park 	}
134*54fd6939SJiyong Park 	printf("\n");
135*54fd6939SJiyong Park }
136*54fd6939SJiyong Park 
get_key_alg(const char * key_alg_str)137*54fd6939SJiyong Park static int get_key_alg(const char *key_alg_str)
138*54fd6939SJiyong Park {
139*54fd6939SJiyong Park 	int i;
140*54fd6939SJiyong Park 
141*54fd6939SJiyong Park 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
142*54fd6939SJiyong Park 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
143*54fd6939SJiyong Park 			return i;
144*54fd6939SJiyong Park 		}
145*54fd6939SJiyong Park 	}
146*54fd6939SJiyong Park 
147*54fd6939SJiyong Park 	return -1;
148*54fd6939SJiyong Park }
149*54fd6939SJiyong Park 
get_key_size(const char * key_size_str)150*54fd6939SJiyong Park static int get_key_size(const char *key_size_str)
151*54fd6939SJiyong Park {
152*54fd6939SJiyong Park 	char *end;
153*54fd6939SJiyong Park 	long key_size;
154*54fd6939SJiyong Park 
155*54fd6939SJiyong Park 	key_size = strtol(key_size_str, &end, 10);
156*54fd6939SJiyong Park 	if (*end != '\0')
157*54fd6939SJiyong Park 		return -1;
158*54fd6939SJiyong Park 
159*54fd6939SJiyong Park 	return key_size;
160*54fd6939SJiyong Park }
161*54fd6939SJiyong Park 
get_hash_alg(const char * hash_alg_str)162*54fd6939SJiyong Park static int get_hash_alg(const char *hash_alg_str)
163*54fd6939SJiyong Park {
164*54fd6939SJiyong Park 	int i;
165*54fd6939SJiyong Park 
166*54fd6939SJiyong Park 	for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
167*54fd6939SJiyong Park 		if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
168*54fd6939SJiyong Park 			return i;
169*54fd6939SJiyong Park 		}
170*54fd6939SJiyong Park 	}
171*54fd6939SJiyong Park 
172*54fd6939SJiyong Park 	return -1;
173*54fd6939SJiyong Park }
174*54fd6939SJiyong Park 
check_cmd_params(void)175*54fd6939SJiyong Park static void check_cmd_params(void)
176*54fd6939SJiyong Park {
177*54fd6939SJiyong Park 	cert_t *cert;
178*54fd6939SJiyong Park 	ext_t *ext;
179*54fd6939SJiyong Park 	key_t *key;
180*54fd6939SJiyong Park 	int i, j;
181*54fd6939SJiyong Park 	bool valid_size;
182*54fd6939SJiyong Park 
183*54fd6939SJiyong Park 	/* Only save new keys */
184*54fd6939SJiyong Park 	if (save_keys && !new_keys) {
185*54fd6939SJiyong Park 		ERROR("Only new keys can be saved to disk\n");
186*54fd6939SJiyong Park 		exit(1);
187*54fd6939SJiyong Park 	}
188*54fd6939SJiyong Park 
189*54fd6939SJiyong Park 	/* Validate key-size */
190*54fd6939SJiyong Park 	valid_size = false;
191*54fd6939SJiyong Park 	for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
192*54fd6939SJiyong Park 		if (key_size == KEY_SIZES[key_alg][i]) {
193*54fd6939SJiyong Park 			valid_size = true;
194*54fd6939SJiyong Park 			break;
195*54fd6939SJiyong Park 		}
196*54fd6939SJiyong Park 	}
197*54fd6939SJiyong Park 	if (!valid_size) {
198*54fd6939SJiyong Park 		ERROR("'%d' is not a valid key size for '%s'\n",
199*54fd6939SJiyong Park 				key_size, key_algs_str[key_alg]);
200*54fd6939SJiyong Park 		NOTICE("Valid sizes are: ");
201*54fd6939SJiyong Park 		for (i = 0; i < KEY_SIZE_MAX_NUM &&
202*54fd6939SJiyong Park 				KEY_SIZES[key_alg][i] != 0; i++) {
203*54fd6939SJiyong Park 			printf("%d ", KEY_SIZES[key_alg][i]);
204*54fd6939SJiyong Park 		}
205*54fd6939SJiyong Park 		printf("\n");
206*54fd6939SJiyong Park 		exit(1);
207*54fd6939SJiyong Park 	}
208*54fd6939SJiyong Park 
209*54fd6939SJiyong Park 	/* Check that all required options have been specified in the
210*54fd6939SJiyong Park 	 * command line */
211*54fd6939SJiyong Park 	for (i = 0; i < num_certs; i++) {
212*54fd6939SJiyong Park 		cert = &certs[i];
213*54fd6939SJiyong Park 		if (cert->fn == NULL) {
214*54fd6939SJiyong Park 			/* Certificate not requested. Skip to the next one */
215*54fd6939SJiyong Park 			continue;
216*54fd6939SJiyong Park 		}
217*54fd6939SJiyong Park 
218*54fd6939SJiyong Park 		/* Check that all parameters required to create this certificate
219*54fd6939SJiyong Park 		 * have been specified in the command line */
220*54fd6939SJiyong Park 		for (j = 0; j < cert->num_ext; j++) {
221*54fd6939SJiyong Park 			ext = &extensions[cert->ext[j]];
222*54fd6939SJiyong Park 			switch (ext->type) {
223*54fd6939SJiyong Park 			case EXT_TYPE_NVCOUNTER:
224*54fd6939SJiyong Park 				/* Counter value must be specified */
225*54fd6939SJiyong Park 				if ((!ext->optional) && (ext->arg == NULL)) {
226*54fd6939SJiyong Park 					ERROR("Value for '%s' not specified\n",
227*54fd6939SJiyong Park 					      ext->ln);
228*54fd6939SJiyong Park 					exit(1);
229*54fd6939SJiyong Park 				}
230*54fd6939SJiyong Park 				break;
231*54fd6939SJiyong Park 			case EXT_TYPE_PKEY:
232*54fd6939SJiyong Park 				/* Key filename must be specified */
233*54fd6939SJiyong Park 				key = &keys[ext->attr.key];
234*54fd6939SJiyong Park 				if (!new_keys && key->fn == NULL) {
235*54fd6939SJiyong Park 					ERROR("Key '%s' required by '%s' not "
236*54fd6939SJiyong Park 					      "specified\n", key->desc,
237*54fd6939SJiyong Park 					      cert->cn);
238*54fd6939SJiyong Park 					exit(1);
239*54fd6939SJiyong Park 				}
240*54fd6939SJiyong Park 				break;
241*54fd6939SJiyong Park 			case EXT_TYPE_HASH:
242*54fd6939SJiyong Park 				/*
243*54fd6939SJiyong Park 				 * Binary image must be specified
244*54fd6939SJiyong Park 				 * unless it is explicitly made optional.
245*54fd6939SJiyong Park 				 */
246*54fd6939SJiyong Park 				if ((!ext->optional) && (ext->arg == NULL)) {
247*54fd6939SJiyong Park 					ERROR("Image for '%s' not specified\n",
248*54fd6939SJiyong Park 					      ext->ln);
249*54fd6939SJiyong Park 					exit(1);
250*54fd6939SJiyong Park 				}
251*54fd6939SJiyong Park 				break;
252*54fd6939SJiyong Park 			default:
253*54fd6939SJiyong Park 				ERROR("Unknown extension type '%d' in '%s'\n",
254*54fd6939SJiyong Park 				      ext->type, ext->ln);
255*54fd6939SJiyong Park 				exit(1);
256*54fd6939SJiyong Park 				break;
257*54fd6939SJiyong Park 			}
258*54fd6939SJiyong Park 		}
259*54fd6939SJiyong Park 	}
260*54fd6939SJiyong Park }
261*54fd6939SJiyong Park 
262*54fd6939SJiyong Park /* Common command line options */
263*54fd6939SJiyong Park static const cmd_opt_t common_cmd_opt[] = {
264*54fd6939SJiyong Park 	{
265*54fd6939SJiyong Park 		{ "help", no_argument, NULL, 'h' },
266*54fd6939SJiyong Park 		"Print this message and exit"
267*54fd6939SJiyong Park 	},
268*54fd6939SJiyong Park 	{
269*54fd6939SJiyong Park 		{ "key-alg", required_argument, NULL, 'a' },
270*54fd6939SJiyong Park 		"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'"
271*54fd6939SJiyong Park 	},
272*54fd6939SJiyong Park 	{
273*54fd6939SJiyong Park 		{ "key-size", required_argument, NULL, 'b' },
274*54fd6939SJiyong Park 		"Key size (for supported algorithms)."
275*54fd6939SJiyong Park 	},
276*54fd6939SJiyong Park 	{
277*54fd6939SJiyong Park 		{ "hash-alg", required_argument, NULL, 's' },
278*54fd6939SJiyong Park 		"Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
279*54fd6939SJiyong Park 	},
280*54fd6939SJiyong Park 	{
281*54fd6939SJiyong Park 		{ "save-keys", no_argument, NULL, 'k' },
282*54fd6939SJiyong Park 		"Save key pairs into files. Filenames must be provided"
283*54fd6939SJiyong Park 	},
284*54fd6939SJiyong Park 	{
285*54fd6939SJiyong Park 		{ "new-keys", no_argument, NULL, 'n' },
286*54fd6939SJiyong Park 		"Generate new key pairs if no key files are provided"
287*54fd6939SJiyong Park 	},
288*54fd6939SJiyong Park 	{
289*54fd6939SJiyong Park 		{ "print-cert", no_argument, NULL, 'p' },
290*54fd6939SJiyong Park 		"Print the certificates in the standard output"
291*54fd6939SJiyong Park 	}
292*54fd6939SJiyong Park };
293*54fd6939SJiyong Park 
main(int argc,char * argv[])294*54fd6939SJiyong Park int main(int argc, char *argv[])
295*54fd6939SJiyong Park {
296*54fd6939SJiyong Park 	STACK_OF(X509_EXTENSION) * sk;
297*54fd6939SJiyong Park 	X509_EXTENSION *cert_ext = NULL;
298*54fd6939SJiyong Park 	ext_t *ext;
299*54fd6939SJiyong Park 	key_t *key;
300*54fd6939SJiyong Park 	cert_t *cert;
301*54fd6939SJiyong Park 	FILE *file;
302*54fd6939SJiyong Park 	int i, j, ext_nid, nvctr;
303*54fd6939SJiyong Park 	int c, opt_idx = 0;
304*54fd6939SJiyong Park 	const struct option *cmd_opt;
305*54fd6939SJiyong Park 	const char *cur_opt;
306*54fd6939SJiyong Park 	unsigned int err_code;
307*54fd6939SJiyong Park 	unsigned char md[SHA512_DIGEST_LENGTH];
308*54fd6939SJiyong Park 	unsigned int  md_len;
309*54fd6939SJiyong Park 	const EVP_MD *md_info;
310*54fd6939SJiyong Park 
311*54fd6939SJiyong Park 	NOTICE("CoT Generation Tool: %s\n", build_msg);
312*54fd6939SJiyong Park 	NOTICE("Target platform: %s\n", platform_msg);
313*54fd6939SJiyong Park 
314*54fd6939SJiyong Park 	/* Set default options */
315*54fd6939SJiyong Park 	key_alg = KEY_ALG_RSA;
316*54fd6939SJiyong Park 	hash_alg = HASH_ALG_SHA256;
317*54fd6939SJiyong Park 	key_size = -1;
318*54fd6939SJiyong Park 
319*54fd6939SJiyong Park 	/* Add common command line options */
320*54fd6939SJiyong Park 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
321*54fd6939SJiyong Park 		cmd_opt_add(&common_cmd_opt[i]);
322*54fd6939SJiyong Park 	}
323*54fd6939SJiyong Park 
324*54fd6939SJiyong Park 	/* Initialize the certificates */
325*54fd6939SJiyong Park 	if (cert_init() != 0) {
326*54fd6939SJiyong Park 		ERROR("Cannot initialize certificates\n");
327*54fd6939SJiyong Park 		exit(1);
328*54fd6939SJiyong Park 	}
329*54fd6939SJiyong Park 
330*54fd6939SJiyong Park 	/* Initialize the keys */
331*54fd6939SJiyong Park 	if (key_init() != 0) {
332*54fd6939SJiyong Park 		ERROR("Cannot initialize keys\n");
333*54fd6939SJiyong Park 		exit(1);
334*54fd6939SJiyong Park 	}
335*54fd6939SJiyong Park 
336*54fd6939SJiyong Park 	/* Initialize the new types and register OIDs for the extensions */
337*54fd6939SJiyong Park 	if (ext_init() != 0) {
338*54fd6939SJiyong Park 		ERROR("Cannot initialize extensions\n");
339*54fd6939SJiyong Park 		exit(1);
340*54fd6939SJiyong Park 	}
341*54fd6939SJiyong Park 
342*54fd6939SJiyong Park 	/* Get the command line options populated during the initialization */
343*54fd6939SJiyong Park 	cmd_opt = cmd_opt_get_array();
344*54fd6939SJiyong Park 
345*54fd6939SJiyong Park 	while (1) {
346*54fd6939SJiyong Park 		/* getopt_long stores the option index here. */
347*54fd6939SJiyong Park 		c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
348*54fd6939SJiyong Park 
349*54fd6939SJiyong Park 		/* Detect the end of the options. */
350*54fd6939SJiyong Park 		if (c == -1) {
351*54fd6939SJiyong Park 			break;
352*54fd6939SJiyong Park 		}
353*54fd6939SJiyong Park 
354*54fd6939SJiyong Park 		switch (c) {
355*54fd6939SJiyong Park 		case 'a':
356*54fd6939SJiyong Park 			key_alg = get_key_alg(optarg);
357*54fd6939SJiyong Park 			if (key_alg < 0) {
358*54fd6939SJiyong Park 				ERROR("Invalid key algorithm '%s'\n", optarg);
359*54fd6939SJiyong Park 				exit(1);
360*54fd6939SJiyong Park 			}
361*54fd6939SJiyong Park 			break;
362*54fd6939SJiyong Park 		case 'b':
363*54fd6939SJiyong Park 			key_size = get_key_size(optarg);
364*54fd6939SJiyong Park 			if (key_size <= 0) {
365*54fd6939SJiyong Park 				ERROR("Invalid key size '%s'\n", optarg);
366*54fd6939SJiyong Park 				exit(1);
367*54fd6939SJiyong Park 			}
368*54fd6939SJiyong Park 			break;
369*54fd6939SJiyong Park 		case 'h':
370*54fd6939SJiyong Park 			print_help(argv[0], cmd_opt);
371*54fd6939SJiyong Park 			exit(0);
372*54fd6939SJiyong Park 		case 'k':
373*54fd6939SJiyong Park 			save_keys = 1;
374*54fd6939SJiyong Park 			break;
375*54fd6939SJiyong Park 		case 'n':
376*54fd6939SJiyong Park 			new_keys = 1;
377*54fd6939SJiyong Park 			break;
378*54fd6939SJiyong Park 		case 'p':
379*54fd6939SJiyong Park 			print_cert = 1;
380*54fd6939SJiyong Park 			break;
381*54fd6939SJiyong Park 		case 's':
382*54fd6939SJiyong Park 			hash_alg = get_hash_alg(optarg);
383*54fd6939SJiyong Park 			if (hash_alg < 0) {
384*54fd6939SJiyong Park 				ERROR("Invalid hash algorithm '%s'\n", optarg);
385*54fd6939SJiyong Park 				exit(1);
386*54fd6939SJiyong Park 			}
387*54fd6939SJiyong Park 			break;
388*54fd6939SJiyong Park 		case CMD_OPT_EXT:
389*54fd6939SJiyong Park 			cur_opt = cmd_opt_get_name(opt_idx);
390*54fd6939SJiyong Park 			ext = ext_get_by_opt(cur_opt);
391*54fd6939SJiyong Park 			ext->arg = strdup(optarg);
392*54fd6939SJiyong Park 			break;
393*54fd6939SJiyong Park 		case CMD_OPT_KEY:
394*54fd6939SJiyong Park 			cur_opt = cmd_opt_get_name(opt_idx);
395*54fd6939SJiyong Park 			key = key_get_by_opt(cur_opt);
396*54fd6939SJiyong Park 			key->fn = strdup(optarg);
397*54fd6939SJiyong Park 			break;
398*54fd6939SJiyong Park 		case CMD_OPT_CERT:
399*54fd6939SJiyong Park 			cur_opt = cmd_opt_get_name(opt_idx);
400*54fd6939SJiyong Park 			cert = cert_get_by_opt(cur_opt);
401*54fd6939SJiyong Park 			cert->fn = strdup(optarg);
402*54fd6939SJiyong Park 			break;
403*54fd6939SJiyong Park 		case '?':
404*54fd6939SJiyong Park 		default:
405*54fd6939SJiyong Park 			print_help(argv[0], cmd_opt);
406*54fd6939SJiyong Park 			exit(1);
407*54fd6939SJiyong Park 		}
408*54fd6939SJiyong Park 	}
409*54fd6939SJiyong Park 
410*54fd6939SJiyong Park 	/* Select a reasonable default key-size */
411*54fd6939SJiyong Park 	if (key_size == -1) {
412*54fd6939SJiyong Park 		key_size = KEY_SIZES[key_alg][0];
413*54fd6939SJiyong Park 	}
414*54fd6939SJiyong Park 
415*54fd6939SJiyong Park 	/* Check command line arguments */
416*54fd6939SJiyong Park 	check_cmd_params();
417*54fd6939SJiyong Park 
418*54fd6939SJiyong Park 	/* Indicate SHA as image hash algorithm in the certificate
419*54fd6939SJiyong Park 	 * extension */
420*54fd6939SJiyong Park 	if (hash_alg == HASH_ALG_SHA384) {
421*54fd6939SJiyong Park 		md_info = EVP_sha384();
422*54fd6939SJiyong Park 		md_len  = SHA384_DIGEST_LENGTH;
423*54fd6939SJiyong Park 	} else if (hash_alg == HASH_ALG_SHA512) {
424*54fd6939SJiyong Park 		md_info = EVP_sha512();
425*54fd6939SJiyong Park 		md_len  = SHA512_DIGEST_LENGTH;
426*54fd6939SJiyong Park 	} else {
427*54fd6939SJiyong Park 		md_info = EVP_sha256();
428*54fd6939SJiyong Park 		md_len  = SHA256_DIGEST_LENGTH;
429*54fd6939SJiyong Park 	}
430*54fd6939SJiyong Park 
431*54fd6939SJiyong Park 	/* Load private keys from files (or generate new ones) */
432*54fd6939SJiyong Park 	for (i = 0 ; i < num_keys ; i++) {
433*54fd6939SJiyong Park 		if (!key_new(&keys[i])) {
434*54fd6939SJiyong Park 			ERROR("Failed to allocate key container\n");
435*54fd6939SJiyong Park 			exit(1);
436*54fd6939SJiyong Park 		}
437*54fd6939SJiyong Park 
438*54fd6939SJiyong Park 		/* First try to load the key from disk */
439*54fd6939SJiyong Park 		if (key_load(&keys[i], &err_code)) {
440*54fd6939SJiyong Park 			/* Key loaded successfully */
441*54fd6939SJiyong Park 			continue;
442*54fd6939SJiyong Park 		}
443*54fd6939SJiyong Park 
444*54fd6939SJiyong Park 		/* Key not loaded. Check the error code */
445*54fd6939SJiyong Park 		if (err_code == KEY_ERR_LOAD) {
446*54fd6939SJiyong Park 			/* File exists, but it does not contain a valid private
447*54fd6939SJiyong Park 			 * key. Abort. */
448*54fd6939SJiyong Park 			ERROR("Error loading '%s'\n", keys[i].fn);
449*54fd6939SJiyong Park 			exit(1);
450*54fd6939SJiyong Park 		}
451*54fd6939SJiyong Park 
452*54fd6939SJiyong Park 		/* File does not exist, could not be opened or no filename was
453*54fd6939SJiyong Park 		 * given */
454*54fd6939SJiyong Park 		if (new_keys) {
455*54fd6939SJiyong Park 			/* Try to create a new key */
456*54fd6939SJiyong Park 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
457*54fd6939SJiyong Park 			if (!key_create(&keys[i], key_alg, key_size)) {
458*54fd6939SJiyong Park 				ERROR("Error creating key '%s'\n", keys[i].desc);
459*54fd6939SJiyong Park 				exit(1);
460*54fd6939SJiyong Park 			}
461*54fd6939SJiyong Park 		} else {
462*54fd6939SJiyong Park 			if (err_code == KEY_ERR_OPEN) {
463*54fd6939SJiyong Park 				ERROR("Error opening '%s'\n", keys[i].fn);
464*54fd6939SJiyong Park 			} else {
465*54fd6939SJiyong Park 				ERROR("Key '%s' not specified\n", keys[i].desc);
466*54fd6939SJiyong Park 			}
467*54fd6939SJiyong Park 			exit(1);
468*54fd6939SJiyong Park 		}
469*54fd6939SJiyong Park 	}
470*54fd6939SJiyong Park 
471*54fd6939SJiyong Park 	/* Create the certificates */
472*54fd6939SJiyong Park 	for (i = 0 ; i < num_certs ; i++) {
473*54fd6939SJiyong Park 
474*54fd6939SJiyong Park 		cert = &certs[i];
475*54fd6939SJiyong Park 
476*54fd6939SJiyong Park 		if (cert->fn == NULL) {
477*54fd6939SJiyong Park 			/* Certificate not requested. Skip to the next one */
478*54fd6939SJiyong Park 			continue;
479*54fd6939SJiyong Park 		}
480*54fd6939SJiyong Park 
481*54fd6939SJiyong Park 		/* Create a new stack of extensions. This stack will be used
482*54fd6939SJiyong Park 		 * to create the certificate */
483*54fd6939SJiyong Park 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
484*54fd6939SJiyong Park 
485*54fd6939SJiyong Park 		for (j = 0 ; j < cert->num_ext ; j++) {
486*54fd6939SJiyong Park 
487*54fd6939SJiyong Park 			ext = &extensions[cert->ext[j]];
488*54fd6939SJiyong Park 
489*54fd6939SJiyong Park 			/* Get OpenSSL internal ID for this extension */
490*54fd6939SJiyong Park 			CHECK_OID(ext_nid, ext->oid);
491*54fd6939SJiyong Park 
492*54fd6939SJiyong Park 			/*
493*54fd6939SJiyong Park 			 * Three types of extensions are currently supported:
494*54fd6939SJiyong Park 			 *     - EXT_TYPE_NVCOUNTER
495*54fd6939SJiyong Park 			 *     - EXT_TYPE_HASH
496*54fd6939SJiyong Park 			 *     - EXT_TYPE_PKEY
497*54fd6939SJiyong Park 			 */
498*54fd6939SJiyong Park 			switch (ext->type) {
499*54fd6939SJiyong Park 			case EXT_TYPE_NVCOUNTER:
500*54fd6939SJiyong Park 				if (ext->optional && ext->arg == NULL) {
501*54fd6939SJiyong Park 					/* Skip this NVCounter */
502*54fd6939SJiyong Park 					continue;
503*54fd6939SJiyong Park 				} else {
504*54fd6939SJiyong Park 					/* Checked by `check_cmd_params` */
505*54fd6939SJiyong Park 					assert(ext->arg != NULL);
506*54fd6939SJiyong Park 					nvctr = atoi(ext->arg);
507*54fd6939SJiyong Park 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
508*54fd6939SJiyong Park 						EXT_CRIT, nvctr));
509*54fd6939SJiyong Park 				}
510*54fd6939SJiyong Park 				break;
511*54fd6939SJiyong Park 			case EXT_TYPE_HASH:
512*54fd6939SJiyong Park 				if (ext->arg == NULL) {
513*54fd6939SJiyong Park 					if (ext->optional) {
514*54fd6939SJiyong Park 						/* Include a hash filled with zeros */
515*54fd6939SJiyong Park 						memset(md, 0x0, SHA512_DIGEST_LENGTH);
516*54fd6939SJiyong Park 					} else {
517*54fd6939SJiyong Park 						/* Do not include this hash in the certificate */
518*54fd6939SJiyong Park 						continue;
519*54fd6939SJiyong Park 					}
520*54fd6939SJiyong Park 				} else {
521*54fd6939SJiyong Park 					/* Calculate the hash of the file */
522*54fd6939SJiyong Park 					if (!sha_file(hash_alg, ext->arg, md)) {
523*54fd6939SJiyong Park 						ERROR("Cannot calculate hash of %s\n",
524*54fd6939SJiyong Park 							ext->arg);
525*54fd6939SJiyong Park 						exit(1);
526*54fd6939SJiyong Park 					}
527*54fd6939SJiyong Park 				}
528*54fd6939SJiyong Park 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
529*54fd6939SJiyong Park 						EXT_CRIT, md_info, md,
530*54fd6939SJiyong Park 						md_len));
531*54fd6939SJiyong Park 				break;
532*54fd6939SJiyong Park 			case EXT_TYPE_PKEY:
533*54fd6939SJiyong Park 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
534*54fd6939SJiyong Park 					EXT_CRIT, keys[ext->attr.key].key));
535*54fd6939SJiyong Park 				break;
536*54fd6939SJiyong Park 			default:
537*54fd6939SJiyong Park 				ERROR("Unknown extension type '%d' in %s\n",
538*54fd6939SJiyong Park 						ext->type, cert->cn);
539*54fd6939SJiyong Park 				exit(1);
540*54fd6939SJiyong Park 			}
541*54fd6939SJiyong Park 
542*54fd6939SJiyong Park 			/* Push the extension into the stack */
543*54fd6939SJiyong Park 			sk_X509_EXTENSION_push(sk, cert_ext);
544*54fd6939SJiyong Park 		}
545*54fd6939SJiyong Park 
546*54fd6939SJiyong Park 		/* Create certificate. Signed with corresponding key */
547*54fd6939SJiyong Park 		if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
548*54fd6939SJiyong Park 			ERROR("Cannot create %s\n", cert->cn);
549*54fd6939SJiyong Park 			exit(1);
550*54fd6939SJiyong Park 		}
551*54fd6939SJiyong Park 
552*54fd6939SJiyong Park 		for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
553*54fd6939SJiyong Park 				cert_ext = sk_X509_EXTENSION_pop(sk)) {
554*54fd6939SJiyong Park 			X509_EXTENSION_free(cert_ext);
555*54fd6939SJiyong Park 		}
556*54fd6939SJiyong Park 
557*54fd6939SJiyong Park 		sk_X509_EXTENSION_free(sk);
558*54fd6939SJiyong Park 	}
559*54fd6939SJiyong Park 
560*54fd6939SJiyong Park 
561*54fd6939SJiyong Park 	/* Print the certificates */
562*54fd6939SJiyong Park 	if (print_cert) {
563*54fd6939SJiyong Park 		for (i = 0 ; i < num_certs ; i++) {
564*54fd6939SJiyong Park 			if (!certs[i].x) {
565*54fd6939SJiyong Park 				continue;
566*54fd6939SJiyong Park 			}
567*54fd6939SJiyong Park 			printf("\n\n=====================================\n\n");
568*54fd6939SJiyong Park 			X509_print_fp(stdout, certs[i].x);
569*54fd6939SJiyong Park 		}
570*54fd6939SJiyong Park 	}
571*54fd6939SJiyong Park 
572*54fd6939SJiyong Park 	/* Save created certificates to files */
573*54fd6939SJiyong Park 	for (i = 0 ; i < num_certs ; i++) {
574*54fd6939SJiyong Park 		if (certs[i].x && certs[i].fn) {
575*54fd6939SJiyong Park 			file = fopen(certs[i].fn, "w");
576*54fd6939SJiyong Park 			if (file != NULL) {
577*54fd6939SJiyong Park 				i2d_X509_fp(file, certs[i].x);
578*54fd6939SJiyong Park 				fclose(file);
579*54fd6939SJiyong Park 			} else {
580*54fd6939SJiyong Park 				ERROR("Cannot create file %s\n", certs[i].fn);
581*54fd6939SJiyong Park 			}
582*54fd6939SJiyong Park 		}
583*54fd6939SJiyong Park 	}
584*54fd6939SJiyong Park 
585*54fd6939SJiyong Park 	/* Save keys */
586*54fd6939SJiyong Park 	if (save_keys) {
587*54fd6939SJiyong Park 		for (i = 0 ; i < num_keys ; i++) {
588*54fd6939SJiyong Park 			if (!key_store(&keys[i])) {
589*54fd6939SJiyong Park 				ERROR("Cannot save %s\n", keys[i].desc);
590*54fd6939SJiyong Park 			}
591*54fd6939SJiyong Park 		}
592*54fd6939SJiyong Park 	}
593*54fd6939SJiyong Park 
594*54fd6939SJiyong Park 	/* If we got here, then we must have filled the key array completely.
595*54fd6939SJiyong Park 	 * We can then safely call free on all of the keys in the array
596*54fd6939SJiyong Park 	 */
597*54fd6939SJiyong Park 	for (i = 0; i < num_keys; i++) {
598*54fd6939SJiyong Park 		EVP_PKEY_free(keys[i].key);
599*54fd6939SJiyong Park 	}
600*54fd6939SJiyong Park 
601*54fd6939SJiyong Park #ifndef OPENSSL_NO_ENGINE
602*54fd6939SJiyong Park 	ENGINE_cleanup();
603*54fd6939SJiyong Park #endif
604*54fd6939SJiyong Park 	CRYPTO_cleanup_all_ex_data();
605*54fd6939SJiyong Park 
606*54fd6939SJiyong Park 
607*54fd6939SJiyong Park 	/* We allocated strings through strdup, so now we have to free them */
608*54fd6939SJiyong Park 	for (i = 0; i < num_keys; i++) {
609*54fd6939SJiyong Park 		if (keys[i].fn != NULL) {
610*54fd6939SJiyong Park 			void *ptr = keys[i].fn;
611*54fd6939SJiyong Park 
612*54fd6939SJiyong Park 			keys[i].fn = NULL;
613*54fd6939SJiyong Park 			free(ptr);
614*54fd6939SJiyong Park 		}
615*54fd6939SJiyong Park 	}
616*54fd6939SJiyong Park 	for (i = 0; i < num_extensions; i++) {
617*54fd6939SJiyong Park 		if (extensions[i].arg != NULL) {
618*54fd6939SJiyong Park 			void *ptr = (void *)extensions[i].arg;
619*54fd6939SJiyong Park 
620*54fd6939SJiyong Park 			extensions[i].arg = NULL;
621*54fd6939SJiyong Park 			free(ptr);
622*54fd6939SJiyong Park 		}
623*54fd6939SJiyong Park 	}
624*54fd6939SJiyong Park 	for (i = 0; i < num_certs; i++) {
625*54fd6939SJiyong Park 		if (certs[i].fn != NULL) {
626*54fd6939SJiyong Park 			void *ptr = (void *)certs[i].fn;
627*54fd6939SJiyong Park 
628*54fd6939SJiyong Park 			certs[i].fn = NULL;
629*54fd6939SJiyong Park 			free(ptr);
630*54fd6939SJiyong Park 		}
631*54fd6939SJiyong Park 	}
632*54fd6939SJiyong Park 
633*54fd6939SJiyong Park 	return 0;
634*54fd6939SJiyong Park }
635