xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision dfc90e269c07a29648f8ff1cbdb0d9fd8645e7ff)
1 /*
2  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of ARM nor the names of its contributors may be used
15  * to endorse or promote products derived from this software without specific
16  * prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <getopt.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include <openssl/conf.h>
37 #include <openssl/engine.h>
38 #include <openssl/err.h>
39 #include <openssl/pem.h>
40 #include <openssl/sha.h>
41 #include <openssl/x509v3.h>
42 
43 #include "cert.h"
44 #include "debug.h"
45 #include "ext.h"
46 #include "key.h"
47 #include "platform_oid.h"
48 #include "sha.h"
49 #include "tbbr/tbb_ext.h"
50 #include "tbbr/tbb_cert.h"
51 #include "tbbr/tbb_key.h"
52 
53 /*
54  * Helper macros to simplify the code. This macro assigns the return value of
55  * the 'fn' function to 'v' and exits if the value is NULL.
56  */
57 #define CHECK_NULL(v, fn) \
58 	do { \
59 		v = fn; \
60 		if (v == NULL) { \
61 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
62 			exit(1); \
63 		} \
64 	} while (0)
65 
66 /*
67  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
68  * NID is undefined.
69  */
70 #define CHECK_OID(v, oid) \
71 	do { \
72 		v = OBJ_txt2nid(oid); \
73 		if (v == NID_undef) { \
74 			ERROR("Cannot find TBB extension %s\n", oid); \
75 			exit(1); \
76 		} \
77 	} while (0)
78 
79 #define MAX_FILENAME_LEN		1024
80 #define VAL_DAYS			7300
81 #define ID_TO_BIT_MASK(id)		(1 << id)
82 #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
83 
84 /* Files */
85 enum {
86 	/* Image file names (inputs) */
87 	BL2_ID = 0,
88 	BL30_ID,
89 	BL31_ID,
90 	BL32_ID,
91 	BL33_ID,
92 	/* Certificate file names (outputs) */
93 	BL2_CERT_ID,
94 	TRUSTED_KEY_CERT_ID,
95 	BL30_KEY_CERT_ID,
96 	BL30_CERT_ID,
97 	BL31_KEY_CERT_ID,
98 	BL31_CERT_ID,
99 	BL32_KEY_CERT_ID,
100 	BL32_CERT_ID,
101 	BL33_KEY_CERT_ID,
102 	BL33_CERT_ID,
103 	/* Key file names (input/output) */
104 	ROT_KEY_ID,
105 	TRUSTED_WORLD_KEY_ID,
106 	NON_TRUSTED_WORLD_KEY_ID,
107 	BL30_KEY_ID,
108 	BL31_KEY_ID,
109 	BL32_KEY_ID,
110 	BL33_KEY_ID,
111 	NUM_OPTS
112 };
113 
114 /* Global options */
115 static int key_alg;
116 static int new_keys;
117 static int save_keys;
118 static int print_cert;
119 
120 /* Info messages created in the Makefile */
121 extern const char build_msg[];
122 extern const char platform_msg[];
123 
124 
125 static char *strdup(const char *str)
126 {
127 	int n = strlen(str) + 1;
128 	char *dup = malloc(n);
129 	if (dup) {
130 		strcpy(dup, str);
131 	}
132 	return dup;
133 }
134 
135 static const char *key_algs_str[] = {
136 	[KEY_ALG_RSA] = "rsa",
137 #ifndef OPENSSL_NO_EC
138 	[KEY_ALG_ECDSA] = "ecdsa"
139 #endif /* OPENSSL_NO_EC */
140 };
141 
142 /* Command line options */
143 static const struct option long_opt[] = {
144 	/* Binary images */
145 	{"bl2", required_argument, 0, BL2_ID},
146 	{"bl30", required_argument, 0, BL30_ID},
147 	{"bl31", required_argument, 0, BL31_ID},
148 	{"bl32", required_argument, 0, BL32_ID},
149 	{"bl33", required_argument, 0, BL33_ID},
150 	/* Certificate files */
151 	{"bl2-cert", required_argument, 0, BL2_CERT_ID},
152 	{"trusted-key-cert", required_argument, 0, TRUSTED_KEY_CERT_ID},
153 	{"bl30-key-cert", required_argument, 0, BL30_KEY_CERT_ID},
154 	{"bl30-cert", required_argument, 0, BL30_CERT_ID},
155 	{"bl31-key-cert", required_argument, 0, BL31_KEY_CERT_ID},
156 	{"bl31-cert", required_argument, 0, BL31_CERT_ID},
157 	{"bl32-key-cert", required_argument, 0, BL32_KEY_CERT_ID},
158 	{"bl32-cert", required_argument, 0, BL32_CERT_ID},
159 	{"bl33-key-cert", required_argument, 0, BL33_KEY_CERT_ID},
160 	{"bl33-cert", required_argument, 0, BL33_CERT_ID},
161 	/* Private key files */
162 	{"rot-key", required_argument, 0, ROT_KEY_ID},
163 	{"trusted-world-key", required_argument, 0, TRUSTED_WORLD_KEY_ID},
164 	{"non-trusted-world-key", required_argument, 0, NON_TRUSTED_WORLD_KEY_ID},
165 	{"bl30-key", required_argument, 0, BL30_KEY_ID},
166 	{"bl31-key", required_argument, 0, BL31_KEY_ID},
167 	{"bl32-key", required_argument, 0, BL32_KEY_ID},
168 	{"bl33-key", required_argument, 0, BL33_KEY_ID},
169 	/* Common options */
170 	{"key-alg", required_argument, 0, 'a'},
171 	{"help", no_argument, 0, 'h'},
172 	{"save-keys", no_argument, 0, 'k'},
173 	{"new-chain", no_argument, 0, 'n'},
174 	{"print-cert", no_argument, 0, 'p'},
175 	{0, 0, 0, 0}
176 };
177 
178 static void print_help(const char *cmd)
179 {
180 	int i = 0;
181 	printf("\n\n");
182 	printf("The certificate generation tool loads the binary images and\n"
183 	       "optionally the RSA keys, and outputs the key and content\n"
184 	       "certificates properly signed to implement the chain of trust.\n"
185 	       "If keys are provided, they must be in PEM format.\n"
186 	       "Certificates are generated in DER format.\n");
187 	printf("\n");
188 	printf("Usage:\n\n");
189 	printf("    %s [-hknp] \\\n", cmd);
190 	for (i = 0; i < NUM_OPTS; i++) {
191 		printf("        --%s <file>  \\\n", long_opt[i].name);
192 	}
193 	printf("\n");
194 	printf("-a    Key algorithm: rsa (default), ecdsa\n");
195 	printf("-h    Print help and exit\n");
196 	printf("-k    Save key pairs into files. Filenames must be provided\n");
197 	printf("-n    Generate new key pairs if no key files are provided\n");
198 	printf("-p    Print the certificates in the standard output\n");
199 	printf("\n");
200 
201 	exit(0);
202 }
203 
204 static int get_key_alg(const char *key_alg_str)
205 {
206 	int i;
207 
208 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
209 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
210 			return i;
211 		}
212 	}
213 
214 	return -1;
215 }
216 
217 static void check_cmd_params(void)
218 {
219 	cert_t *cert;
220 	ext_t *ext;
221 	key_t *key;
222 	int i, j;
223 
224 	/* Only save new keys */
225 	if (save_keys && !new_keys) {
226 		ERROR("Only new keys can be saved to disk\n");
227 		exit(1);
228 	}
229 
230 	/* Check that all required options have been specified in the
231 	 * command line */
232 	for (i = 0; i < num_certs; i++) {
233 		cert = &certs[i];
234 		if (cert->fn == NULL) {
235 			/* Certificate not requested. Skip to the next one */
236 			continue;
237 		}
238 
239 		/* Check that all parameters required to create this certificate
240 		 * have been specified in the command line */
241 		for (j = 0; j < cert->num_ext; j++) {
242 			ext = &extensions[cert->ext[j]];
243 			switch (ext->type) {
244 			case EXT_TYPE_PKEY:
245 				/* Key filename must be specified */
246 				key = &keys[ext->data.key];
247 				if (!new_keys && key->fn == NULL) {
248 					ERROR("Key '%s' required by '%s' not "
249 					      "specified\n", key->desc,
250 					      cert->cn);
251 					exit(1);
252 				}
253 				break;
254 			case EXT_TYPE_HASH:
255 				/* Binary image must be specified */
256 				if (ext->data.fn == NULL) {
257 					ERROR("Image for '%s' not specified\n",
258 					      ext->ln);
259 					exit(1);
260 				}
261 				break;
262 			default:
263 				ERROR("Unknown extension type in '%s'\n",
264 				      ext->ln);
265 				exit(1);
266 				break;
267 			}
268 		}
269 	}
270 }
271 
272 int main(int argc, char *argv[])
273 {
274 	STACK_OF(X509_EXTENSION) * sk = NULL;
275 	X509_EXTENSION *cert_ext = NULL;
276 	ext_t *ext = NULL;
277 	cert_t *cert;
278 	FILE *file = NULL;
279 	int i, j, ext_nid;
280 	int c, opt_idx = 0;
281 	unsigned int err_code;
282 	unsigned char md[SHA256_DIGEST_LENGTH];
283 	const EVP_MD *md_info;
284 
285 	NOTICE("CoT Generation Tool: %s\n", build_msg);
286 	NOTICE("Target platform: %s\n", platform_msg);
287 
288 	/* Set default options */
289 	key_alg = KEY_ALG_RSA;
290 
291 	while (1) {
292 		/* getopt_long stores the option index here. */
293 		c = getopt_long(argc, argv, "ahknp", long_opt, &opt_idx);
294 
295 		/* Detect the end of the options. */
296 		if (c == -1) {
297 			break;
298 		}
299 
300 		switch (c) {
301 		case 'a':
302 			key_alg = get_key_alg(optarg);
303 			if (key_alg < 0) {
304 				ERROR("Invalid key algorithm '%s'\n", optarg);
305 				exit(1);
306 			}
307 			break;
308 		case 'h':
309 			print_help(argv[0]);
310 			break;
311 		case 'k':
312 			save_keys = 1;
313 			break;
314 		case 'n':
315 			new_keys = 1;
316 			break;
317 		case 'p':
318 			print_cert = 1;
319 			break;
320 		case BL2_ID:
321 			extensions[BL2_HASH_EXT].data.fn = strdup(optarg);
322 			break;
323 		case BL30_ID:
324 			extensions[BL30_HASH_EXT].data.fn = strdup(optarg);
325 			break;
326 		case BL31_ID:
327 			extensions[BL31_HASH_EXT].data.fn = strdup(optarg);
328 			break;
329 		case BL32_ID:
330 			extensions[BL32_HASH_EXT].data.fn = strdup(optarg);
331 			break;
332 		case BL33_ID:
333 			extensions[BL33_HASH_EXT].data.fn = strdup(optarg);
334 			break;
335 		case BL2_CERT_ID:
336 			certs[BL2_CERT].fn = strdup(optarg);
337 			break;
338 		case TRUSTED_KEY_CERT_ID:
339 			certs[TRUSTED_KEY_CERT].fn = strdup(optarg);
340 			break;
341 		case BL30_KEY_CERT_ID:
342 			certs[BL30_KEY_CERT].fn = strdup(optarg);
343 			break;
344 		case BL30_CERT_ID:
345 			certs[BL30_CERT].fn = strdup(optarg);
346 			break;
347 		case BL31_KEY_CERT_ID:
348 			certs[BL31_KEY_CERT].fn = strdup(optarg);
349 			break;
350 		case BL31_CERT_ID:
351 			certs[BL31_CERT].fn = strdup(optarg);
352 			break;
353 		case BL32_KEY_CERT_ID:
354 			certs[BL32_KEY_CERT].fn = strdup(optarg);
355 			break;
356 		case BL32_CERT_ID:
357 			certs[BL32_CERT].fn = strdup(optarg);
358 			break;
359 		case BL33_KEY_CERT_ID:
360 			certs[BL33_KEY_CERT].fn = strdup(optarg);
361 			break;
362 		case BL33_CERT_ID:
363 			certs[BL33_CERT].fn = strdup(optarg);
364 			break;
365 		case ROT_KEY_ID:
366 			keys[ROT_KEY].fn = strdup(optarg);
367 			break;
368 		case TRUSTED_WORLD_KEY_ID:
369 			keys[TRUSTED_WORLD_KEY].fn = strdup(optarg);
370 			break;
371 		case NON_TRUSTED_WORLD_KEY_ID:
372 			keys[NON_TRUSTED_WORLD_KEY].fn = strdup(optarg);
373 			break;
374 		case BL30_KEY_ID:
375 			keys[BL30_KEY].fn = strdup(optarg);
376 			break;
377 		case BL31_KEY_ID:
378 			keys[BL31_KEY].fn = strdup(optarg);
379 			break;
380 		case BL32_KEY_ID:
381 			keys[BL32_KEY].fn = strdup(optarg);
382 			break;
383 		case BL33_KEY_ID:
384 			keys[BL33_KEY].fn = strdup(optarg);
385 			break;
386 		case '?':
387 		default:
388 			printf("%s\n", optarg);
389 			exit(1);
390 		}
391 	}
392 
393 	/* Check command line arguments */
394 	check_cmd_params();
395 
396 	/* Register the new types and OIDs for the extensions */
397 	if (ext_register(extensions) != 0) {
398 		ERROR("Cannot register TBB extensions\n");
399 		exit(1);
400 	}
401 
402 	/* Indicate SHA256 as image hash algorithm in the certificate
403 	 * extension */
404 	md_info = EVP_sha256();
405 
406 	/* Load private keys from files (or generate new ones) */
407 	for (i = 0 ; i < num_keys ; i++) {
408 		/* First try to load the key from disk */
409 		if (key_load(&keys[i], &err_code)) {
410 			/* Key loaded successfully */
411 			continue;
412 		}
413 
414 		/* Key not loaded. Check the error code */
415 		if (err_code == KEY_ERR_MALLOC) {
416 			/* Cannot allocate memory. Abort. */
417 			ERROR("Malloc error while loading '%s'\n", keys[i].fn);
418 			exit(1);
419 		} else if (err_code == KEY_ERR_LOAD) {
420 			/* File exists, but it does not contain a valid private
421 			 * key. Abort. */
422 			ERROR("Error loading '%s'\n", keys[i].fn);
423 			exit(1);
424 		}
425 
426 		/* File does not exist, could not be opened or no filename was
427 		 * given */
428 		if (new_keys) {
429 			/* Try to create a new key */
430 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
431 			if (!key_create(&keys[i], key_alg)) {
432 				ERROR("Error creating key '%s'\n", keys[i].desc);
433 				exit(1);
434 			}
435 		} else {
436 			if (err_code == KEY_ERR_OPEN) {
437 				ERROR("Error opening '%s'\n", keys[i].fn);
438 			} else {
439 				ERROR("Key '%s' not specified\n", keys[i].desc);
440 			}
441 			exit(1);
442 		}
443 	}
444 
445 	/* Create the certificates */
446 	for (i = 0 ; i < num_certs ; i++) {
447 
448 		cert = &certs[i];
449 
450 		/* Create a new stack of extensions. This stack will be used
451 		 * to create the certificate */
452 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
453 
454 		for (j = 0 ; j < cert->num_ext ; j++) {
455 
456 			ext = &extensions[cert->ext[j]];
457 
458 			/* Get OpenSSL internal ID for this extension */
459 			CHECK_OID(ext_nid, ext->oid);
460 
461 			/*
462 			 * Three types of extensions are currently supported:
463 			 *     - EXT_TYPE_NVCOUNTER
464 			 *     - EXT_TYPE_HASH
465 			 *     - EXT_TYPE_PKEY
466 			 */
467 			switch (ext->type) {
468 			case EXT_TYPE_NVCOUNTER:
469 				CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
470 						EXT_CRIT, ext->data.nvcounter));
471 				break;
472 			case EXT_TYPE_HASH:
473 				if (ext->data.fn == NULL) {
474 					break;
475 				}
476 				if (!sha_file(ext->data.fn, md)) {
477 					ERROR("Cannot calculate hash of %s\n",
478 						ext->data.fn);
479 					exit(1);
480 				}
481 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
482 						EXT_CRIT, md_info, md,
483 						SHA256_DIGEST_LENGTH));
484 				break;
485 			case EXT_TYPE_PKEY:
486 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
487 					EXT_CRIT, keys[ext->data.key].key));
488 				break;
489 			default:
490 				ERROR("Unknown extension type in %s\n",
491 						cert->cn);
492 				exit(1);
493 			}
494 
495 			/* Push the extension into the stack */
496 			sk_X509_EXTENSION_push(sk, cert_ext);
497 		}
498 
499 		/* Create certificate. Signed with ROT key */
500 		if (cert->fn && !cert_new(cert, VAL_DAYS, 0, sk)) {
501 			ERROR("Cannot create %s\n", cert->cn);
502 			exit(1);
503 		}
504 
505 		sk_X509_EXTENSION_free(sk);
506 	}
507 
508 
509 	/* Print the certificates */
510 	if (print_cert) {
511 		for (i = 0 ; i < num_certs ; i++) {
512 			if (!certs[i].x) {
513 				continue;
514 			}
515 			printf("\n\n=====================================\n\n");
516 			X509_print_fp(stdout, certs[i].x);
517 		}
518 	}
519 
520 	/* Save created certificates to files */
521 	for (i = 0 ; i < num_certs ; i++) {
522 		if (certs[i].x && certs[i].fn) {
523 			file = fopen(certs[i].fn, "w");
524 			if (file != NULL) {
525 				i2d_X509_fp(file, certs[i].x);
526 				fclose(file);
527 			} else {
528 				ERROR("Cannot create file %s\n", certs[i].fn);
529 			}
530 		}
531 	}
532 
533 	/* Save keys */
534 	if (save_keys) {
535 		for (i = 0 ; i < num_keys ; i++) {
536 			if (!key_store(&keys[i])) {
537 				ERROR("Cannot save %s\n", keys[i].desc);
538 			}
539 		}
540 	}
541 
542 #ifndef OPENSSL_NO_ENGINE
543 	ENGINE_cleanup();
544 #endif
545 	CRYPTO_cleanup_all_ex_data();
546 
547 	return 0;
548 }
549