blob: d5abe4917d05273404befa56ccf8f773d79fd72d [file] [log] [blame]
Juan Castillo6f971622014-10-21 11:30:42 +01001/*
Sandrine Bailleuxba1eaab2020-01-07 15:12:08 +01002 * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
Juan Castillo6f971622014-10-21 11:30:42 +01003 *
dp-arm82cb2c12017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Juan Castillo6f971622014-10-21 11:30:42 +01005 */
6
Juan Castillo159807e2015-12-15 16:37:57 +00007#include <assert.h>
8#include <ctype.h>
Juan Castillo6f971622014-10-21 11:30:42 +01009#include <getopt.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +010013#include <stdbool.h>
Juan Castillo6f971622014-10-21 11:30:42 +010014
15#include <openssl/conf.h>
16#include <openssl/engine.h>
17#include <openssl/err.h>
18#include <openssl/pem.h>
19#include <openssl/sha.h>
20#include <openssl/x509v3.h>
21
22#include "cert.h"
Juan Castilload2c1a92015-07-03 16:23:16 +010023#include "cmd_opt.h"
Juan Castillo6f971622014-10-21 11:30:42 +010024#include "debug.h"
25#include "ext.h"
26#include "key.h"
Juan Castillo6f971622014-10-21 11:30:42 +010027#include "sha.h"
Juan Castillo6f971622014-10-21 11:30:42 +010028
29/*
30 * Helper macros to simplify the code. This macro assigns the return value of
31 * the 'fn' function to 'v' and exits if the value is NULL.
32 */
33#define CHECK_NULL(v, fn) \
34 do { \
35 v = fn; \
36 if (v == NULL) { \
37 ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
38 exit(1); \
39 } \
40 } while (0)
41
42/*
43 * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
44 * NID is undefined.
45 */
46#define CHECK_OID(v, oid) \
47 do { \
48 v = OBJ_txt2nid(oid); \
49 if (v == NID_undef) { \
Sandrine Bailleux067f7e92020-01-15 11:01:25 +010050 ERROR("Cannot find extension %s\n", oid); \
Juan Castillo6f971622014-10-21 11:30:42 +010051 exit(1); \
52 } \
53 } while (0)
54
55#define MAX_FILENAME_LEN 1024
56#define VAL_DAYS 7300
57#define ID_TO_BIT_MASK(id) (1 << id)
Juan Castilloccbf8902015-06-01 16:34:23 +010058#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0])))
Juan Castillo159807e2015-12-15 16:37:57 +000059#define HELP_OPT_MAX_LEN 128
Juan Castillo6f971622014-10-21 11:30:42 +010060
61/* Global options */
Juan Castilloccbf8902015-06-01 16:34:23 +010062static int key_alg;
Qixiang Xu29722472017-11-09 13:51:58 +080063static int hash_alg;
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +010064static int key_size;
Juan Castillo6f971622014-10-21 11:30:42 +010065static int new_keys;
66static int save_keys;
67static int print_cert;
Juan Castillo6f971622014-10-21 11:30:42 +010068
Juan Castillo6f971622014-10-21 11:30:42 +010069/* Info messages created in the Makefile */
70extern const char build_msg[];
71extern const char platform_msg[];
72
73
74static char *strdup(const char *str)
75{
76 int n = strlen(str) + 1;
77 char *dup = malloc(n);
78 if (dup) {
79 strcpy(dup, str);
80 }
81 return dup;
82}
83
Juan Castilloccbf8902015-06-01 16:34:23 +010084static const char *key_algs_str[] = {
85 [KEY_ALG_RSA] = "rsa",
Juan Castilloed2a76e2015-06-30 13:36:57 +010086#ifndef OPENSSL_NO_EC
Juan Castilloccbf8902015-06-01 16:34:23 +010087 [KEY_ALG_ECDSA] = "ecdsa"
Juan Castilloed2a76e2015-06-30 13:36:57 +010088#endif /* OPENSSL_NO_EC */
Juan Castilloccbf8902015-06-01 16:34:23 +010089};
90
Qixiang Xu29722472017-11-09 13:51:58 +080091static const char *hash_algs_str[] = {
92 [HASH_ALG_SHA256] = "sha256",
93 [HASH_ALG_SHA384] = "sha384",
94 [HASH_ALG_SHA512] = "sha512",
95};
96
Juan Castilload2c1a92015-07-03 16:23:16 +010097static void print_help(const char *cmd, const struct option *long_opt)
Juan Castillo6f971622014-10-21 11:30:42 +010098{
Juan Castillo159807e2015-12-15 16:37:57 +000099 int rem, i = 0;
100 const struct option *opt;
101 char line[HELP_OPT_MAX_LEN];
102 char *p;
103
104 assert(cmd != NULL);
105 assert(long_opt != NULL);
106
Juan Castillo6f971622014-10-21 11:30:42 +0100107 printf("\n\n");
108 printf("The certificate generation tool loads the binary images and\n"
109 "optionally the RSA keys, and outputs the key and content\n"
110 "certificates properly signed to implement the chain of trust.\n"
111 "If keys are provided, they must be in PEM format.\n"
112 "Certificates are generated in DER format.\n");
113 printf("\n");
Juan Castillo159807e2015-12-15 16:37:57 +0000114 printf("Usage:\n");
115 printf("\t%s [OPTIONS]\n\n", cmd);
116
117 printf("Available options:\n");
Juan Castillo159807e2015-12-15 16:37:57 +0000118 opt = long_opt;
119 while (opt->name) {
120 p = line;
121 rem = HELP_OPT_MAX_LEN;
122 if (isalpha(opt->val)) {
123 /* Short format */
124 sprintf(p, "-%c,", (char)opt->val);
125 p += 3;
126 rem -= 3;
127 }
128 snprintf(p, rem, "--%s %s", opt->name,
129 (opt->has_arg == required_argument) ? "<arg>" : "");
130 printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
131 opt++;
132 i++;
Juan Castillo6f971622014-10-21 11:30:42 +0100133 }
134 printf("\n");
Juan Castillo6f971622014-10-21 11:30:42 +0100135}
136
Juan Castilloccbf8902015-06-01 16:34:23 +0100137static int get_key_alg(const char *key_alg_str)
138{
139 int i;
140
141 for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
142 if (0 == strcmp(key_alg_str, key_algs_str[i])) {
143 return i;
144 }
145 }
146
147 return -1;
148}
149
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100150static int get_key_size(const char *key_size_str)
151{
152 char *end;
153 long key_size;
154
155 key_size = strtol(key_size_str, &end, 10);
156 if (*end != '\0')
157 return -1;
158
159 return key_size;
160}
161
Qixiang Xu29722472017-11-09 13:51:58 +0800162static int get_hash_alg(const char *hash_alg_str)
163{
164 int i;
165
166 for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
167 if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
168 return i;
169 }
170 }
171
172 return -1;
173}
174
Juan Castillo6f971622014-10-21 11:30:42 +0100175static void check_cmd_params(void)
176{
Juan Castillodfc90e22015-07-08 12:11:38 +0100177 cert_t *cert;
178 ext_t *ext;
179 key_t *key;
180 int i, j;
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100181 bool valid_size;
Juan Castillodfc90e22015-07-08 12:11:38 +0100182
Juan Castilloccbf8902015-06-01 16:34:23 +0100183 /* Only save new keys */
184 if (save_keys && !new_keys) {
185 ERROR("Only new keys can be saved to disk\n");
186 exit(1);
187 }
188
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100189 /* Validate key-size */
190 valid_size = false;
191 for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
192 if (key_size == KEY_SIZES[key_alg][i]) {
193 valid_size = true;
194 break;
195 }
196 }
197 if (!valid_size) {
198 ERROR("'%d' is not a valid key size for '%s'\n",
199 key_size, key_algs_str[key_alg]);
200 NOTICE("Valid sizes are: ");
201 for (i = 0; i < KEY_SIZE_MAX_NUM &&
202 KEY_SIZES[key_alg][i] != 0; i++) {
203 printf("%d ", KEY_SIZES[key_alg][i]);
204 }
205 printf("\n");
206 exit(1);
207 }
208
Juan Castillodfc90e22015-07-08 12:11:38 +0100209 /* Check that all required options have been specified in the
210 * command line */
211 for (i = 0; i < num_certs; i++) {
212 cert = &certs[i];
213 if (cert->fn == NULL) {
214 /* Certificate not requested. Skip to the next one */
215 continue;
Juan Castillo6f971622014-10-21 11:30:42 +0100216 }
217
Juan Castillodfc90e22015-07-08 12:11:38 +0100218 /* Check that all parameters required to create this certificate
219 * have been specified in the command line */
220 for (j = 0; j < cert->num_ext; j++) {
221 ext = &extensions[cert->ext[j]];
222 switch (ext->type) {
Juan Castillo96103d52016-01-22 11:05:24 +0000223 case EXT_TYPE_NVCOUNTER:
224 /* Counter value must be specified */
225 if ((!ext->optional) && (ext->arg == NULL)) {
226 ERROR("Value for '%s' not specified\n",
227 ext->ln);
228 exit(1);
229 }
230 break;
Juan Castillodfc90e22015-07-08 12:11:38 +0100231 case EXT_TYPE_PKEY:
232 /* Key filename must be specified */
Juan Castillo96103d52016-01-22 11:05:24 +0000233 key = &keys[ext->attr.key];
Juan Castillodfc90e22015-07-08 12:11:38 +0100234 if (!new_keys && key->fn == NULL) {
235 ERROR("Key '%s' required by '%s' not "
236 "specified\n", key->desc,
237 cert->cn);
238 exit(1);
239 }
240 break;
241 case EXT_TYPE_HASH:
Yatharth Kocharcebe1f22015-08-21 15:30:55 +0100242 /*
243 * Binary image must be specified
244 * unless it is explicitly made optional.
245 */
Juan Castillo96103d52016-01-22 11:05:24 +0000246 if ((!ext->optional) && (ext->arg == NULL)) {
Juan Castillodfc90e22015-07-08 12:11:38 +0100247 ERROR("Image for '%s' not specified\n",
248 ext->ln);
249 exit(1);
250 }
251 break;
252 default:
Juan Castillo96103d52016-01-22 11:05:24 +0000253 ERROR("Unknown extension type '%d' in '%s'\n",
254 ext->type, ext->ln);
Juan Castillodfc90e22015-07-08 12:11:38 +0100255 exit(1);
256 break;
257 }
Juan Castillo6f971622014-10-21 11:30:42 +0100258 }
259 }
260}
261
Juan Castillo159807e2015-12-15 16:37:57 +0000262/* Common command line options */
263static const cmd_opt_t common_cmd_opt[] = {
264 {
265 { "help", no_argument, NULL, 'h' },
266 "Print this message and exit"
267 },
268 {
269 { "key-alg", required_argument, NULL, 'a' },
Justin Chadwell6a415a52019-09-09 15:24:31 +0100270 "Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'"
Juan Castillo159807e2015-12-15 16:37:57 +0000271 },
272 {
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100273 { "key-size", required_argument, NULL, 'b' },
274 "Key size (for supported algorithms)."
275 },
276 {
Qixiang Xu29722472017-11-09 13:51:58 +0800277 { "hash-alg", required_argument, NULL, 's' },
278 "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
279 },
280 {
Juan Castillo159807e2015-12-15 16:37:57 +0000281 { "save-keys", no_argument, NULL, 'k' },
282 "Save key pairs into files. Filenames must be provided"
283 },
284 {
285 { "new-keys", no_argument, NULL, 'n' },
286 "Generate new key pairs if no key files are provided"
287 },
288 {
289 { "print-cert", no_argument, NULL, 'p' },
290 "Print the certificates in the standard output"
291 }
292};
293
Juan Castillo6f971622014-10-21 11:30:42 +0100294int main(int argc, char *argv[])
295{
Masahiro Yamadac893c732017-02-06 19:47:44 +0900296 STACK_OF(X509_EXTENSION) * sk;
Michalis Pappas742c4e12017-10-06 16:11:44 +0800297 X509_EXTENSION *cert_ext = NULL;
Masahiro Yamadac893c732017-02-06 19:47:44 +0900298 ext_t *ext;
299 key_t *key;
300 cert_t *cert;
301 FILE *file;
Juan Castillo96103d52016-01-22 11:05:24 +0000302 int i, j, ext_nid, nvctr;
Juan Castillo6f971622014-10-21 11:30:42 +0100303 int c, opt_idx = 0;
Juan Castilload2c1a92015-07-03 16:23:16 +0100304 const struct option *cmd_opt;
305 const char *cur_opt;
Juan Castilloccbf8902015-06-01 16:34:23 +0100306 unsigned int err_code;
Qixiang Xu29722472017-11-09 13:51:58 +0800307 unsigned char md[SHA512_DIGEST_LENGTH];
308 unsigned int md_len;
Juan Castilloc3da66b2015-03-05 14:30:00 +0000309 const EVP_MD *md_info;
Juan Castillo6f971622014-10-21 11:30:42 +0100310
311 NOTICE("CoT Generation Tool: %s\n", build_msg);
312 NOTICE("Target platform: %s\n", platform_msg);
313
Juan Castilloccbf8902015-06-01 16:34:23 +0100314 /* Set default options */
315 key_alg = KEY_ALG_RSA;
Qixiang Xu29722472017-11-09 13:51:58 +0800316 hash_alg = HASH_ALG_SHA256;
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100317 key_size = -1;
Juan Castilloccbf8902015-06-01 16:34:23 +0100318
Juan Castilload2c1a92015-07-03 16:23:16 +0100319 /* Add common command line options */
Juan Castillo159807e2015-12-15 16:37:57 +0000320 for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
321 cmd_opt_add(&common_cmd_opt[i]);
322 }
Juan Castilload2c1a92015-07-03 16:23:16 +0100323
324 /* Initialize the certificates */
325 if (cert_init() != 0) {
326 ERROR("Cannot initialize certificates\n");
327 exit(1);
328 }
329
330 /* Initialize the keys */
331 if (key_init() != 0) {
332 ERROR("Cannot initialize keys\n");
333 exit(1);
334 }
335
336 /* Initialize the new types and register OIDs for the extensions */
337 if (ext_init() != 0) {
Sandrine Bailleux067f7e92020-01-15 11:01:25 +0100338 ERROR("Cannot initialize extensions\n");
Juan Castilload2c1a92015-07-03 16:23:16 +0100339 exit(1);
340 }
341
342 /* Get the command line options populated during the initialization */
343 cmd_opt = cmd_opt_get_array();
344
Juan Castillo6f971622014-10-21 11:30:42 +0100345 while (1) {
346 /* getopt_long stores the option index here. */
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100347 c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
Juan Castillo6f971622014-10-21 11:30:42 +0100348
349 /* Detect the end of the options. */
350 if (c == -1) {
351 break;
352 }
353
354 switch (c) {
Juan Castilloccbf8902015-06-01 16:34:23 +0100355 case 'a':
356 key_alg = get_key_alg(optarg);
357 if (key_alg < 0) {
358 ERROR("Invalid key algorithm '%s'\n", optarg);
359 exit(1);
360 }
361 break;
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100362 case 'b':
363 key_size = get_key_size(optarg);
364 if (key_size <= 0) {
365 ERROR("Invalid key size '%s'\n", optarg);
366 exit(1);
367 }
368 break;
Juan Castillo6f971622014-10-21 11:30:42 +0100369 case 'h':
Juan Castilload2c1a92015-07-03 16:23:16 +0100370 print_help(argv[0], cmd_opt);
Roberto Vargas600835d2018-06-27 08:23:22 +0100371 exit(0);
Juan Castillo6f971622014-10-21 11:30:42 +0100372 case 'k':
373 save_keys = 1;
374 break;
375 case 'n':
376 new_keys = 1;
377 break;
378 case 'p':
379 print_cert = 1;
380 break;
Qixiang Xu29722472017-11-09 13:51:58 +0800381 case 's':
382 hash_alg = get_hash_alg(optarg);
383 if (hash_alg < 0) {
384 ERROR("Invalid hash algorithm '%s'\n", optarg);
385 exit(1);
386 }
387 break;
Juan Castilload2c1a92015-07-03 16:23:16 +0100388 case CMD_OPT_EXT:
389 cur_opt = cmd_opt_get_name(opt_idx);
390 ext = ext_get_by_opt(cur_opt);
Juan Castillo96103d52016-01-22 11:05:24 +0000391 ext->arg = strdup(optarg);
Juan Castillo6f971622014-10-21 11:30:42 +0100392 break;
Juan Castilload2c1a92015-07-03 16:23:16 +0100393 case CMD_OPT_KEY:
394 cur_opt = cmd_opt_get_name(opt_idx);
395 key = key_get_by_opt(cur_opt);
396 key->fn = strdup(optarg);
Juan Castillo6f971622014-10-21 11:30:42 +0100397 break;
Juan Castilload2c1a92015-07-03 16:23:16 +0100398 case CMD_OPT_CERT:
399 cur_opt = cmd_opt_get_name(opt_idx);
400 cert = cert_get_by_opt(cur_opt);
401 cert->fn = strdup(optarg);
Juan Castillo6f971622014-10-21 11:30:42 +0100402 break;
403 case '?':
404 default:
Juan Castillo159807e2015-12-15 16:37:57 +0000405 print_help(argv[0], cmd_opt);
Juan Castillo6f971622014-10-21 11:30:42 +0100406 exit(1);
407 }
408 }
409
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100410 /* Select a reasonable default key-size */
411 if (key_size == -1) {
412 key_size = KEY_SIZES[key_alg][0];
413 }
414
Juan Castillo6f971622014-10-21 11:30:42 +0100415 /* Check command line arguments */
416 check_cmd_params();
417
Qixiang Xu29722472017-11-09 13:51:58 +0800418 /* Indicate SHA as image hash algorithm in the certificate
Juan Castilloc3da66b2015-03-05 14:30:00 +0000419 * extension */
Qixiang Xu29722472017-11-09 13:51:58 +0800420 if (hash_alg == HASH_ALG_SHA384) {
421 md_info = EVP_sha384();
422 md_len = SHA384_DIGEST_LENGTH;
423 } else if (hash_alg == HASH_ALG_SHA512) {
424 md_info = EVP_sha512();
425 md_len = SHA512_DIGEST_LENGTH;
426 } else {
427 md_info = EVP_sha256();
428 md_len = SHA256_DIGEST_LENGTH;
429 }
Juan Castilloc3da66b2015-03-05 14:30:00 +0000430
Juan Castillo6f971622014-10-21 11:30:42 +0100431 /* Load private keys from files (or generate new ones) */
Juan Castillo55e291a2015-06-12 11:27:59 +0100432 for (i = 0 ; i < num_keys ; i++) {
Masahiro Yamada762f1eb2017-02-06 21:15:01 +0900433 if (!key_new(&keys[i])) {
434 ERROR("Failed to allocate key container\n");
435 exit(1);
436 }
437
Juan Castilloccbf8902015-06-01 16:34:23 +0100438 /* First try to load the key from disk */
439 if (key_load(&keys[i], &err_code)) {
440 /* Key loaded successfully */
441 continue;
Juan Castillo6f971622014-10-21 11:30:42 +0100442 }
Juan Castilloccbf8902015-06-01 16:34:23 +0100443
444 /* Key not loaded. Check the error code */
Masahiro Yamada762f1eb2017-02-06 21:15:01 +0900445 if (err_code == KEY_ERR_LOAD) {
Juan Castilloccbf8902015-06-01 16:34:23 +0100446 /* File exists, but it does not contain a valid private
447 * key. Abort. */
448 ERROR("Error loading '%s'\n", keys[i].fn);
449 exit(1);
450 }
451
452 /* File does not exist, could not be opened or no filename was
453 * given */
454 if (new_keys) {
455 /* Try to create a new key */
456 NOTICE("Creating new key for '%s'\n", keys[i].desc);
Justin Chadwelldfe0f4c2019-07-29 17:13:45 +0100457 if (!key_create(&keys[i], key_alg, key_size)) {
Juan Castilloccbf8902015-06-01 16:34:23 +0100458 ERROR("Error creating key '%s'\n", keys[i].desc);
Juan Castillo6f971622014-10-21 11:30:42 +0100459 exit(1);
460 }
Juan Castilloccbf8902015-06-01 16:34:23 +0100461 } else {
462 if (err_code == KEY_ERR_OPEN) {
463 ERROR("Error opening '%s'\n", keys[i].fn);
464 } else {
465 ERROR("Key '%s' not specified\n", keys[i].desc);
466 }
467 exit(1);
Juan Castillo6f971622014-10-21 11:30:42 +0100468 }
469 }
470
Juan Castillo55e291a2015-06-12 11:27:59 +0100471 /* Create the certificates */
472 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo6f971622014-10-21 11:30:42 +0100473
Juan Castillo55e291a2015-06-12 11:27:59 +0100474 cert = &certs[i];
Juan Castillo6f971622014-10-21 11:30:42 +0100475
Juan Castillo55e291a2015-06-12 11:27:59 +0100476 /* Create a new stack of extensions. This stack will be used
477 * to create the certificate */
Juan Castillo6f971622014-10-21 11:30:42 +0100478 CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
Juan Castillo55e291a2015-06-12 11:27:59 +0100479
480 for (j = 0 ; j < cert->num_ext ; j++) {
481
482 ext = &extensions[cert->ext[j]];
483
484 /* Get OpenSSL internal ID for this extension */
485 CHECK_OID(ext_nid, ext->oid);
486
487 /*
488 * Three types of extensions are currently supported:
489 * - EXT_TYPE_NVCOUNTER
490 * - EXT_TYPE_HASH
491 * - EXT_TYPE_PKEY
492 */
493 switch (ext->type) {
494 case EXT_TYPE_NVCOUNTER:
Yatharth Kocharf16db562016-06-22 14:49:27 +0100495 if (ext->arg) {
496 nvctr = atoi(ext->arg);
497 CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
Juan Castillo96103d52016-01-22 11:05:24 +0000498 EXT_CRIT, nvctr));
Yatharth Kocharf16db562016-06-22 14:49:27 +0100499 }
Juan Castillo55e291a2015-06-12 11:27:59 +0100500 break;
501 case EXT_TYPE_HASH:
Juan Castillo96103d52016-01-22 11:05:24 +0000502 if (ext->arg == NULL) {
Yatharth Kocharcebe1f22015-08-21 15:30:55 +0100503 if (ext->optional) {
504 /* Include a hash filled with zeros */
Qixiang Xu29722472017-11-09 13:51:58 +0800505 memset(md, 0x0, SHA512_DIGEST_LENGTH);
Yatharth Kocharcebe1f22015-08-21 15:30:55 +0100506 } else {
507 /* Do not include this hash in the certificate */
508 break;
509 }
510 } else {
511 /* Calculate the hash of the file */
Qixiang Xu29722472017-11-09 13:51:58 +0800512 if (!sha_file(hash_alg, ext->arg, md)) {
Yatharth Kocharcebe1f22015-08-21 15:30:55 +0100513 ERROR("Cannot calculate hash of %s\n",
Juan Castillo96103d52016-01-22 11:05:24 +0000514 ext->arg);
Yatharth Kocharcebe1f22015-08-21 15:30:55 +0100515 exit(1);
516 }
Juan Castillo55e291a2015-06-12 11:27:59 +0100517 }
518 CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
519 EXT_CRIT, md_info, md,
Qixiang Xu29722472017-11-09 13:51:58 +0800520 md_len));
Juan Castillo55e291a2015-06-12 11:27:59 +0100521 break;
522 case EXT_TYPE_PKEY:
523 CHECK_NULL(cert_ext, ext_new_key(ext_nid,
Juan Castillo96103d52016-01-22 11:05:24 +0000524 EXT_CRIT, keys[ext->attr.key].key));
Juan Castillo55e291a2015-06-12 11:27:59 +0100525 break;
526 default:
Juan Castillo96103d52016-01-22 11:05:24 +0000527 ERROR("Unknown extension type '%d' in %s\n",
528 ext->type, cert->cn);
Juan Castillo55e291a2015-06-12 11:27:59 +0100529 exit(1);
530 }
531
532 /* Push the extension into the stack */
533 sk_X509_EXTENSION_push(sk, cert_ext);
Juan Castillo6f971622014-10-21 11:30:42 +0100534 }
Juan Castillo6f971622014-10-21 11:30:42 +0100535
Soby Mathewa8eb2862017-08-31 11:50:29 +0100536 /* Create certificate. Signed with corresponding key */
Justin Chadwell6a415a52019-09-09 15:24:31 +0100537 if (cert->fn && !cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
Juan Castillo55e291a2015-06-12 11:27:59 +0100538 ERROR("Cannot create %s\n", cert->cn);
Juan Castillo6f971622014-10-21 11:30:42 +0100539 exit(1);
540 }
541
Jimmy Brissonbea80192020-07-24 14:31:48 -0500542 for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
543 cert_ext = sk_X509_EXTENSION_pop(sk)) {
544 X509_EXTENSION_free(cert_ext);
545 }
546
Juan Castillo6f971622014-10-21 11:30:42 +0100547 sk_X509_EXTENSION_free(sk);
548 }
549
Juan Castillo6f971622014-10-21 11:30:42 +0100550
551 /* Print the certificates */
552 if (print_cert) {
Juan Castillo55e291a2015-06-12 11:27:59 +0100553 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo6f971622014-10-21 11:30:42 +0100554 if (!certs[i].x) {
555 continue;
556 }
557 printf("\n\n=====================================\n\n");
558 X509_print_fp(stdout, certs[i].x);
559 }
560 }
561
562 /* Save created certificates to files */
Juan Castillo55e291a2015-06-12 11:27:59 +0100563 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo6f971622014-10-21 11:30:42 +0100564 if (certs[i].x && certs[i].fn) {
565 file = fopen(certs[i].fn, "w");
566 if (file != NULL) {
567 i2d_X509_fp(file, certs[i].x);
568 fclose(file);
569 } else {
570 ERROR("Cannot create file %s\n", certs[i].fn);
571 }
572 }
573 }
574
575 /* Save keys */
576 if (save_keys) {
Juan Castillo55e291a2015-06-12 11:27:59 +0100577 for (i = 0 ; i < num_keys ; i++) {
Juan Castillo6f971622014-10-21 11:30:42 +0100578 if (!key_store(&keys[i])) {
579 ERROR("Cannot save %s\n", keys[i].desc);
580 }
581 }
582 }
583
Jimmy Brisson1f111f12020-07-27 10:43:40 -0500584 /* If we got here, then we must have filled the key array completely.
585 * We can then safely call free on all of the keys in the array
586 */
587 for (i = 0; i < num_keys; i++) {
588 EVP_PKEY_free(keys[i].key);
589 }
590
Juan Castillo6f971622014-10-21 11:30:42 +0100591#ifndef OPENSSL_NO_ENGINE
592 ENGINE_cleanup();
593#endif
594 CRYPTO_cleanup_all_ex_data();
595
Jimmy Brisson4a34d182020-07-27 11:23:20 -0500596
597 /* We allocated strings through strdup, so now we have to free them */
598 for (i = 0; i < num_keys; i++) {
599 if (keys[i].fn != NULL) {
600 void *ptr = keys[i].fn;
601
602 keys[i].fn = NULL;
603 free(ptr);
604 }
605 }
606 for (i = 0; i < num_extensions; i++) {
607 if (extensions[i].arg != NULL) {
608 void *ptr = (void *)extensions[i].arg;
609
610 extensions[i].arg = NULL;
611 free(ptr);
612 }
613 }
614 for (i = 0; i < num_certs; i++) {
615 if (certs[i].fn != NULL) {
616 void *ptr = (void *)certs[i].fn;
617
618 certs[i].fn = NULL;
619 free(ptr);
620 }
621 }
622
Juan Castillo6f971622014-10-21 11:30:42 +0100623 return 0;
624}