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 "cmd_opt.h" 45 #include "debug.h" 46 #include "ext.h" 47 #include "key.h" 48 #include "platform_oid.h" 49 #include "sha.h" 50 #include "tbbr/tbb_ext.h" 51 #include "tbbr/tbb_cert.h" 52 #include "tbbr/tbb_key.h" 53 54 /* 55 * Helper macros to simplify the code. This macro assigns the return value of 56 * the 'fn' function to 'v' and exits if the value is NULL. 57 */ 58 #define CHECK_NULL(v, fn) \ 59 do { \ 60 v = fn; \ 61 if (v == NULL) { \ 62 ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ 63 exit(1); \ 64 } \ 65 } while (0) 66 67 /* 68 * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the 69 * NID is undefined. 70 */ 71 #define CHECK_OID(v, oid) \ 72 do { \ 73 v = OBJ_txt2nid(oid); \ 74 if (v == NID_undef) { \ 75 ERROR("Cannot find TBB extension %s\n", oid); \ 76 exit(1); \ 77 } \ 78 } while (0) 79 80 #define MAX_FILENAME_LEN 1024 81 #define VAL_DAYS 7300 82 #define ID_TO_BIT_MASK(id) (1 << id) 83 #define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) 84 85 /* Files */ 86 enum { 87 /* Image file names (inputs) */ 88 BL2_ID = 0, 89 BL30_ID, 90 BL31_ID, 91 BL32_ID, 92 BL33_ID, 93 /* Certificate file names (outputs) */ 94 BL2_CERT_ID, 95 TRUSTED_KEY_CERT_ID, 96 BL30_KEY_CERT_ID, 97 BL30_CERT_ID, 98 BL31_KEY_CERT_ID, 99 BL31_CERT_ID, 100 BL32_KEY_CERT_ID, 101 BL32_CERT_ID, 102 BL33_KEY_CERT_ID, 103 BL33_CERT_ID, 104 /* Key file names (input/output) */ 105 ROT_KEY_ID, 106 TRUSTED_WORLD_KEY_ID, 107 NON_TRUSTED_WORLD_KEY_ID, 108 BL30_KEY_ID, 109 BL31_KEY_ID, 110 BL32_KEY_ID, 111 BL33_KEY_ID, 112 NUM_OPTS 113 }; 114 115 /* Global options */ 116 static int key_alg; 117 static int new_keys; 118 static int save_keys; 119 static int print_cert; 120 121 /* Info messages created in the Makefile */ 122 extern const char build_msg[]; 123 extern const char platform_msg[]; 124 125 126 static char *strdup(const char *str) 127 { 128 int n = strlen(str) + 1; 129 char *dup = malloc(n); 130 if (dup) { 131 strcpy(dup, str); 132 } 133 return dup; 134 } 135 136 static const char *key_algs_str[] = { 137 [KEY_ALG_RSA] = "rsa", 138 #ifndef OPENSSL_NO_EC 139 [KEY_ALG_ECDSA] = "ecdsa" 140 #endif /* OPENSSL_NO_EC */ 141 }; 142 143 static void print_help(const char *cmd, const struct option *long_opt) 144 { 145 int i = 0; 146 printf("\n\n"); 147 printf("The certificate generation tool loads the binary images and\n" 148 "optionally the RSA keys, and outputs the key and content\n" 149 "certificates properly signed to implement the chain of trust.\n" 150 "If keys are provided, they must be in PEM format.\n" 151 "Certificates are generated in DER format.\n"); 152 printf("\n"); 153 printf("Usage:\n\n"); 154 printf(" %s [-hknp] \\\n", cmd); 155 for (i = 0; i < NUM_OPTS; i++) { 156 printf(" --%s <file> \\\n", long_opt[i].name); 157 } 158 printf("\n"); 159 printf("-a Key algorithm: rsa (default), ecdsa\n"); 160 printf("-h Print help and exit\n"); 161 printf("-k Save key pairs into files. Filenames must be provided\n"); 162 printf("-n Generate new key pairs if no key files are provided\n"); 163 printf("-p Print the certificates in the standard output\n"); 164 printf("\n"); 165 166 exit(0); 167 } 168 169 static int get_key_alg(const char *key_alg_str) 170 { 171 int i; 172 173 for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { 174 if (0 == strcmp(key_alg_str, key_algs_str[i])) { 175 return i; 176 } 177 } 178 179 return -1; 180 } 181 182 static void check_cmd_params(void) 183 { 184 cert_t *cert; 185 ext_t *ext; 186 key_t *key; 187 int i, j; 188 189 /* Only save new keys */ 190 if (save_keys && !new_keys) { 191 ERROR("Only new keys can be saved to disk\n"); 192 exit(1); 193 } 194 195 /* Check that all required options have been specified in the 196 * command line */ 197 for (i = 0; i < num_certs; i++) { 198 cert = &certs[i]; 199 if (cert->fn == NULL) { 200 /* Certificate not requested. Skip to the next one */ 201 continue; 202 } 203 204 /* Check that all parameters required to create this certificate 205 * have been specified in the command line */ 206 for (j = 0; j < cert->num_ext; j++) { 207 ext = &extensions[cert->ext[j]]; 208 switch (ext->type) { 209 case EXT_TYPE_PKEY: 210 /* Key filename must be specified */ 211 key = &keys[ext->data.key]; 212 if (!new_keys && key->fn == NULL) { 213 ERROR("Key '%s' required by '%s' not " 214 "specified\n", key->desc, 215 cert->cn); 216 exit(1); 217 } 218 break; 219 case EXT_TYPE_HASH: 220 /* Binary image must be specified */ 221 if (ext->data.fn == NULL) { 222 ERROR("Image for '%s' not specified\n", 223 ext->ln); 224 exit(1); 225 } 226 break; 227 default: 228 ERROR("Unknown extension type in '%s'\n", 229 ext->ln); 230 exit(1); 231 break; 232 } 233 } 234 } 235 } 236 237 int main(int argc, char *argv[]) 238 { 239 STACK_OF(X509_EXTENSION) * sk = NULL; 240 X509_EXTENSION *cert_ext = NULL; 241 ext_t *ext = NULL; 242 key_t *key = NULL; 243 cert_t *cert = NULL; 244 FILE *file = NULL; 245 int i, j, ext_nid; 246 int c, opt_idx = 0; 247 const struct option *cmd_opt; 248 const char *cur_opt; 249 unsigned int err_code; 250 unsigned char md[SHA256_DIGEST_LENGTH]; 251 const EVP_MD *md_info; 252 253 NOTICE("CoT Generation Tool: %s\n", build_msg); 254 NOTICE("Target platform: %s\n", platform_msg); 255 256 /* Set default options */ 257 key_alg = KEY_ALG_RSA; 258 259 /* Add common command line options */ 260 cmd_opt_add("key-alg", required_argument, 'a'); 261 cmd_opt_add("help", no_argument, 'h'); 262 cmd_opt_add("save-keys", no_argument, 'k'); 263 cmd_opt_add("new-chain", no_argument, 'n'); 264 cmd_opt_add("print-cert", no_argument, 'p'); 265 266 /* Initialize the certificates */ 267 if (cert_init() != 0) { 268 ERROR("Cannot initialize certificates\n"); 269 exit(1); 270 } 271 272 /* Initialize the keys */ 273 if (key_init() != 0) { 274 ERROR("Cannot initialize keys\n"); 275 exit(1); 276 } 277 278 /* Initialize the new types and register OIDs for the extensions */ 279 if (ext_init() != 0) { 280 ERROR("Cannot initialize TBB extensions\n"); 281 exit(1); 282 } 283 284 /* Get the command line options populated during the initialization */ 285 cmd_opt = cmd_opt_get_array(); 286 287 while (1) { 288 /* getopt_long stores the option index here. */ 289 c = getopt_long(argc, argv, "ahknp", cmd_opt, &opt_idx); 290 291 /* Detect the end of the options. */ 292 if (c == -1) { 293 break; 294 } 295 296 switch (c) { 297 case 'a': 298 key_alg = get_key_alg(optarg); 299 if (key_alg < 0) { 300 ERROR("Invalid key algorithm '%s'\n", optarg); 301 exit(1); 302 } 303 break; 304 case 'h': 305 print_help(argv[0], cmd_opt); 306 break; 307 case 'k': 308 save_keys = 1; 309 break; 310 case 'n': 311 new_keys = 1; 312 break; 313 case 'p': 314 print_cert = 1; 315 break; 316 case CMD_OPT_EXT: 317 cur_opt = cmd_opt_get_name(opt_idx); 318 ext = ext_get_by_opt(cur_opt); 319 ext->data.fn = strdup(optarg); 320 break; 321 case CMD_OPT_KEY: 322 cur_opt = cmd_opt_get_name(opt_idx); 323 key = key_get_by_opt(cur_opt); 324 key->fn = strdup(optarg); 325 break; 326 case CMD_OPT_CERT: 327 cur_opt = cmd_opt_get_name(opt_idx); 328 cert = cert_get_by_opt(cur_opt); 329 cert->fn = strdup(optarg); 330 break; 331 case '?': 332 default: 333 printf("%s\n", optarg); 334 exit(1); 335 } 336 } 337 338 /* Check command line arguments */ 339 check_cmd_params(); 340 341 /* Indicate SHA256 as image hash algorithm in the certificate 342 * extension */ 343 md_info = EVP_sha256(); 344 345 /* Load private keys from files (or generate new ones) */ 346 for (i = 0 ; i < num_keys ; i++) { 347 /* First try to load the key from disk */ 348 if (key_load(&keys[i], &err_code)) { 349 /* Key loaded successfully */ 350 continue; 351 } 352 353 /* Key not loaded. Check the error code */ 354 if (err_code == KEY_ERR_MALLOC) { 355 /* Cannot allocate memory. Abort. */ 356 ERROR("Malloc error while loading '%s'\n", keys[i].fn); 357 exit(1); 358 } else if (err_code == KEY_ERR_LOAD) { 359 /* File exists, but it does not contain a valid private 360 * key. Abort. */ 361 ERROR("Error loading '%s'\n", keys[i].fn); 362 exit(1); 363 } 364 365 /* File does not exist, could not be opened or no filename was 366 * given */ 367 if (new_keys) { 368 /* Try to create a new key */ 369 NOTICE("Creating new key for '%s'\n", keys[i].desc); 370 if (!key_create(&keys[i], key_alg)) { 371 ERROR("Error creating key '%s'\n", keys[i].desc); 372 exit(1); 373 } 374 } else { 375 if (err_code == KEY_ERR_OPEN) { 376 ERROR("Error opening '%s'\n", keys[i].fn); 377 } else { 378 ERROR("Key '%s' not specified\n", keys[i].desc); 379 } 380 exit(1); 381 } 382 } 383 384 /* Create the certificates */ 385 for (i = 0 ; i < num_certs ; i++) { 386 387 cert = &certs[i]; 388 389 /* Create a new stack of extensions. This stack will be used 390 * to create the certificate */ 391 CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 392 393 for (j = 0 ; j < cert->num_ext ; j++) { 394 395 ext = &extensions[cert->ext[j]]; 396 397 /* Get OpenSSL internal ID for this extension */ 398 CHECK_OID(ext_nid, ext->oid); 399 400 /* 401 * Three types of extensions are currently supported: 402 * - EXT_TYPE_NVCOUNTER 403 * - EXT_TYPE_HASH 404 * - EXT_TYPE_PKEY 405 */ 406 switch (ext->type) { 407 case EXT_TYPE_NVCOUNTER: 408 CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, 409 EXT_CRIT, ext->data.nvcounter)); 410 break; 411 case EXT_TYPE_HASH: 412 if (ext->data.fn == NULL) { 413 break; 414 } 415 if (!sha_file(ext->data.fn, md)) { 416 ERROR("Cannot calculate hash of %s\n", 417 ext->data.fn); 418 exit(1); 419 } 420 CHECK_NULL(cert_ext, ext_new_hash(ext_nid, 421 EXT_CRIT, md_info, md, 422 SHA256_DIGEST_LENGTH)); 423 break; 424 case EXT_TYPE_PKEY: 425 CHECK_NULL(cert_ext, ext_new_key(ext_nid, 426 EXT_CRIT, keys[ext->data.key].key)); 427 break; 428 default: 429 ERROR("Unknown extension type in %s\n", 430 cert->cn); 431 exit(1); 432 } 433 434 /* Push the extension into the stack */ 435 sk_X509_EXTENSION_push(sk, cert_ext); 436 } 437 438 /* Create certificate. Signed with ROT key */ 439 if (cert->fn && !cert_new(cert, VAL_DAYS, 0, sk)) { 440 ERROR("Cannot create %s\n", cert->cn); 441 exit(1); 442 } 443 444 sk_X509_EXTENSION_free(sk); 445 } 446 447 448 /* Print the certificates */ 449 if (print_cert) { 450 for (i = 0 ; i < num_certs ; i++) { 451 if (!certs[i].x) { 452 continue; 453 } 454 printf("\n\n=====================================\n\n"); 455 X509_print_fp(stdout, certs[i].x); 456 } 457 } 458 459 /* Save created certificates to files */ 460 for (i = 0 ; i < num_certs ; i++) { 461 if (certs[i].x && certs[i].fn) { 462 file = fopen(certs[i].fn, "w"); 463 if (file != NULL) { 464 i2d_X509_fp(file, certs[i].x); 465 fclose(file); 466 } else { 467 ERROR("Cannot create file %s\n", certs[i].fn); 468 } 469 } 470 } 471 472 /* Save keys */ 473 if (save_keys) { 474 for (i = 0 ; i < num_keys ; i++) { 475 if (!key_store(&keys[i])) { 476 ERROR("Cannot save %s\n", keys[i].desc); 477 } 478 } 479 } 480 481 #ifndef OPENSSL_NO_ENGINE 482 ENGINE_cleanup(); 483 #endif 484 CRYPTO_cleanup_all_ex_data(); 485 486 return 0; 487 } 488