xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision c0c280dfda7322dcaebb5c6341c0880bdf524e13)
16f971622SJuan Castillo /*
2cf2dd17dSJuan Pablo Conde  * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
36f971622SJuan Castillo  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
56f971622SJuan Castillo  */
66f971622SJuan Castillo 
7159807e2SJuan Castillo #include <assert.h>
8159807e2SJuan Castillo #include <ctype.h>
96f971622SJuan Castillo #include <getopt.h>
106f971622SJuan Castillo #include <stdio.h>
116f971622SJuan Castillo #include <stdlib.h>
126f971622SJuan Castillo #include <string.h>
13dfe0f4c2SJustin Chadwell #include <stdbool.h>
146f971622SJuan Castillo 
156f971622SJuan Castillo #include <openssl/conf.h>
166f971622SJuan Castillo #include <openssl/engine.h>
176f971622SJuan Castillo #include <openssl/err.h>
186f971622SJuan Castillo #include <openssl/pem.h>
196f971622SJuan Castillo #include <openssl/sha.h>
206f971622SJuan Castillo #include <openssl/x509v3.h>
216f971622SJuan Castillo 
226f971622SJuan Castillo #include "cert.h"
23ad2c1a9aSJuan Castillo #include "cmd_opt.h"
246f971622SJuan Castillo #include "debug.h"
256f971622SJuan Castillo #include "ext.h"
266f971622SJuan Castillo #include "key.h"
276f971622SJuan Castillo #include "sha.h"
286f971622SJuan Castillo 
296f971622SJuan Castillo /*
306f971622SJuan Castillo  * Helper macros to simplify the code. This macro assigns the return value of
316f971622SJuan Castillo  * the 'fn' function to 'v' and exits if the value is NULL.
326f971622SJuan Castillo  */
336f971622SJuan Castillo #define CHECK_NULL(v, fn) \
346f971622SJuan Castillo 	do { \
356f971622SJuan Castillo 		v = fn; \
366f971622SJuan Castillo 		if (v == NULL) { \
376f971622SJuan Castillo 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
386f971622SJuan Castillo 			exit(1); \
396f971622SJuan Castillo 		} \
406f971622SJuan Castillo 	} while (0)
416f971622SJuan Castillo 
426f971622SJuan Castillo /*
436f971622SJuan Castillo  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
446f971622SJuan Castillo  * NID is undefined.
456f971622SJuan Castillo  */
466f971622SJuan Castillo #define CHECK_OID(v, oid) \
476f971622SJuan Castillo 	do { \
486f971622SJuan Castillo 		v = OBJ_txt2nid(oid); \
496f971622SJuan Castillo 		if (v == NID_undef) { \
50067f7e9cSSandrine Bailleux 			ERROR("Cannot find extension %s\n", oid); \
516f971622SJuan Castillo 			exit(1); \
526f971622SJuan Castillo 		} \
536f971622SJuan Castillo 	} while (0)
546f971622SJuan Castillo 
556f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
566f971622SJuan Castillo #define VAL_DAYS			7300
576f971622SJuan Castillo #define ID_TO_BIT_MASK(id)		(1 << id)
58ccbf890eSJuan Castillo #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
59159807e2SJuan Castillo #define HELP_OPT_MAX_LEN		128
606f971622SJuan Castillo 
616f971622SJuan Castillo /* Global options */
62ccbf890eSJuan Castillo static int key_alg;
632972247cSQixiang Xu static int hash_alg;
64dfe0f4c2SJustin Chadwell static int key_size;
656f971622SJuan Castillo static int new_keys;
666f971622SJuan Castillo static int save_keys;
676f971622SJuan Castillo static int print_cert;
686f971622SJuan Castillo 
696f971622SJuan Castillo /* Info messages created in the Makefile */
706f971622SJuan Castillo extern const char build_msg[];
716f971622SJuan Castillo extern const char platform_msg[];
726f971622SJuan Castillo 
736f971622SJuan Castillo 
746f971622SJuan Castillo static char *strdup(const char *str)
756f971622SJuan Castillo {
766f971622SJuan Castillo 	int n = strlen(str) + 1;
776f971622SJuan Castillo 	char *dup = malloc(n);
786f971622SJuan Castillo 	if (dup) {
796f971622SJuan Castillo 		strcpy(dup, str);
806f971622SJuan Castillo 	}
816f971622SJuan Castillo 	return dup;
826f971622SJuan Castillo }
836f971622SJuan Castillo 
84ccbf890eSJuan Castillo static const char *key_algs_str[] = {
85ccbf890eSJuan Castillo 	[KEY_ALG_RSA] = "rsa",
86ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
87e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_NIST] = "ecdsa",
88*c0c280dfSDonald Chan #if OPENSSL_VERSION_NUMBER >= 0x10100000L
89e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_R] = "ecdsa-brainpool-regular",
90e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_T] = "ecdsa-brainpool-twisted",
91*c0c280dfSDonald Chan #endif
92ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
93ccbf890eSJuan Castillo };
94ccbf890eSJuan Castillo 
952972247cSQixiang Xu static const char *hash_algs_str[] = {
962972247cSQixiang Xu 	[HASH_ALG_SHA256] = "sha256",
972972247cSQixiang Xu 	[HASH_ALG_SHA384] = "sha384",
982972247cSQixiang Xu 	[HASH_ALG_SHA512] = "sha512",
992972247cSQixiang Xu };
1002972247cSQixiang Xu 
101ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt)
1026f971622SJuan Castillo {
103159807e2SJuan Castillo 	int rem, i = 0;
104159807e2SJuan Castillo 	const struct option *opt;
105159807e2SJuan Castillo 	char line[HELP_OPT_MAX_LEN];
106159807e2SJuan Castillo 	char *p;
107159807e2SJuan Castillo 
108159807e2SJuan Castillo 	assert(cmd != NULL);
109159807e2SJuan Castillo 	assert(long_opt != NULL);
110159807e2SJuan Castillo 
1116f971622SJuan Castillo 	printf("\n\n");
1126f971622SJuan Castillo 	printf("The certificate generation tool loads the binary images and\n"
113e78ba69eSLionel Debieve 	       "optionally the RSA or ECC keys, and outputs the key and content\n"
1146f971622SJuan Castillo 	       "certificates properly signed to implement the chain of trust.\n"
1156f971622SJuan Castillo 	       "If keys are provided, they must be in PEM format.\n"
1166f971622SJuan Castillo 	       "Certificates are generated in DER format.\n");
1176f971622SJuan Castillo 	printf("\n");
118159807e2SJuan Castillo 	printf("Usage:\n");
119159807e2SJuan Castillo 	printf("\t%s [OPTIONS]\n\n", cmd);
120159807e2SJuan Castillo 
121159807e2SJuan Castillo 	printf("Available options:\n");
122159807e2SJuan Castillo 	opt = long_opt;
123159807e2SJuan Castillo 	while (opt->name) {
124159807e2SJuan Castillo 		p = line;
125159807e2SJuan Castillo 		rem = HELP_OPT_MAX_LEN;
126159807e2SJuan Castillo 		if (isalpha(opt->val)) {
127159807e2SJuan Castillo 			/* Short format */
128159807e2SJuan Castillo 			sprintf(p, "-%c,", (char)opt->val);
129159807e2SJuan Castillo 			p += 3;
130159807e2SJuan Castillo 			rem -= 3;
1316f971622SJuan Castillo 		}
132159807e2SJuan Castillo 		snprintf(p, rem, "--%s %s", opt->name,
133159807e2SJuan Castillo 			 (opt->has_arg == required_argument) ? "<arg>" : "");
134159807e2SJuan Castillo 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
135159807e2SJuan Castillo 		opt++;
136159807e2SJuan Castillo 		i++;
137159807e2SJuan Castillo 	}
1386f971622SJuan Castillo 	printf("\n");
1396f971622SJuan Castillo }
1406f971622SJuan Castillo 
141ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
142ccbf890eSJuan Castillo {
143ccbf890eSJuan Castillo 	int i;
144ccbf890eSJuan Castillo 
145ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
146ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
147ccbf890eSJuan Castillo 			return i;
148ccbf890eSJuan Castillo 		}
149ccbf890eSJuan Castillo 	}
150ccbf890eSJuan Castillo 
151ccbf890eSJuan Castillo 	return -1;
152ccbf890eSJuan Castillo }
153ccbf890eSJuan Castillo 
154dfe0f4c2SJustin Chadwell static int get_key_size(const char *key_size_str)
155dfe0f4c2SJustin Chadwell {
156dfe0f4c2SJustin Chadwell 	char *end;
157dfe0f4c2SJustin Chadwell 	long key_size;
158dfe0f4c2SJustin Chadwell 
159dfe0f4c2SJustin Chadwell 	key_size = strtol(key_size_str, &end, 10);
160dfe0f4c2SJustin Chadwell 	if (*end != '\0')
161dfe0f4c2SJustin Chadwell 		return -1;
162dfe0f4c2SJustin Chadwell 
163dfe0f4c2SJustin Chadwell 	return key_size;
164dfe0f4c2SJustin Chadwell }
165dfe0f4c2SJustin Chadwell 
1662972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str)
1672972247cSQixiang Xu {
1682972247cSQixiang Xu 	int i;
1692972247cSQixiang Xu 
1702972247cSQixiang Xu 	for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
1712972247cSQixiang Xu 		if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
1722972247cSQixiang Xu 			return i;
1732972247cSQixiang Xu 		}
1742972247cSQixiang Xu 	}
1752972247cSQixiang Xu 
1762972247cSQixiang Xu 	return -1;
1772972247cSQixiang Xu }
1782972247cSQixiang Xu 
1796f971622SJuan Castillo static void check_cmd_params(void)
1806f971622SJuan Castillo {
181dfc90e26SJuan Castillo 	cert_t *cert;
182dfc90e26SJuan Castillo 	ext_t *ext;
183dfc90e26SJuan Castillo 	key_t *key;
184dfc90e26SJuan Castillo 	int i, j;
185dfe0f4c2SJustin Chadwell 	bool valid_size;
186dfc90e26SJuan Castillo 
187ccbf890eSJuan Castillo 	/* Only save new keys */
188ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
189ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
190ccbf890eSJuan Castillo 		exit(1);
191ccbf890eSJuan Castillo 	}
192ccbf890eSJuan Castillo 
193dfe0f4c2SJustin Chadwell 	/* Validate key-size */
194dfe0f4c2SJustin Chadwell 	valid_size = false;
195dfe0f4c2SJustin Chadwell 	for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
196dfe0f4c2SJustin Chadwell 		if (key_size == KEY_SIZES[key_alg][i]) {
197dfe0f4c2SJustin Chadwell 			valid_size = true;
198dfe0f4c2SJustin Chadwell 			break;
199dfe0f4c2SJustin Chadwell 		}
200dfe0f4c2SJustin Chadwell 	}
201dfe0f4c2SJustin Chadwell 	if (!valid_size) {
202dfe0f4c2SJustin Chadwell 		ERROR("'%d' is not a valid key size for '%s'\n",
203dfe0f4c2SJustin Chadwell 				key_size, key_algs_str[key_alg]);
204dfe0f4c2SJustin Chadwell 		NOTICE("Valid sizes are: ");
205dfe0f4c2SJustin Chadwell 		for (i = 0; i < KEY_SIZE_MAX_NUM &&
206dfe0f4c2SJustin Chadwell 				KEY_SIZES[key_alg][i] != 0; i++) {
207dfe0f4c2SJustin Chadwell 			printf("%d ", KEY_SIZES[key_alg][i]);
208dfe0f4c2SJustin Chadwell 		}
209dfe0f4c2SJustin Chadwell 		printf("\n");
210dfe0f4c2SJustin Chadwell 		exit(1);
211dfe0f4c2SJustin Chadwell 	}
212dfe0f4c2SJustin Chadwell 
213dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
214dfc90e26SJuan Castillo 	 * command line */
215dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
216dfc90e26SJuan Castillo 		cert = &certs[i];
217dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
218dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
219dfc90e26SJuan Castillo 			continue;
220dfc90e26SJuan Castillo 		}
221dfc90e26SJuan Castillo 
222dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
223dfc90e26SJuan Castillo 		 * have been specified in the command line */
224dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
225dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
226dfc90e26SJuan Castillo 			switch (ext->type) {
22796103d5aSJuan Castillo 			case EXT_TYPE_NVCOUNTER:
22896103d5aSJuan Castillo 				/* Counter value must be specified */
22996103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
23096103d5aSJuan Castillo 					ERROR("Value for '%s' not specified\n",
23196103d5aSJuan Castillo 					      ext->ln);
23296103d5aSJuan Castillo 					exit(1);
23396103d5aSJuan Castillo 				}
23496103d5aSJuan Castillo 				break;
235dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
236dfc90e26SJuan Castillo 				/* Key filename must be specified */
23796103d5aSJuan Castillo 				key = &keys[ext->attr.key];
238dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
239dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
240dfc90e26SJuan Castillo 					      "specified\n", key->desc,
241dfc90e26SJuan Castillo 					      cert->cn);
2426f971622SJuan Castillo 					exit(1);
2436f971622SJuan Castillo 				}
244dfc90e26SJuan Castillo 				break;
245dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
246cebe1f23SYatharth Kochar 				/*
247cebe1f23SYatharth Kochar 				 * Binary image must be specified
248cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
249cebe1f23SYatharth Kochar 				 */
25096103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
251dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
252dfc90e26SJuan Castillo 					      ext->ln);
2536f971622SJuan Castillo 					exit(1);
2546f971622SJuan Castillo 				}
255dfc90e26SJuan Castillo 				break;
256dfc90e26SJuan Castillo 			default:
25796103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in '%s'\n",
25896103d5aSJuan Castillo 				      ext->type, ext->ln);
2596f971622SJuan Castillo 				exit(1);
260dfc90e26SJuan Castillo 				break;
2616f971622SJuan Castillo 			}
2626f971622SJuan Castillo 		}
2636f971622SJuan Castillo 	}
2646f971622SJuan Castillo }
2656f971622SJuan Castillo 
266159807e2SJuan Castillo /* Common command line options */
267159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = {
268159807e2SJuan Castillo 	{
269159807e2SJuan Castillo 		{ "help", no_argument, NULL, 'h' },
270159807e2SJuan Castillo 		"Print this message and exit"
271159807e2SJuan Castillo 	},
272159807e2SJuan Castillo 	{
273159807e2SJuan Castillo 		{ "key-alg", required_argument, NULL, 'a' },
274*c0c280dfSDonald Chan 		"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, "
275*c0c280dfSDonald Chan #if OPENSSL_VERSION_NUMBER >= 0x10100000L
276e78ba69eSLionel Debieve 		"'ecdsa', 'ecdsa-brainpool-regular', 'ecdsa-brainpool-twisted'"
277*c0c280dfSDonald Chan #else
278*c0c280dfSDonald Chan 		"'ecdsa'"
279*c0c280dfSDonald Chan #endif
280159807e2SJuan Castillo 	},
281159807e2SJuan Castillo 	{
282dfe0f4c2SJustin Chadwell 		{ "key-size", required_argument, NULL, 'b' },
283dfe0f4c2SJustin Chadwell 		"Key size (for supported algorithms)."
284dfe0f4c2SJustin Chadwell 	},
285dfe0f4c2SJustin Chadwell 	{
2862972247cSQixiang Xu 		{ "hash-alg", required_argument, NULL, 's' },
2872972247cSQixiang Xu 		"Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
2882972247cSQixiang Xu 	},
2892972247cSQixiang Xu 	{
290159807e2SJuan Castillo 		{ "save-keys", no_argument, NULL, 'k' },
291159807e2SJuan Castillo 		"Save key pairs into files. Filenames must be provided"
292159807e2SJuan Castillo 	},
293159807e2SJuan Castillo 	{
294159807e2SJuan Castillo 		{ "new-keys", no_argument, NULL, 'n' },
295159807e2SJuan Castillo 		"Generate new key pairs if no key files are provided"
296159807e2SJuan Castillo 	},
297159807e2SJuan Castillo 	{
298159807e2SJuan Castillo 		{ "print-cert", no_argument, NULL, 'p' },
299159807e2SJuan Castillo 		"Print the certificates in the standard output"
300159807e2SJuan Castillo 	}
301159807e2SJuan Castillo };
302159807e2SJuan Castillo 
3036f971622SJuan Castillo int main(int argc, char *argv[])
3046f971622SJuan Castillo {
305c893c733SMasahiro Yamada 	STACK_OF(X509_EXTENSION) * sk;
306742c4e14SMichalis Pappas 	X509_EXTENSION *cert_ext = NULL;
307c893c733SMasahiro Yamada 	ext_t *ext;
308c893c733SMasahiro Yamada 	key_t *key;
309c893c733SMasahiro Yamada 	cert_t *cert;
310c893c733SMasahiro Yamada 	FILE *file;
31196103d5aSJuan Castillo 	int i, j, ext_nid, nvctr;
3126f971622SJuan Castillo 	int c, opt_idx = 0;
313ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
314ad2c1a9aSJuan Castillo 	const char *cur_opt;
315ccbf890eSJuan Castillo 	unsigned int err_code;
3162972247cSQixiang Xu 	unsigned char md[SHA512_DIGEST_LENGTH];
3172972247cSQixiang Xu 	unsigned int  md_len;
318c3da66b1SJuan Castillo 	const EVP_MD *md_info;
3196f971622SJuan Castillo 
3206f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
3216f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
3226f971622SJuan Castillo 
323ccbf890eSJuan Castillo 	/* Set default options */
324ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
3252972247cSQixiang Xu 	hash_alg = HASH_ALG_SHA256;
326dfe0f4c2SJustin Chadwell 	key_size = -1;
327ccbf890eSJuan Castillo 
328ad2c1a9aSJuan Castillo 	/* Add common command line options */
329159807e2SJuan Castillo 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
330159807e2SJuan Castillo 		cmd_opt_add(&common_cmd_opt[i]);
331159807e2SJuan Castillo 	}
332ad2c1a9aSJuan Castillo 
333ad2c1a9aSJuan Castillo 	/* Initialize the certificates */
334ad2c1a9aSJuan Castillo 	if (cert_init() != 0) {
335ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize certificates\n");
336ad2c1a9aSJuan Castillo 		exit(1);
337ad2c1a9aSJuan Castillo 	}
338ad2c1a9aSJuan Castillo 
339ad2c1a9aSJuan Castillo 	/* Initialize the keys */
340ad2c1a9aSJuan Castillo 	if (key_init() != 0) {
341ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize keys\n");
342ad2c1a9aSJuan Castillo 		exit(1);
343ad2c1a9aSJuan Castillo 	}
344ad2c1a9aSJuan Castillo 
345ad2c1a9aSJuan Castillo 	/* Initialize the new types and register OIDs for the extensions */
346ad2c1a9aSJuan Castillo 	if (ext_init() != 0) {
347067f7e9cSSandrine Bailleux 		ERROR("Cannot initialize extensions\n");
348ad2c1a9aSJuan Castillo 		exit(1);
349ad2c1a9aSJuan Castillo 	}
350ad2c1a9aSJuan Castillo 
351ad2c1a9aSJuan Castillo 	/* Get the command line options populated during the initialization */
352ad2c1a9aSJuan Castillo 	cmd_opt = cmd_opt_get_array();
353ad2c1a9aSJuan Castillo 
3546f971622SJuan Castillo 	while (1) {
3556f971622SJuan Castillo 		/* getopt_long stores the option index here. */
356dfe0f4c2SJustin Chadwell 		c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
3576f971622SJuan Castillo 
3586f971622SJuan Castillo 		/* Detect the end of the options. */
3596f971622SJuan Castillo 		if (c == -1) {
3606f971622SJuan Castillo 			break;
3616f971622SJuan Castillo 		}
3626f971622SJuan Castillo 
3636f971622SJuan Castillo 		switch (c) {
364ccbf890eSJuan Castillo 		case 'a':
365ccbf890eSJuan Castillo 			key_alg = get_key_alg(optarg);
366ccbf890eSJuan Castillo 			if (key_alg < 0) {
367ccbf890eSJuan Castillo 				ERROR("Invalid key algorithm '%s'\n", optarg);
368ccbf890eSJuan Castillo 				exit(1);
369ccbf890eSJuan Castillo 			}
370ccbf890eSJuan Castillo 			break;
371dfe0f4c2SJustin Chadwell 		case 'b':
372dfe0f4c2SJustin Chadwell 			key_size = get_key_size(optarg);
373dfe0f4c2SJustin Chadwell 			if (key_size <= 0) {
374dfe0f4c2SJustin Chadwell 				ERROR("Invalid key size '%s'\n", optarg);
375dfe0f4c2SJustin Chadwell 				exit(1);
376dfe0f4c2SJustin Chadwell 			}
377dfe0f4c2SJustin Chadwell 			break;
3786f971622SJuan Castillo 		case 'h':
379ad2c1a9aSJuan Castillo 			print_help(argv[0], cmd_opt);
380600835d0SRoberto Vargas 			exit(0);
3816f971622SJuan Castillo 		case 'k':
3826f971622SJuan Castillo 			save_keys = 1;
3836f971622SJuan Castillo 			break;
3846f971622SJuan Castillo 		case 'n':
3856f971622SJuan Castillo 			new_keys = 1;
3866f971622SJuan Castillo 			break;
3876f971622SJuan Castillo 		case 'p':
3886f971622SJuan Castillo 			print_cert = 1;
3896f971622SJuan Castillo 			break;
3902972247cSQixiang Xu 		case 's':
3912972247cSQixiang Xu 			hash_alg = get_hash_alg(optarg);
3922972247cSQixiang Xu 			if (hash_alg < 0) {
3932972247cSQixiang Xu 				ERROR("Invalid hash algorithm '%s'\n", optarg);
3942972247cSQixiang Xu 				exit(1);
3952972247cSQixiang Xu 			}
3962972247cSQixiang Xu 			break;
397ad2c1a9aSJuan Castillo 		case CMD_OPT_EXT:
398ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
399ad2c1a9aSJuan Castillo 			ext = ext_get_by_opt(cur_opt);
40096103d5aSJuan Castillo 			ext->arg = strdup(optarg);
4016f971622SJuan Castillo 			break;
402ad2c1a9aSJuan Castillo 		case CMD_OPT_KEY:
403ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
404ad2c1a9aSJuan Castillo 			key = key_get_by_opt(cur_opt);
405ad2c1a9aSJuan Castillo 			key->fn = strdup(optarg);
4066f971622SJuan Castillo 			break;
407ad2c1a9aSJuan Castillo 		case CMD_OPT_CERT:
408ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
409ad2c1a9aSJuan Castillo 			cert = cert_get_by_opt(cur_opt);
410ad2c1a9aSJuan Castillo 			cert->fn = strdup(optarg);
4116f971622SJuan Castillo 			break;
4126f971622SJuan Castillo 		case '?':
4136f971622SJuan Castillo 		default:
414159807e2SJuan Castillo 			print_help(argv[0], cmd_opt);
4156f971622SJuan Castillo 			exit(1);
4166f971622SJuan Castillo 		}
4176f971622SJuan Castillo 	}
4186f971622SJuan Castillo 
419dfe0f4c2SJustin Chadwell 	/* Select a reasonable default key-size */
420dfe0f4c2SJustin Chadwell 	if (key_size == -1) {
421dfe0f4c2SJustin Chadwell 		key_size = KEY_SIZES[key_alg][0];
422dfe0f4c2SJustin Chadwell 	}
423dfe0f4c2SJustin Chadwell 
4246f971622SJuan Castillo 	/* Check command line arguments */
4256f971622SJuan Castillo 	check_cmd_params();
4266f971622SJuan Castillo 
4272972247cSQixiang Xu 	/* Indicate SHA as image hash algorithm in the certificate
428c3da66b1SJuan Castillo 	 * extension */
4292972247cSQixiang Xu 	if (hash_alg == HASH_ALG_SHA384) {
4302972247cSQixiang Xu 		md_info = EVP_sha384();
4312972247cSQixiang Xu 		md_len  = SHA384_DIGEST_LENGTH;
4322972247cSQixiang Xu 	} else if (hash_alg == HASH_ALG_SHA512) {
4332972247cSQixiang Xu 		md_info = EVP_sha512();
4342972247cSQixiang Xu 		md_len  = SHA512_DIGEST_LENGTH;
4352972247cSQixiang Xu 	} else {
436c3da66b1SJuan Castillo 		md_info = EVP_sha256();
4372972247cSQixiang Xu 		md_len  = SHA256_DIGEST_LENGTH;
4382972247cSQixiang Xu 	}
439c3da66b1SJuan Castillo 
4406f971622SJuan Castillo 	/* Load private keys from files (or generate new ones) */
44155e291a4SJuan Castillo 	for (i = 0 ; i < num_keys ; i++) {
442cf2dd17dSJuan Pablo Conde #if !USING_OPENSSL3
443762f1ebeSMasahiro Yamada 		if (!key_new(&keys[i])) {
444762f1ebeSMasahiro Yamada 			ERROR("Failed to allocate key container\n");
445762f1ebeSMasahiro Yamada 			exit(1);
446762f1ebeSMasahiro Yamada 		}
447cf2dd17dSJuan Pablo Conde #endif
448762f1ebeSMasahiro Yamada 
449ccbf890eSJuan Castillo 		/* First try to load the key from disk */
450bb3b0c0bSSandrine Bailleux 		err_code = key_load(&keys[i]);
451bb3b0c0bSSandrine Bailleux 		if (err_code == KEY_ERR_NONE) {
452ccbf890eSJuan Castillo 			/* Key loaded successfully */
453ccbf890eSJuan Castillo 			continue;
454ccbf890eSJuan Castillo 		}
455ccbf890eSJuan Castillo 
456ccbf890eSJuan Castillo 		/* Key not loaded. Check the error code */
457762f1ebeSMasahiro Yamada 		if (err_code == KEY_ERR_LOAD) {
458ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
459ccbf890eSJuan Castillo 			 * key. Abort. */
460ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
4616f971622SJuan Castillo 			exit(1);
4626f971622SJuan Castillo 		}
463ccbf890eSJuan Castillo 
464ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
465ccbf890eSJuan Castillo 		 * given */
466ccbf890eSJuan Castillo 		if (new_keys) {
467ccbf890eSJuan Castillo 			/* Try to create a new key */
468ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
469dfe0f4c2SJustin Chadwell 			if (!key_create(&keys[i], key_alg, key_size)) {
470ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
471ccbf890eSJuan Castillo 				exit(1);
4726f971622SJuan Castillo 			}
4736f971622SJuan Castillo 		} else {
474ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
475ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
476ccbf890eSJuan Castillo 			} else {
477ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
4786f971622SJuan Castillo 			}
479ccbf890eSJuan Castillo 			exit(1);
4806f971622SJuan Castillo 		}
4816f971622SJuan Castillo 	}
4826f971622SJuan Castillo 
48355e291a4SJuan Castillo 	/* Create the certificates */
48455e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
48555e291a4SJuan Castillo 
48655e291a4SJuan Castillo 		cert = &certs[i];
48755e291a4SJuan Castillo 
488294e2656SManish V Badarkhe 		if (cert->fn == NULL) {
489294e2656SManish V Badarkhe 			/* Certificate not requested. Skip to the next one */
490294e2656SManish V Badarkhe 			continue;
491294e2656SManish V Badarkhe 		}
492294e2656SManish V Badarkhe 
49355e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
49455e291a4SJuan Castillo 		 * to create the certificate */
4956f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
4966f971622SJuan Castillo 
49755e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
4986f971622SJuan Castillo 
49955e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
50055e291a4SJuan Castillo 
50155e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
50255e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
50355e291a4SJuan Castillo 
50455e291a4SJuan Castillo 			/*
50555e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
50655e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
50755e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
50855e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
50955e291a4SJuan Castillo 			 */
51055e291a4SJuan Castillo 			switch (ext->type) {
51155e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
5121ed941c0SJimmy Brisson 				if (ext->optional && ext->arg == NULL) {
5131ed941c0SJimmy Brisson 					/* Skip this NVCounter */
5141ed941c0SJimmy Brisson 					continue;
5151ed941c0SJimmy Brisson 				} else {
5161ed941c0SJimmy Brisson 					/* Checked by `check_cmd_params` */
5171ed941c0SJimmy Brisson 					assert(ext->arg != NULL);
51896103d5aSJuan Castillo 					nvctr = atoi(ext->arg);
51955e291a4SJuan Castillo 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
52096103d5aSJuan Castillo 						EXT_CRIT, nvctr));
521f16db56aSYatharth Kochar 				}
52255e291a4SJuan Castillo 				break;
52355e291a4SJuan Castillo 			case EXT_TYPE_HASH:
52496103d5aSJuan Castillo 				if (ext->arg == NULL) {
525cebe1f23SYatharth Kochar 					if (ext->optional) {
526cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
5272972247cSQixiang Xu 						memset(md, 0x0, SHA512_DIGEST_LENGTH);
528cebe1f23SYatharth Kochar 					} else {
529cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
5301ed941c0SJimmy Brisson 						continue;
53155e291a4SJuan Castillo 					}
532cebe1f23SYatharth Kochar 				} else {
533cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
5342972247cSQixiang Xu 					if (!sha_file(hash_alg, ext->arg, md)) {
53555e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
53696103d5aSJuan Castillo 							ext->arg);
5376f971622SJuan Castillo 						exit(1);
5386f971622SJuan Castillo 					}
539cebe1f23SYatharth Kochar 				}
54055e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
54155e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
5422972247cSQixiang Xu 						md_len));
54355e291a4SJuan Castillo 				break;
54455e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
54555e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
54696103d5aSJuan Castillo 					EXT_CRIT, keys[ext->attr.key].key));
54755e291a4SJuan Castillo 				break;
54855e291a4SJuan Castillo 			default:
54996103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in %s\n",
55096103d5aSJuan Castillo 						ext->type, cert->cn);
55155e291a4SJuan Castillo 				exit(1);
55255e291a4SJuan Castillo 			}
55355e291a4SJuan Castillo 
55455e291a4SJuan Castillo 			/* Push the extension into the stack */
55555e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
55655e291a4SJuan Castillo 		}
5576f971622SJuan Castillo 
558a8eb286aSSoby Mathew 		/* Create certificate. Signed with corresponding key */
559294e2656SManish V Badarkhe 		if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
56055e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
5616f971622SJuan Castillo 			exit(1);
5626f971622SJuan Castillo 		}
5636f971622SJuan Castillo 
564bea80198SJimmy Brisson 		for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
565bea80198SJimmy Brisson 				cert_ext = sk_X509_EXTENSION_pop(sk)) {
566bea80198SJimmy Brisson 			X509_EXTENSION_free(cert_ext);
567bea80198SJimmy Brisson 		}
568bea80198SJimmy Brisson 
5696f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
5706f971622SJuan Castillo 	}
5716f971622SJuan Castillo 
5726f971622SJuan Castillo 
5736f971622SJuan Castillo 	/* Print the certificates */
5746f971622SJuan Castillo 	if (print_cert) {
57555e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
5766f971622SJuan Castillo 			if (!certs[i].x) {
5776f971622SJuan Castillo 				continue;
5786f971622SJuan Castillo 			}
5796f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
5806f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
5816f971622SJuan Castillo 		}
5826f971622SJuan Castillo 	}
5836f971622SJuan Castillo 
5846f971622SJuan Castillo 	/* Save created certificates to files */
58555e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
5866f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
5876f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
5886f971622SJuan Castillo 			if (file != NULL) {
5896f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
5906f971622SJuan Castillo 				fclose(file);
5916f971622SJuan Castillo 			} else {
5926f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
5936f971622SJuan Castillo 			}
5946f971622SJuan Castillo 		}
5956f971622SJuan Castillo 	}
5966f971622SJuan Castillo 
5976f971622SJuan Castillo 	/* Save keys */
5986f971622SJuan Castillo 	if (save_keys) {
59955e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
6006f971622SJuan Castillo 			if (!key_store(&keys[i])) {
6016f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
6026f971622SJuan Castillo 			}
6036f971622SJuan Castillo 		}
6046f971622SJuan Castillo 	}
6056f971622SJuan Castillo 
6061f111f12SJimmy Brisson 	/* If we got here, then we must have filled the key array completely.
6071f111f12SJimmy Brisson 	 * We can then safely call free on all of the keys in the array
6081f111f12SJimmy Brisson 	 */
609cf2dd17dSJuan Pablo Conde 	key_cleanup();
6101f111f12SJimmy Brisson 
6116f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
6126f971622SJuan Castillo 	ENGINE_cleanup();
6136f971622SJuan Castillo #endif
6146f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
6156f971622SJuan Castillo 
6164a34d18fSJimmy Brisson 
6174a34d18fSJimmy Brisson 	/* We allocated strings through strdup, so now we have to free them */
6184a34d18fSJimmy Brisson 
619cf2dd17dSJuan Pablo Conde 	ext_cleanup();
6204a34d18fSJimmy Brisson 
621cf2dd17dSJuan Pablo Conde 	cert_cleanup();
6224a34d18fSJimmy Brisson 
6236f971622SJuan Castillo 	return 0;
6246f971622SJuan Castillo }
625