blob: 44a65eb982e1745725b00a695f13abb929064b9a [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
Justin Chadwellfa3ec4c2019-08-12 12:19:21 +01002 * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
Juan Castillo11abdcd2014-10-21 11:30:42 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Juan Castillo11abdcd2014-10-21 11:30:42 +01005 */
6
Juan Castillo212f7382015-12-15 16:37:57 +00007#include <assert.h>
8#include <ctype.h>
Juan Castillo11abdcd2014-10-21 11:30:42 +01009#include <getopt.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
Justin Chadwellfebe86c2019-07-29 17:13:45 +010013#include <stdbool.h>
Juan Castillo11abdcd2014-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
Masahiro Yamadaa27c1662017-05-22 12:11:24 +090022#if USE_TBBR_DEFS
23#include <tbbr_oid.h>
24#else
25#include <platform_oid.h>
26#endif
27
Juan Castillo11abdcd2014-10-21 11:30:42 +010028#include "cert.h"
Juan Castillo1218dd52015-07-03 16:23:16 +010029#include "cmd_opt.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010030#include "debug.h"
31#include "ext.h"
32#include "key.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010033#include "sha.h"
Juan Castilloe6d30e92015-06-12 11:27:59 +010034#include "tbbr/tbb_cert.h"
Isla Mitchell99305012017-07-11 14:54:08 +010035#include "tbbr/tbb_ext.h"
Juan Castilloe6d30e92015-06-12 11:27:59 +010036#include "tbbr/tbb_key.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010037
38/*
39 * Helper macros to simplify the code. This macro assigns the return value of
40 * the 'fn' function to 'v' and exits if the value is NULL.
41 */
42#define CHECK_NULL(v, fn) \
43 do { \
44 v = fn; \
45 if (v == NULL) { \
46 ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
47 exit(1); \
48 } \
49 } while (0)
50
51/*
52 * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
53 * NID is undefined.
54 */
55#define CHECK_OID(v, oid) \
56 do { \
57 v = OBJ_txt2nid(oid); \
58 if (v == NID_undef) { \
59 ERROR("Cannot find TBB extension %s\n", oid); \
60 exit(1); \
61 } \
62 } while (0)
63
64#define MAX_FILENAME_LEN 1024
65#define VAL_DAYS 7300
66#define ID_TO_BIT_MASK(id) (1 << id)
Juan Castillof9f39c32015-06-01 16:34:23 +010067#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0])))
Juan Castillo212f7382015-12-15 16:37:57 +000068#define HELP_OPT_MAX_LEN 128
Juan Castillo11abdcd2014-10-21 11:30:42 +010069
70/* Global options */
Juan Castillof9f39c32015-06-01 16:34:23 +010071static int key_alg;
Qixiang Xu76a5a9b2017-11-09 13:51:58 +080072static int hash_alg;
Justin Chadwellfebe86c2019-07-29 17:13:45 +010073static int key_size;
Juan Castillo11abdcd2014-10-21 11:30:42 +010074static int new_keys;
75static int save_keys;
76static int print_cert;
Juan Castillo11abdcd2014-10-21 11:30:42 +010077
Juan Castillo11abdcd2014-10-21 11:30:42 +010078/* Info messages created in the Makefile */
79extern const char build_msg[];
80extern const char platform_msg[];
81
82
83static char *strdup(const char *str)
84{
85 int n = strlen(str) + 1;
86 char *dup = malloc(n);
87 if (dup) {
88 strcpy(dup, str);
89 }
90 return dup;
91}
92
Juan Castillof9f39c32015-06-01 16:34:23 +010093static const char *key_algs_str[] = {
94 [KEY_ALG_RSA] = "rsa",
Soby Mathew2fd70f62017-08-31 11:50:29 +010095 [KEY_ALG_RSA_1_5] = "rsa_1_5",
Juan Castilloa2224ab2015-06-30 13:36:57 +010096#ifndef OPENSSL_NO_EC
Juan Castillof9f39c32015-06-01 16:34:23 +010097 [KEY_ALG_ECDSA] = "ecdsa"
Juan Castilloa2224ab2015-06-30 13:36:57 +010098#endif /* OPENSSL_NO_EC */
Juan Castillof9f39c32015-06-01 16:34:23 +010099};
100
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800101static const char *hash_algs_str[] = {
102 [HASH_ALG_SHA256] = "sha256",
103 [HASH_ALG_SHA384] = "sha384",
104 [HASH_ALG_SHA512] = "sha512",
105};
106
Juan Castillo1218dd52015-07-03 16:23:16 +0100107static void print_help(const char *cmd, const struct option *long_opt)
Juan Castillo11abdcd2014-10-21 11:30:42 +0100108{
Juan Castillo212f7382015-12-15 16:37:57 +0000109 int rem, i = 0;
110 const struct option *opt;
111 char line[HELP_OPT_MAX_LEN];
112 char *p;
113
114 assert(cmd != NULL);
115 assert(long_opt != NULL);
116
Juan Castillo11abdcd2014-10-21 11:30:42 +0100117 printf("\n\n");
118 printf("The certificate generation tool loads the binary images and\n"
119 "optionally the RSA keys, and outputs the key and content\n"
120 "certificates properly signed to implement the chain of trust.\n"
121 "If keys are provided, they must be in PEM format.\n"
122 "Certificates are generated in DER format.\n");
123 printf("\n");
Juan Castillo212f7382015-12-15 16:37:57 +0000124 printf("Usage:\n");
125 printf("\t%s [OPTIONS]\n\n", cmd);
126
127 printf("Available options:\n");
Juan Castillo212f7382015-12-15 16:37:57 +0000128 opt = long_opt;
129 while (opt->name) {
130 p = line;
131 rem = HELP_OPT_MAX_LEN;
132 if (isalpha(opt->val)) {
133 /* Short format */
134 sprintf(p, "-%c,", (char)opt->val);
135 p += 3;
136 rem -= 3;
137 }
138 snprintf(p, rem, "--%s %s", opt->name,
139 (opt->has_arg == required_argument) ? "<arg>" : "");
140 printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
141 opt++;
142 i++;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100143 }
144 printf("\n");
Juan Castillo11abdcd2014-10-21 11:30:42 +0100145}
146
Juan Castillof9f39c32015-06-01 16:34:23 +0100147static int get_key_alg(const char *key_alg_str)
148{
149 int i;
150
151 for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
152 if (0 == strcmp(key_alg_str, key_algs_str[i])) {
153 return i;
154 }
155 }
156
157 return -1;
158}
159
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100160static int get_key_size(const char *key_size_str)
161{
162 char *end;
163 long key_size;
164
165 key_size = strtol(key_size_str, &end, 10);
166 if (*end != '\0')
167 return -1;
168
169 return key_size;
170}
171
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800172static int get_hash_alg(const char *hash_alg_str)
173{
174 int i;
175
176 for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
177 if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
178 return i;
179 }
180 }
181
182 return -1;
183}
184
Juan Castillo11abdcd2014-10-21 11:30:42 +0100185static void check_cmd_params(void)
186{
Juan Castillo86958fd2015-07-08 12:11:38 +0100187 cert_t *cert;
188 ext_t *ext;
189 key_t *key;
190 int i, j;
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100191 bool valid_size;
Juan Castillo86958fd2015-07-08 12:11:38 +0100192
Juan Castillof9f39c32015-06-01 16:34:23 +0100193 /* Only save new keys */
194 if (save_keys && !new_keys) {
195 ERROR("Only new keys can be saved to disk\n");
196 exit(1);
197 }
198
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100199 /* Validate key-size */
200 valid_size = false;
201 for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
202 if (key_size == KEY_SIZES[key_alg][i]) {
203 valid_size = true;
204 break;
205 }
206 }
207 if (!valid_size) {
208 ERROR("'%d' is not a valid key size for '%s'\n",
209 key_size, key_algs_str[key_alg]);
210 NOTICE("Valid sizes are: ");
211 for (i = 0; i < KEY_SIZE_MAX_NUM &&
212 KEY_SIZES[key_alg][i] != 0; i++) {
213 printf("%d ", KEY_SIZES[key_alg][i]);
214 }
215 printf("\n");
216 exit(1);
217 }
218
Juan Castillo86958fd2015-07-08 12:11:38 +0100219 /* Check that all required options have been specified in the
220 * command line */
221 for (i = 0; i < num_certs; i++) {
222 cert = &certs[i];
223 if (cert->fn == NULL) {
224 /* Certificate not requested. Skip to the next one */
225 continue;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100226 }
227
Juan Castillo86958fd2015-07-08 12:11:38 +0100228 /* Check that all parameters required to create this certificate
229 * have been specified in the command line */
230 for (j = 0; j < cert->num_ext; j++) {
231 ext = &extensions[cert->ext[j]];
232 switch (ext->type) {
Juan Castillo43529982016-01-22 11:05:24 +0000233 case EXT_TYPE_NVCOUNTER:
234 /* Counter value must be specified */
235 if ((!ext->optional) && (ext->arg == NULL)) {
236 ERROR("Value for '%s' not specified\n",
237 ext->ln);
238 exit(1);
239 }
240 break;
Juan Castillo86958fd2015-07-08 12:11:38 +0100241 case EXT_TYPE_PKEY:
242 /* Key filename must be specified */
Juan Castillo43529982016-01-22 11:05:24 +0000243 key = &keys[ext->attr.key];
Juan Castillo86958fd2015-07-08 12:11:38 +0100244 if (!new_keys && key->fn == NULL) {
245 ERROR("Key '%s' required by '%s' not "
246 "specified\n", key->desc,
247 cert->cn);
248 exit(1);
249 }
250 break;
251 case EXT_TYPE_HASH:
Yatharth Kochar5752b592015-08-21 15:30:55 +0100252 /*
253 * Binary image must be specified
254 * unless it is explicitly made optional.
255 */
Juan Castillo43529982016-01-22 11:05:24 +0000256 if ((!ext->optional) && (ext->arg == NULL)) {
Juan Castillo86958fd2015-07-08 12:11:38 +0100257 ERROR("Image for '%s' not specified\n",
258 ext->ln);
259 exit(1);
260 }
261 break;
262 default:
Juan Castillo43529982016-01-22 11:05:24 +0000263 ERROR("Unknown extension type '%d' in '%s'\n",
264 ext->type, ext->ln);
Juan Castillo86958fd2015-07-08 12:11:38 +0100265 exit(1);
266 break;
267 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100268 }
269 }
270}
271
Juan Castillo212f7382015-12-15 16:37:57 +0000272/* Common command line options */
273static const cmd_opt_t common_cmd_opt[] = {
274 {
275 { "help", no_argument, NULL, 'h' },
276 "Print this message and exit"
277 },
278 {
279 { "key-alg", required_argument, NULL, 'a' },
Soby Mathew2fd70f62017-08-31 11:50:29 +0100280 "Key algorithm: 'rsa' (default) - RSAPSS scheme as per \
281PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'"
Juan Castillo212f7382015-12-15 16:37:57 +0000282 },
283 {
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100284 { "key-size", required_argument, NULL, 'b' },
285 "Key size (for supported algorithms)."
286 },
287 {
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800288 { "hash-alg", required_argument, NULL, 's' },
289 "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
290 },
291 {
Juan Castillo212f7382015-12-15 16:37:57 +0000292 { "save-keys", no_argument, NULL, 'k' },
293 "Save key pairs into files. Filenames must be provided"
294 },
295 {
296 { "new-keys", no_argument, NULL, 'n' },
297 "Generate new key pairs if no key files are provided"
298 },
299 {
300 { "print-cert", no_argument, NULL, 'p' },
301 "Print the certificates in the standard output"
302 }
303};
304
Juan Castillo11abdcd2014-10-21 11:30:42 +0100305int main(int argc, char *argv[])
306{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900307 STACK_OF(X509_EXTENSION) * sk;
Michalis Pappas38628942017-10-06 16:11:44 +0800308 X509_EXTENSION *cert_ext = NULL;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900309 ext_t *ext;
310 key_t *key;
311 cert_t *cert;
312 FILE *file;
Juan Castillo43529982016-01-22 11:05:24 +0000313 int i, j, ext_nid, nvctr;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100314 int c, opt_idx = 0;
Juan Castillo1218dd52015-07-03 16:23:16 +0100315 const struct option *cmd_opt;
316 const char *cur_opt;
Juan Castillof9f39c32015-06-01 16:34:23 +0100317 unsigned int err_code;
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800318 unsigned char md[SHA512_DIGEST_LENGTH];
319 unsigned int md_len;
Juan Castilloac402932015-03-05 14:30:00 +0000320 const EVP_MD *md_info;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100321
322 NOTICE("CoT Generation Tool: %s\n", build_msg);
323 NOTICE("Target platform: %s\n", platform_msg);
324
Juan Castillof9f39c32015-06-01 16:34:23 +0100325 /* Set default options */
326 key_alg = KEY_ALG_RSA;
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800327 hash_alg = HASH_ALG_SHA256;
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100328 key_size = -1;
Juan Castillof9f39c32015-06-01 16:34:23 +0100329
Juan Castillo1218dd52015-07-03 16:23:16 +0100330 /* Add common command line options */
Juan Castillo212f7382015-12-15 16:37:57 +0000331 for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
332 cmd_opt_add(&common_cmd_opt[i]);
333 }
Juan Castillo1218dd52015-07-03 16:23:16 +0100334
335 /* Initialize the certificates */
336 if (cert_init() != 0) {
337 ERROR("Cannot initialize certificates\n");
338 exit(1);
339 }
340
341 /* Initialize the keys */
342 if (key_init() != 0) {
343 ERROR("Cannot initialize keys\n");
344 exit(1);
345 }
346
347 /* Initialize the new types and register OIDs for the extensions */
348 if (ext_init() != 0) {
349 ERROR("Cannot initialize TBB extensions\n");
350 exit(1);
351 }
352
353 /* Get the command line options populated during the initialization */
354 cmd_opt = cmd_opt_get_array();
355
Juan Castillo11abdcd2014-10-21 11:30:42 +0100356 while (1) {
357 /* getopt_long stores the option index here. */
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100358 c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100359
360 /* Detect the end of the options. */
361 if (c == -1) {
362 break;
363 }
364
365 switch (c) {
Juan Castillof9f39c32015-06-01 16:34:23 +0100366 case 'a':
367 key_alg = get_key_alg(optarg);
368 if (key_alg < 0) {
369 ERROR("Invalid key algorithm '%s'\n", optarg);
370 exit(1);
371 }
372 break;
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100373 case 'b':
374 key_size = get_key_size(optarg);
375 if (key_size <= 0) {
376 ERROR("Invalid key size '%s'\n", optarg);
377 exit(1);
378 }
379 break;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100380 case 'h':
Juan Castillo1218dd52015-07-03 16:23:16 +0100381 print_help(argv[0], cmd_opt);
Roberto Vargas58a5b2b2018-06-27 08:23:22 +0100382 exit(0);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100383 case 'k':
384 save_keys = 1;
385 break;
386 case 'n':
387 new_keys = 1;
388 break;
389 case 'p':
390 print_cert = 1;
391 break;
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800392 case 's':
393 hash_alg = get_hash_alg(optarg);
394 if (hash_alg < 0) {
395 ERROR("Invalid hash algorithm '%s'\n", optarg);
396 exit(1);
397 }
398 break;
Juan Castillo1218dd52015-07-03 16:23:16 +0100399 case CMD_OPT_EXT:
400 cur_opt = cmd_opt_get_name(opt_idx);
401 ext = ext_get_by_opt(cur_opt);
Juan Castillo43529982016-01-22 11:05:24 +0000402 ext->arg = strdup(optarg);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100403 break;
Juan Castillo1218dd52015-07-03 16:23:16 +0100404 case CMD_OPT_KEY:
405 cur_opt = cmd_opt_get_name(opt_idx);
406 key = key_get_by_opt(cur_opt);
407 key->fn = strdup(optarg);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100408 break;
Juan Castillo1218dd52015-07-03 16:23:16 +0100409 case CMD_OPT_CERT:
410 cur_opt = cmd_opt_get_name(opt_idx);
411 cert = cert_get_by_opt(cur_opt);
412 cert->fn = strdup(optarg);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100413 break;
414 case '?':
415 default:
Juan Castillo212f7382015-12-15 16:37:57 +0000416 print_help(argv[0], cmd_opt);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100417 exit(1);
418 }
419 }
420
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100421 /* Select a reasonable default key-size */
422 if (key_size == -1) {
423 key_size = KEY_SIZES[key_alg][0];
424 }
425
Juan Castillo11abdcd2014-10-21 11:30:42 +0100426 /* Check command line arguments */
427 check_cmd_params();
428
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800429 /* Indicate SHA as image hash algorithm in the certificate
Juan Castilloac402932015-03-05 14:30:00 +0000430 * extension */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800431 if (hash_alg == HASH_ALG_SHA384) {
432 md_info = EVP_sha384();
433 md_len = SHA384_DIGEST_LENGTH;
434 } else if (hash_alg == HASH_ALG_SHA512) {
435 md_info = EVP_sha512();
436 md_len = SHA512_DIGEST_LENGTH;
437 } else {
438 md_info = EVP_sha256();
439 md_len = SHA256_DIGEST_LENGTH;
440 }
Juan Castilloac402932015-03-05 14:30:00 +0000441
Juan Castillo11abdcd2014-10-21 11:30:42 +0100442 /* Load private keys from files (or generate new ones) */
Juan Castilloe6d30e92015-06-12 11:27:59 +0100443 for (i = 0 ; i < num_keys ; i++) {
Masahiro Yamadabccb1092017-02-06 21:15:01 +0900444 if (!key_new(&keys[i])) {
445 ERROR("Failed to allocate key container\n");
446 exit(1);
447 }
448
Juan Castillof9f39c32015-06-01 16:34:23 +0100449 /* First try to load the key from disk */
450 if (key_load(&keys[i], &err_code)) {
451 /* Key loaded successfully */
452 continue;
453 }
454
455 /* Key not loaded. Check the error code */
Masahiro Yamadabccb1092017-02-06 21:15:01 +0900456 if (err_code == KEY_ERR_LOAD) {
Juan Castillof9f39c32015-06-01 16:34:23 +0100457 /* File exists, but it does not contain a valid private
458 * key. Abort. */
459 ERROR("Error loading '%s'\n", keys[i].fn);
460 exit(1);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100461 }
Juan Castillof9f39c32015-06-01 16:34:23 +0100462
463 /* File does not exist, could not be opened or no filename was
464 * given */
465 if (new_keys) {
466 /* Try to create a new key */
467 NOTICE("Creating new key for '%s'\n", keys[i].desc);
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100468 if (!key_create(&keys[i], key_alg, key_size)) {
Juan Castillof9f39c32015-06-01 16:34:23 +0100469 ERROR("Error creating key '%s'\n", keys[i].desc);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100470 exit(1);
471 }
Juan Castillof9f39c32015-06-01 16:34:23 +0100472 } else {
473 if (err_code == KEY_ERR_OPEN) {
474 ERROR("Error opening '%s'\n", keys[i].fn);
475 } else {
476 ERROR("Key '%s' not specified\n", keys[i].desc);
477 }
478 exit(1);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100479 }
480 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100481
Juan Castilloe6d30e92015-06-12 11:27:59 +0100482 /* Create the certificates */
483 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100484
Juan Castilloe6d30e92015-06-12 11:27:59 +0100485 cert = &certs[i];
Juan Castillo11abdcd2014-10-21 11:30:42 +0100486
Juan Castilloe6d30e92015-06-12 11:27:59 +0100487 /* Create a new stack of extensions. This stack will be used
488 * to create the certificate */
Juan Castillo11abdcd2014-10-21 11:30:42 +0100489 CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
Juan Castillo11abdcd2014-10-21 11:30:42 +0100490
Juan Castilloe6d30e92015-06-12 11:27:59 +0100491 for (j = 0 ; j < cert->num_ext ; j++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100492
Juan Castilloe6d30e92015-06-12 11:27:59 +0100493 ext = &extensions[cert->ext[j]];
Juan Castillo11abdcd2014-10-21 11:30:42 +0100494
Juan Castilloe6d30e92015-06-12 11:27:59 +0100495 /* Get OpenSSL internal ID for this extension */
496 CHECK_OID(ext_nid, ext->oid);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100497
Juan Castilloe6d30e92015-06-12 11:27:59 +0100498 /*
499 * Three types of extensions are currently supported:
500 * - EXT_TYPE_NVCOUNTER
501 * - EXT_TYPE_HASH
502 * - EXT_TYPE_PKEY
503 */
504 switch (ext->type) {
505 case EXT_TYPE_NVCOUNTER:
Yatharth Kochar79f86402016-06-22 14:49:27 +0100506 if (ext->arg) {
507 nvctr = atoi(ext->arg);
508 CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
Juan Castillo43529982016-01-22 11:05:24 +0000509 EXT_CRIT, nvctr));
Yatharth Kochar79f86402016-06-22 14:49:27 +0100510 }
Juan Castilloe6d30e92015-06-12 11:27:59 +0100511 break;
512 case EXT_TYPE_HASH:
Juan Castillo43529982016-01-22 11:05:24 +0000513 if (ext->arg == NULL) {
Yatharth Kochar5752b592015-08-21 15:30:55 +0100514 if (ext->optional) {
515 /* Include a hash filled with zeros */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800516 memset(md, 0x0, SHA512_DIGEST_LENGTH);
Yatharth Kochar5752b592015-08-21 15:30:55 +0100517 } else {
518 /* Do not include this hash in the certificate */
519 break;
520 }
521 } else {
522 /* Calculate the hash of the file */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800523 if (!sha_file(hash_alg, ext->arg, md)) {
Yatharth Kochar5752b592015-08-21 15:30:55 +0100524 ERROR("Cannot calculate hash of %s\n",
Juan Castillo43529982016-01-22 11:05:24 +0000525 ext->arg);
Yatharth Kochar5752b592015-08-21 15:30:55 +0100526 exit(1);
527 }
Juan Castilloe6d30e92015-06-12 11:27:59 +0100528 }
529 CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
530 EXT_CRIT, md_info, md,
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800531 md_len));
Juan Castilloe6d30e92015-06-12 11:27:59 +0100532 break;
533 case EXT_TYPE_PKEY:
534 CHECK_NULL(cert_ext, ext_new_key(ext_nid,
Juan Castillo43529982016-01-22 11:05:24 +0000535 EXT_CRIT, keys[ext->attr.key].key));
Juan Castilloe6d30e92015-06-12 11:27:59 +0100536 break;
537 default:
Juan Castillo43529982016-01-22 11:05:24 +0000538 ERROR("Unknown extension type '%d' in %s\n",
539 ext->type, cert->cn);
Juan Castilloe6d30e92015-06-12 11:27:59 +0100540 exit(1);
541 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100542
Juan Castilloe6d30e92015-06-12 11:27:59 +0100543 /* Push the extension into the stack */
544 sk_X509_EXTENSION_push(sk, cert_ext);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100545 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100546
Soby Mathew2fd70f62017-08-31 11:50:29 +0100547 /* Create certificate. Signed with corresponding key */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800548 if (cert->fn && !cert_new(key_alg, hash_alg, cert, VAL_DAYS, 0, sk)) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100549 ERROR("Cannot create %s\n", cert->cn);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100550 exit(1);
551 }
552
553 sk_X509_EXTENSION_free(sk);
554 }
555
Juan Castillo11abdcd2014-10-21 11:30:42 +0100556
557 /* Print the certificates */
558 if (print_cert) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100559 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100560 if (!certs[i].x) {
561 continue;
562 }
563 printf("\n\n=====================================\n\n");
564 X509_print_fp(stdout, certs[i].x);
565 }
566 }
567
568 /* Save created certificates to files */
Juan Castilloe6d30e92015-06-12 11:27:59 +0100569 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100570 if (certs[i].x && certs[i].fn) {
571 file = fopen(certs[i].fn, "w");
572 if (file != NULL) {
573 i2d_X509_fp(file, certs[i].x);
574 fclose(file);
575 } else {
576 ERROR("Cannot create file %s\n", certs[i].fn);
577 }
578 }
579 }
580
581 /* Save keys */
582 if (save_keys) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100583 for (i = 0 ; i < num_keys ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100584 if (!key_store(&keys[i])) {
585 ERROR("Cannot save %s\n", keys[i].desc);
586 }
587 }
588 }
589
Juan Castillo11abdcd2014-10-21 11:30:42 +0100590#ifndef OPENSSL_NO_ENGINE
591 ENGINE_cleanup();
592#endif
593 CRYPTO_cleanup_all_ex_data();
594
595 return 0;
596}