xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision dfe0f4c2999cef10f9c8fb6115e53891f6b2c190)
16f971622SJuan Castillo /*
265ec13bcSJustin Chadwell  * Copyright (c) 2015-2019, 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>
13*dfe0f4c2SJustin 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 
22bb41eb7aSMasahiro Yamada #if USE_TBBR_DEFS
23bb41eb7aSMasahiro Yamada #include <tbbr_oid.h>
24bb41eb7aSMasahiro Yamada #else
25bb41eb7aSMasahiro Yamada #include <platform_oid.h>
26bb41eb7aSMasahiro Yamada #endif
27bb41eb7aSMasahiro Yamada 
286f971622SJuan Castillo #include "cert.h"
29ad2c1a9aSJuan Castillo #include "cmd_opt.h"
306f971622SJuan Castillo #include "debug.h"
316f971622SJuan Castillo #include "ext.h"
326f971622SJuan Castillo #include "key.h"
336f971622SJuan Castillo #include "sha.h"
3455e291a4SJuan Castillo #include "tbbr/tbb_cert.h"
352a4b4b71SIsla Mitchell #include "tbbr/tbb_ext.h"
3655e291a4SJuan Castillo #include "tbbr/tbb_key.h"
376f971622SJuan Castillo 
386f971622SJuan Castillo /*
396f971622SJuan Castillo  * Helper macros to simplify the code. This macro assigns the return value of
406f971622SJuan Castillo  * the 'fn' function to 'v' and exits if the value is NULL.
416f971622SJuan Castillo  */
426f971622SJuan Castillo #define CHECK_NULL(v, fn) \
436f971622SJuan Castillo 	do { \
446f971622SJuan Castillo 		v = fn; \
456f971622SJuan Castillo 		if (v == NULL) { \
466f971622SJuan Castillo 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
476f971622SJuan Castillo 			exit(1); \
486f971622SJuan Castillo 		} \
496f971622SJuan Castillo 	} while (0)
506f971622SJuan Castillo 
516f971622SJuan Castillo /*
526f971622SJuan Castillo  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
536f971622SJuan Castillo  * NID is undefined.
546f971622SJuan Castillo  */
556f971622SJuan Castillo #define CHECK_OID(v, oid) \
566f971622SJuan Castillo 	do { \
576f971622SJuan Castillo 		v = OBJ_txt2nid(oid); \
586f971622SJuan Castillo 		if (v == NID_undef) { \
596f971622SJuan Castillo 			ERROR("Cannot find TBB extension %s\n", oid); \
606f971622SJuan Castillo 			exit(1); \
616f971622SJuan Castillo 		} \
626f971622SJuan Castillo 	} while (0)
636f971622SJuan Castillo 
646f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
656f971622SJuan Castillo #define VAL_DAYS			7300
666f971622SJuan Castillo #define ID_TO_BIT_MASK(id)		(1 << id)
67ccbf890eSJuan Castillo #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
68159807e2SJuan Castillo #define HELP_OPT_MAX_LEN		128
696f971622SJuan Castillo 
706f971622SJuan Castillo /* Global options */
71ccbf890eSJuan Castillo static int key_alg;
722972247cSQixiang Xu static int hash_alg;
73*dfe0f4c2SJustin Chadwell static int key_size;
746f971622SJuan Castillo static int new_keys;
756f971622SJuan Castillo static int save_keys;
766f971622SJuan Castillo static int print_cert;
776f971622SJuan Castillo 
786f971622SJuan Castillo /* Info messages created in the Makefile */
796f971622SJuan Castillo extern const char build_msg[];
806f971622SJuan Castillo extern const char platform_msg[];
816f971622SJuan Castillo 
826f971622SJuan Castillo 
836f971622SJuan Castillo static char *strdup(const char *str)
846f971622SJuan Castillo {
856f971622SJuan Castillo 	int n = strlen(str) + 1;
866f971622SJuan Castillo 	char *dup = malloc(n);
876f971622SJuan Castillo 	if (dup) {
886f971622SJuan Castillo 		strcpy(dup, str);
896f971622SJuan Castillo 	}
906f971622SJuan Castillo 	return dup;
916f971622SJuan Castillo }
926f971622SJuan Castillo 
93ccbf890eSJuan Castillo static const char *key_algs_str[] = {
94ccbf890eSJuan Castillo 	[KEY_ALG_RSA] = "rsa",
95a8eb286aSSoby Mathew 	[KEY_ALG_RSA_1_5] = "rsa_1_5",
96ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
97ccbf890eSJuan Castillo 	[KEY_ALG_ECDSA] = "ecdsa"
98ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
99ccbf890eSJuan Castillo };
100ccbf890eSJuan Castillo 
1012972247cSQixiang Xu static const char *hash_algs_str[] = {
1022972247cSQixiang Xu 	[HASH_ALG_SHA256] = "sha256",
1032972247cSQixiang Xu 	[HASH_ALG_SHA384] = "sha384",
1042972247cSQixiang Xu 	[HASH_ALG_SHA512] = "sha512",
1052972247cSQixiang Xu };
1062972247cSQixiang Xu 
107ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt)
1086f971622SJuan Castillo {
109159807e2SJuan Castillo 	int rem, i = 0;
110159807e2SJuan Castillo 	const struct option *opt;
111159807e2SJuan Castillo 	char line[HELP_OPT_MAX_LEN];
112159807e2SJuan Castillo 	char *p;
113159807e2SJuan Castillo 
114159807e2SJuan Castillo 	assert(cmd != NULL);
115159807e2SJuan Castillo 	assert(long_opt != NULL);
116159807e2SJuan Castillo 
1176f971622SJuan Castillo 	printf("\n\n");
1186f971622SJuan Castillo 	printf("The certificate generation tool loads the binary images and\n"
1196f971622SJuan Castillo 	       "optionally the RSA keys, and outputs the key and content\n"
1206f971622SJuan Castillo 	       "certificates properly signed to implement the chain of trust.\n"
1216f971622SJuan Castillo 	       "If keys are provided, they must be in PEM format.\n"
1226f971622SJuan Castillo 	       "Certificates are generated in DER format.\n");
1236f971622SJuan Castillo 	printf("\n");
124159807e2SJuan Castillo 	printf("Usage:\n");
125159807e2SJuan Castillo 	printf("\t%s [OPTIONS]\n\n", cmd);
126159807e2SJuan Castillo 
127159807e2SJuan Castillo 	printf("Available options:\n");
128159807e2SJuan Castillo 	opt = long_opt;
129159807e2SJuan Castillo 	while (opt->name) {
130159807e2SJuan Castillo 		p = line;
131159807e2SJuan Castillo 		rem = HELP_OPT_MAX_LEN;
132159807e2SJuan Castillo 		if (isalpha(opt->val)) {
133159807e2SJuan Castillo 			/* Short format */
134159807e2SJuan Castillo 			sprintf(p, "-%c,", (char)opt->val);
135159807e2SJuan Castillo 			p += 3;
136159807e2SJuan Castillo 			rem -= 3;
1376f971622SJuan Castillo 		}
138159807e2SJuan Castillo 		snprintf(p, rem, "--%s %s", opt->name,
139159807e2SJuan Castillo 			 (opt->has_arg == required_argument) ? "<arg>" : "");
140159807e2SJuan Castillo 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
141159807e2SJuan Castillo 		opt++;
142159807e2SJuan Castillo 		i++;
143159807e2SJuan Castillo 	}
1446f971622SJuan Castillo 	printf("\n");
1456f971622SJuan Castillo }
1466f971622SJuan Castillo 
147ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
148ccbf890eSJuan Castillo {
149ccbf890eSJuan Castillo 	int i;
150ccbf890eSJuan Castillo 
151ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
152ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
153ccbf890eSJuan Castillo 			return i;
154ccbf890eSJuan Castillo 		}
155ccbf890eSJuan Castillo 	}
156ccbf890eSJuan Castillo 
157ccbf890eSJuan Castillo 	return -1;
158ccbf890eSJuan Castillo }
159ccbf890eSJuan Castillo 
160*dfe0f4c2SJustin Chadwell static int get_key_size(const char *key_size_str)
161*dfe0f4c2SJustin Chadwell {
162*dfe0f4c2SJustin Chadwell 	char *end;
163*dfe0f4c2SJustin Chadwell 	long key_size;
164*dfe0f4c2SJustin Chadwell 
165*dfe0f4c2SJustin Chadwell 	key_size = strtol(key_size_str, &end, 10);
166*dfe0f4c2SJustin Chadwell 	if (*end != '\0')
167*dfe0f4c2SJustin Chadwell 		return -1;
168*dfe0f4c2SJustin Chadwell 
169*dfe0f4c2SJustin Chadwell 	return key_size;
170*dfe0f4c2SJustin Chadwell }
171*dfe0f4c2SJustin Chadwell 
1722972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str)
1732972247cSQixiang Xu {
1742972247cSQixiang Xu 	int i;
1752972247cSQixiang Xu 
1762972247cSQixiang Xu 	for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
1772972247cSQixiang Xu 		if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
1782972247cSQixiang Xu 			return i;
1792972247cSQixiang Xu 		}
1802972247cSQixiang Xu 	}
1812972247cSQixiang Xu 
1822972247cSQixiang Xu 	return -1;
1832972247cSQixiang Xu }
1842972247cSQixiang Xu 
1856f971622SJuan Castillo static void check_cmd_params(void)
1866f971622SJuan Castillo {
187dfc90e26SJuan Castillo 	cert_t *cert;
188dfc90e26SJuan Castillo 	ext_t *ext;
189dfc90e26SJuan Castillo 	key_t *key;
190dfc90e26SJuan Castillo 	int i, j;
191*dfe0f4c2SJustin Chadwell 	bool valid_size;
192dfc90e26SJuan Castillo 
193ccbf890eSJuan Castillo 	/* Only save new keys */
194ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
195ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
196ccbf890eSJuan Castillo 		exit(1);
197ccbf890eSJuan Castillo 	}
198ccbf890eSJuan Castillo 
199*dfe0f4c2SJustin Chadwell 	/* Validate key-size */
200*dfe0f4c2SJustin Chadwell 	valid_size = false;
201*dfe0f4c2SJustin Chadwell 	for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
202*dfe0f4c2SJustin Chadwell 		if (key_size == KEY_SIZES[key_alg][i]) {
203*dfe0f4c2SJustin Chadwell 			valid_size = true;
204*dfe0f4c2SJustin Chadwell 			break;
205*dfe0f4c2SJustin Chadwell 		}
206*dfe0f4c2SJustin Chadwell 	}
207*dfe0f4c2SJustin Chadwell 	if (!valid_size) {
208*dfe0f4c2SJustin Chadwell 		ERROR("'%d' is not a valid key size for '%s'\n",
209*dfe0f4c2SJustin Chadwell 				key_size, key_algs_str[key_alg]);
210*dfe0f4c2SJustin Chadwell 		NOTICE("Valid sizes are: ");
211*dfe0f4c2SJustin Chadwell 		for (i = 0; i < KEY_SIZE_MAX_NUM &&
212*dfe0f4c2SJustin Chadwell 				KEY_SIZES[key_alg][i] != 0; i++) {
213*dfe0f4c2SJustin Chadwell 			printf("%d ", KEY_SIZES[key_alg][i]);
214*dfe0f4c2SJustin Chadwell 		}
215*dfe0f4c2SJustin Chadwell 		printf("\n");
216*dfe0f4c2SJustin Chadwell 		exit(1);
217*dfe0f4c2SJustin Chadwell 	}
218*dfe0f4c2SJustin Chadwell 
219dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
220dfc90e26SJuan Castillo 	 * command line */
221dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
222dfc90e26SJuan Castillo 		cert = &certs[i];
223dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
224dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
225dfc90e26SJuan Castillo 			continue;
226dfc90e26SJuan Castillo 		}
227dfc90e26SJuan Castillo 
228dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
229dfc90e26SJuan Castillo 		 * have been specified in the command line */
230dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
231dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
232dfc90e26SJuan Castillo 			switch (ext->type) {
23396103d5aSJuan Castillo 			case EXT_TYPE_NVCOUNTER:
23496103d5aSJuan Castillo 				/* Counter value must be specified */
23596103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
23696103d5aSJuan Castillo 					ERROR("Value for '%s' not specified\n",
23796103d5aSJuan Castillo 					      ext->ln);
23896103d5aSJuan Castillo 					exit(1);
23996103d5aSJuan Castillo 				}
24096103d5aSJuan Castillo 				break;
241dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
242dfc90e26SJuan Castillo 				/* Key filename must be specified */
24396103d5aSJuan Castillo 				key = &keys[ext->attr.key];
244dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
245dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
246dfc90e26SJuan Castillo 					      "specified\n", key->desc,
247dfc90e26SJuan Castillo 					      cert->cn);
2486f971622SJuan Castillo 					exit(1);
2496f971622SJuan Castillo 				}
250dfc90e26SJuan Castillo 				break;
251dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
252cebe1f23SYatharth Kochar 				/*
253cebe1f23SYatharth Kochar 				 * Binary image must be specified
254cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
255cebe1f23SYatharth Kochar 				 */
25696103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
257dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
258dfc90e26SJuan Castillo 					      ext->ln);
2596f971622SJuan Castillo 					exit(1);
2606f971622SJuan Castillo 				}
261dfc90e26SJuan Castillo 				break;
262dfc90e26SJuan Castillo 			default:
26396103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in '%s'\n",
26496103d5aSJuan Castillo 				      ext->type, ext->ln);
2656f971622SJuan Castillo 				exit(1);
266dfc90e26SJuan Castillo 				break;
2676f971622SJuan Castillo 			}
2686f971622SJuan Castillo 		}
2696f971622SJuan Castillo 	}
2706f971622SJuan Castillo }
2716f971622SJuan Castillo 
272159807e2SJuan Castillo /* Common command line options */
273159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = {
274159807e2SJuan Castillo 	{
275159807e2SJuan Castillo 		{ "help", no_argument, NULL, 'h' },
276159807e2SJuan Castillo 		"Print this message and exit"
277159807e2SJuan Castillo 	},
278159807e2SJuan Castillo 	{
279159807e2SJuan Castillo 		{ "key-alg", required_argument, NULL, 'a' },
280a8eb286aSSoby Mathew 		"Key algorithm: 'rsa' (default) - RSAPSS scheme as per \
281a8eb286aSSoby Mathew PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'"
282159807e2SJuan Castillo 	},
283159807e2SJuan Castillo 	{
284*dfe0f4c2SJustin Chadwell 		{ "key-size", required_argument, NULL, 'b' },
285*dfe0f4c2SJustin Chadwell 		"Key size (for supported algorithms)."
286*dfe0f4c2SJustin Chadwell 	},
287*dfe0f4c2SJustin Chadwell 	{
2882972247cSQixiang Xu 		{ "hash-alg", required_argument, NULL, 's' },
2892972247cSQixiang Xu 		"Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
2902972247cSQixiang Xu 	},
2912972247cSQixiang Xu 	{
292159807e2SJuan Castillo 		{ "save-keys", no_argument, NULL, 'k' },
293159807e2SJuan Castillo 		"Save key pairs into files. Filenames must be provided"
294159807e2SJuan Castillo 	},
295159807e2SJuan Castillo 	{
296159807e2SJuan Castillo 		{ "new-keys", no_argument, NULL, 'n' },
297159807e2SJuan Castillo 		"Generate new key pairs if no key files are provided"
298159807e2SJuan Castillo 	},
299159807e2SJuan Castillo 	{
300159807e2SJuan Castillo 		{ "print-cert", no_argument, NULL, 'p' },
301159807e2SJuan Castillo 		"Print the certificates in the standard output"
302159807e2SJuan Castillo 	}
303159807e2SJuan Castillo };
304159807e2SJuan Castillo 
3056f971622SJuan Castillo int main(int argc, char *argv[])
3066f971622SJuan Castillo {
307c893c733SMasahiro Yamada 	STACK_OF(X509_EXTENSION) * sk;
308742c4e14SMichalis Pappas 	X509_EXTENSION *cert_ext = NULL;
309c893c733SMasahiro Yamada 	ext_t *ext;
310c893c733SMasahiro Yamada 	key_t *key;
311c893c733SMasahiro Yamada 	cert_t *cert;
312c893c733SMasahiro Yamada 	FILE *file;
31396103d5aSJuan Castillo 	int i, j, ext_nid, nvctr;
3146f971622SJuan Castillo 	int c, opt_idx = 0;
315ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
316ad2c1a9aSJuan Castillo 	const char *cur_opt;
317ccbf890eSJuan Castillo 	unsigned int err_code;
3182972247cSQixiang Xu 	unsigned char md[SHA512_DIGEST_LENGTH];
3192972247cSQixiang Xu 	unsigned int  md_len;
320c3da66b1SJuan Castillo 	const EVP_MD *md_info;
3216f971622SJuan Castillo 
3226f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
3236f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
3246f971622SJuan Castillo 
325ccbf890eSJuan Castillo 	/* Set default options */
326ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
3272972247cSQixiang Xu 	hash_alg = HASH_ALG_SHA256;
328*dfe0f4c2SJustin Chadwell 	key_size = -1;
329ccbf890eSJuan Castillo 
330ad2c1a9aSJuan Castillo 	/* Add common command line options */
331159807e2SJuan Castillo 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
332159807e2SJuan Castillo 		cmd_opt_add(&common_cmd_opt[i]);
333159807e2SJuan Castillo 	}
334ad2c1a9aSJuan Castillo 
335ad2c1a9aSJuan Castillo 	/* Initialize the certificates */
336ad2c1a9aSJuan Castillo 	if (cert_init() != 0) {
337ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize certificates\n");
338ad2c1a9aSJuan Castillo 		exit(1);
339ad2c1a9aSJuan Castillo 	}
340ad2c1a9aSJuan Castillo 
341ad2c1a9aSJuan Castillo 	/* Initialize the keys */
342ad2c1a9aSJuan Castillo 	if (key_init() != 0) {
343ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize keys\n");
344ad2c1a9aSJuan Castillo 		exit(1);
345ad2c1a9aSJuan Castillo 	}
346ad2c1a9aSJuan Castillo 
347ad2c1a9aSJuan Castillo 	/* Initialize the new types and register OIDs for the extensions */
348ad2c1a9aSJuan Castillo 	if (ext_init() != 0) {
349ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize TBB extensions\n");
350ad2c1a9aSJuan Castillo 		exit(1);
351ad2c1a9aSJuan Castillo 	}
352ad2c1a9aSJuan Castillo 
353ad2c1a9aSJuan Castillo 	/* Get the command line options populated during the initialization */
354ad2c1a9aSJuan Castillo 	cmd_opt = cmd_opt_get_array();
355ad2c1a9aSJuan Castillo 
3566f971622SJuan Castillo 	while (1) {
3576f971622SJuan Castillo 		/* getopt_long stores the option index here. */
358*dfe0f4c2SJustin Chadwell 		c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
3596f971622SJuan Castillo 
3606f971622SJuan Castillo 		/* Detect the end of the options. */
3616f971622SJuan Castillo 		if (c == -1) {
3626f971622SJuan Castillo 			break;
3636f971622SJuan Castillo 		}
3646f971622SJuan Castillo 
3656f971622SJuan Castillo 		switch (c) {
366ccbf890eSJuan Castillo 		case 'a':
367ccbf890eSJuan Castillo 			key_alg = get_key_alg(optarg);
368ccbf890eSJuan Castillo 			if (key_alg < 0) {
369ccbf890eSJuan Castillo 				ERROR("Invalid key algorithm '%s'\n", optarg);
370ccbf890eSJuan Castillo 				exit(1);
371ccbf890eSJuan Castillo 			}
372ccbf890eSJuan Castillo 			break;
373*dfe0f4c2SJustin Chadwell 		case 'b':
374*dfe0f4c2SJustin Chadwell 			key_size = get_key_size(optarg);
375*dfe0f4c2SJustin Chadwell 			if (key_size <= 0) {
376*dfe0f4c2SJustin Chadwell 				ERROR("Invalid key size '%s'\n", optarg);
377*dfe0f4c2SJustin Chadwell 				exit(1);
378*dfe0f4c2SJustin Chadwell 			}
379*dfe0f4c2SJustin Chadwell 			break;
3806f971622SJuan Castillo 		case 'h':
381ad2c1a9aSJuan Castillo 			print_help(argv[0], cmd_opt);
382600835d0SRoberto Vargas 			exit(0);
3836f971622SJuan Castillo 		case 'k':
3846f971622SJuan Castillo 			save_keys = 1;
3856f971622SJuan Castillo 			break;
3866f971622SJuan Castillo 		case 'n':
3876f971622SJuan Castillo 			new_keys = 1;
3886f971622SJuan Castillo 			break;
3896f971622SJuan Castillo 		case 'p':
3906f971622SJuan Castillo 			print_cert = 1;
3916f971622SJuan Castillo 			break;
3922972247cSQixiang Xu 		case 's':
3932972247cSQixiang Xu 			hash_alg = get_hash_alg(optarg);
3942972247cSQixiang Xu 			if (hash_alg < 0) {
3952972247cSQixiang Xu 				ERROR("Invalid hash algorithm '%s'\n", optarg);
3962972247cSQixiang Xu 				exit(1);
3972972247cSQixiang Xu 			}
3982972247cSQixiang Xu 			break;
399ad2c1a9aSJuan Castillo 		case CMD_OPT_EXT:
400ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
401ad2c1a9aSJuan Castillo 			ext = ext_get_by_opt(cur_opt);
40296103d5aSJuan Castillo 			ext->arg = strdup(optarg);
4036f971622SJuan Castillo 			break;
404ad2c1a9aSJuan Castillo 		case CMD_OPT_KEY:
405ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
406ad2c1a9aSJuan Castillo 			key = key_get_by_opt(cur_opt);
407ad2c1a9aSJuan Castillo 			key->fn = strdup(optarg);
4086f971622SJuan Castillo 			break;
409ad2c1a9aSJuan Castillo 		case CMD_OPT_CERT:
410ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
411ad2c1a9aSJuan Castillo 			cert = cert_get_by_opt(cur_opt);
412ad2c1a9aSJuan Castillo 			cert->fn = strdup(optarg);
4136f971622SJuan Castillo 			break;
4146f971622SJuan Castillo 		case '?':
4156f971622SJuan Castillo 		default:
416159807e2SJuan Castillo 			print_help(argv[0], cmd_opt);
4176f971622SJuan Castillo 			exit(1);
4186f971622SJuan Castillo 		}
4196f971622SJuan Castillo 	}
4206f971622SJuan Castillo 
421*dfe0f4c2SJustin Chadwell 	/* Select a reasonable default key-size */
422*dfe0f4c2SJustin Chadwell 	if (key_size == -1) {
423*dfe0f4c2SJustin Chadwell 		key_size = KEY_SIZES[key_alg][0];
424*dfe0f4c2SJustin Chadwell 	}
425*dfe0f4c2SJustin Chadwell 
4266f971622SJuan Castillo 	/* Check command line arguments */
4276f971622SJuan Castillo 	check_cmd_params();
4286f971622SJuan Castillo 
4292972247cSQixiang Xu 	/* Indicate SHA as image hash algorithm in the certificate
430c3da66b1SJuan Castillo 	 * extension */
4312972247cSQixiang Xu 	if (hash_alg == HASH_ALG_SHA384) {
4322972247cSQixiang Xu 		md_info = EVP_sha384();
4332972247cSQixiang Xu 		md_len  = SHA384_DIGEST_LENGTH;
4342972247cSQixiang Xu 	} else if (hash_alg == HASH_ALG_SHA512) {
4352972247cSQixiang Xu 		md_info = EVP_sha512();
4362972247cSQixiang Xu 		md_len  = SHA512_DIGEST_LENGTH;
4372972247cSQixiang Xu 	} else {
438c3da66b1SJuan Castillo 		md_info = EVP_sha256();
4392972247cSQixiang Xu 		md_len  = SHA256_DIGEST_LENGTH;
4402972247cSQixiang Xu 	}
441c3da66b1SJuan Castillo 
4426f971622SJuan Castillo 	/* Load private keys from files (or generate new ones) */
44355e291a4SJuan Castillo 	for (i = 0 ; i < num_keys ; i++) {
444762f1ebeSMasahiro Yamada 		if (!key_new(&keys[i])) {
445762f1ebeSMasahiro Yamada 			ERROR("Failed to allocate key container\n");
446762f1ebeSMasahiro Yamada 			exit(1);
447762f1ebeSMasahiro Yamada 		}
448762f1ebeSMasahiro Yamada 
449ccbf890eSJuan Castillo 		/* First try to load the key from disk */
450ccbf890eSJuan Castillo 		if (key_load(&keys[i], &err_code)) {
451ccbf890eSJuan Castillo 			/* Key loaded successfully */
452ccbf890eSJuan Castillo 			continue;
453ccbf890eSJuan Castillo 		}
454ccbf890eSJuan Castillo 
455ccbf890eSJuan Castillo 		/* Key not loaded. Check the error code */
456762f1ebeSMasahiro Yamada 		if (err_code == KEY_ERR_LOAD) {
457ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
458ccbf890eSJuan Castillo 			 * key. Abort. */
459ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
4606f971622SJuan Castillo 			exit(1);
4616f971622SJuan Castillo 		}
462ccbf890eSJuan Castillo 
463ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
464ccbf890eSJuan Castillo 		 * given */
465ccbf890eSJuan Castillo 		if (new_keys) {
466ccbf890eSJuan Castillo 			/* Try to create a new key */
467ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
468*dfe0f4c2SJustin Chadwell 			if (!key_create(&keys[i], key_alg, key_size)) {
469ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
470ccbf890eSJuan Castillo 				exit(1);
4716f971622SJuan Castillo 			}
4726f971622SJuan Castillo 		} else {
473ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
474ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
475ccbf890eSJuan Castillo 			} else {
476ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
4776f971622SJuan Castillo 			}
478ccbf890eSJuan Castillo 			exit(1);
4796f971622SJuan Castillo 		}
4806f971622SJuan Castillo 	}
4816f971622SJuan Castillo 
48255e291a4SJuan Castillo 	/* Create the certificates */
48355e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
48455e291a4SJuan Castillo 
48555e291a4SJuan Castillo 		cert = &certs[i];
48655e291a4SJuan Castillo 
48755e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
48855e291a4SJuan Castillo 		 * to create the certificate */
4896f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
4906f971622SJuan Castillo 
49155e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
4926f971622SJuan Castillo 
49355e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
49455e291a4SJuan Castillo 
49555e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
49655e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
49755e291a4SJuan Castillo 
49855e291a4SJuan Castillo 			/*
49955e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
50055e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
50155e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
50255e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
50355e291a4SJuan Castillo 			 */
50455e291a4SJuan Castillo 			switch (ext->type) {
50555e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
506f16db56aSYatharth Kochar 				if (ext->arg) {
50796103d5aSJuan Castillo 					nvctr = atoi(ext->arg);
50855e291a4SJuan Castillo 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
50996103d5aSJuan Castillo 						EXT_CRIT, nvctr));
510f16db56aSYatharth Kochar 				}
51155e291a4SJuan Castillo 				break;
51255e291a4SJuan Castillo 			case EXT_TYPE_HASH:
51396103d5aSJuan Castillo 				if (ext->arg == NULL) {
514cebe1f23SYatharth Kochar 					if (ext->optional) {
515cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
5162972247cSQixiang Xu 						memset(md, 0x0, SHA512_DIGEST_LENGTH);
517cebe1f23SYatharth Kochar 					} else {
518cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
51955e291a4SJuan Castillo 						break;
52055e291a4SJuan Castillo 					}
521cebe1f23SYatharth Kochar 				} else {
522cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
5232972247cSQixiang Xu 					if (!sha_file(hash_alg, ext->arg, md)) {
52455e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
52596103d5aSJuan Castillo 							ext->arg);
5266f971622SJuan Castillo 						exit(1);
5276f971622SJuan Castillo 					}
528cebe1f23SYatharth Kochar 				}
52955e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
53055e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
5312972247cSQixiang Xu 						md_len));
53255e291a4SJuan Castillo 				break;
53355e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
53455e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
53596103d5aSJuan Castillo 					EXT_CRIT, keys[ext->attr.key].key));
53655e291a4SJuan Castillo 				break;
53755e291a4SJuan Castillo 			default:
53896103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in %s\n",
53996103d5aSJuan Castillo 						ext->type, cert->cn);
54055e291a4SJuan Castillo 				exit(1);
54155e291a4SJuan Castillo 			}
54255e291a4SJuan Castillo 
54355e291a4SJuan Castillo 			/* Push the extension into the stack */
54455e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
54555e291a4SJuan Castillo 		}
5466f971622SJuan Castillo 
547a8eb286aSSoby Mathew 		/* Create certificate. Signed with corresponding key */
5482972247cSQixiang Xu 		if (cert->fn && !cert_new(key_alg, hash_alg, cert, VAL_DAYS, 0, sk)) {
54955e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
5506f971622SJuan Castillo 			exit(1);
5516f971622SJuan Castillo 		}
5526f971622SJuan Castillo 
5536f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
5546f971622SJuan Castillo 	}
5556f971622SJuan Castillo 
5566f971622SJuan Castillo 
5576f971622SJuan Castillo 	/* Print the certificates */
5586f971622SJuan Castillo 	if (print_cert) {
55955e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
5606f971622SJuan Castillo 			if (!certs[i].x) {
5616f971622SJuan Castillo 				continue;
5626f971622SJuan Castillo 			}
5636f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
5646f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
5656f971622SJuan Castillo 		}
5666f971622SJuan Castillo 	}
5676f971622SJuan Castillo 
5686f971622SJuan Castillo 	/* Save created certificates to files */
56955e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
5706f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
5716f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
5726f971622SJuan Castillo 			if (file != NULL) {
5736f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
5746f971622SJuan Castillo 				fclose(file);
5756f971622SJuan Castillo 			} else {
5766f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
5776f971622SJuan Castillo 			}
5786f971622SJuan Castillo 		}
5796f971622SJuan Castillo 	}
5806f971622SJuan Castillo 
5816f971622SJuan Castillo 	/* Save keys */
5826f971622SJuan Castillo 	if (save_keys) {
58355e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
5846f971622SJuan Castillo 			if (!key_store(&keys[i])) {
5856f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
5866f971622SJuan Castillo 			}
5876f971622SJuan Castillo 		}
5886f971622SJuan Castillo 	}
5896f971622SJuan Castillo 
5906f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
5916f971622SJuan Castillo 	ENGINE_cleanup();
5926f971622SJuan Castillo #endif
5936f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
5946f971622SJuan Castillo 
5956f971622SJuan Castillo 	return 0;
5966f971622SJuan Castillo }
597