diff options
author | danh-arm <dan.handley@arm.com> | 2015-06-25 09:45:53 +0100 |
---|---|---|
committer | danh-arm <dan.handley@arm.com> | 2015-06-25 09:45:53 +0100 |
commit | 84f95bed549eab4ca40fbd0505e0e3720384880c (patch) | |
tree | 024e625474533cb0bd8928dae8321be9060736db /tools | |
parent | dba12894030db45c495643e4320365dd8f0e6f68 (diff) | |
parent | d337aaaf53ef27897f52e66718a2741399c8a021 (diff) |
Merge pull request #315 from jcastillo-arm/jc/tbb_tmp9
Authentication Framework
Diffstat (limited to 'tools')
-rw-r--r-- | tools/cert_create/Makefile | 5 | ||||
-rw-r--r-- | tools/cert_create/include/ext.h | 3 | ||||
-rw-r--r-- | tools/cert_create/include/key.h | 19 | ||||
-rw-r--r-- | tools/cert_create/src/ext.c | 86 | ||||
-rw-r--r-- | tools/cert_create/src/key.c | 96 | ||||
-rw-r--r-- | tools/cert_create/src/main.c | 102 |
6 files changed, 249 insertions, 62 deletions
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile index eac8cec8..a4bd76fb 100644 --- a/tools/cert_create/Makefile +++ b/tools/cert_create/Makefile @@ -33,6 +33,7 @@ PLAT := none V := 0 DEBUG := 0 BINARY := ${PROJECT} +OPENSSL_DIR := /usr OBJECTS := src/cert.o \ src/ext.o \ @@ -69,8 +70,8 @@ endif # Make soft links and include from local directory otherwise wrong headers # could get pulled in from firmware tree. -INC_DIR := -I ./include -I ${PLAT_INCLUDE} -LIB_DIR := +INC_DIR := -I ./include -I ${PLAT_INCLUDE} -I ${OPENSSL_DIR}/include +LIB_DIR := -L ${OPENSSL_DIR}/lib LIB := -lssl -lcrypto CC := gcc diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h index d73f5734..57bb65f3 100644 --- a/tools/cert_create/include/ext.h +++ b/tools/cert_create/include/ext.h @@ -63,7 +63,8 @@ enum { }; int ext_init(ext_t *tbb_ext); -X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len); +X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, + unsigned char *buf, size_t len); X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value); X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k); diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h index 88197500..dfb31508 100644 --- a/tools/cert_create/include/key.h +++ b/tools/cert_create/include/key.h @@ -35,6 +35,21 @@ #define RSA_KEY_BITS 2048 +/* Error codes */ +enum { + KEY_ERR_NONE, + KEY_ERR_MALLOC, + KEY_ERR_FILENAME, + KEY_ERR_OPEN, + KEY_ERR_LOAD +}; + +/* Supported key algorithms */ +enum { + KEY_ALG_RSA, + KEY_ALG_ECDSA +}; + /* * This structure contains the relevant information to create the keys * required to sign the certificates. @@ -50,8 +65,8 @@ typedef struct key_s { EVP_PKEY *key; /* Key container */ } key_t; -int key_new(key_t *key); -int key_load(key_t *key); +int key_create(key_t *key, int type); +int key_load(key_t *key, unsigned int *err_code); int key_store(key_t *key); #endif /* KEY_H_ */ diff --git a/tools/cert_create/src/ext.c b/tools/cert_create/src/ext.c index 31f84a86..21b90db1 100644 --- a/tools/cert_create/src/ext.c +++ b/tools/cert_create/src/ext.c @@ -31,13 +31,29 @@ #include <stddef.h> #include <stdio.h> #include <string.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> #include <openssl/err.h> #include <openssl/x509v3.h> #include "ext.h" DECLARE_ASN1_ITEM(ASN1_INTEGER) +DECLARE_ASN1_ITEM(X509_ALGOR) DECLARE_ASN1_ITEM(ASN1_OCTET_STRING) +typedef struct { + X509_ALGOR *hashAlgorithm; + ASN1_OCTET_STRING *dataHash; +} HASH; + +ASN1_SEQUENCE(HASH) = { + ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR), + ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(HASH) + +DECLARE_ASN1_FUNCTIONS(HASH) +IMPLEMENT_ASN1_FUNCTIONS(HASH) + /* * This function adds the TBB extensions to the internal extension list * maintained by OpenSSL so they can be used later. @@ -123,37 +139,85 @@ X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len) } /* - * Creates a x509v3 extension containing a hash encapsulated in an ASN1 Octet - * String + * Creates a x509v3 extension containing a hash + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } * * Parameters: - * pex: OpenSSL extension pointer (output parameter) * nid: extension identifier * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * md: hash algorithm * buf: pointer to the buffer that contains the hash * len: size of the hash in bytes * * Return: Extension address, NULL if error */ -X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len) +X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, + unsigned char *buf, size_t len) { X509_EXTENSION *ex = NULL; - ASN1_OCTET_STRING *hash = NULL; + ASN1_OCTET_STRING *octet = NULL; + HASH *hash = NULL; + ASN1_OBJECT *algorithm = NULL; + X509_ALGOR *x509_algor = NULL; unsigned char *p = NULL; int sz = -1; - /* Encode Hash */ - hash = ASN1_OCTET_STRING_new(); - ASN1_OCTET_STRING_set(hash, buf, len); - sz = i2d_ASN1_OCTET_STRING(hash, NULL); - i2d_ASN1_OCTET_STRING(hash, &p); + /* OBJECT_IDENTIFIER with hash algorithm */ + algorithm = OBJ_nid2obj(md->type); + if (algorithm == NULL) { + return NULL; + } + + /* Create X509_ALGOR */ + x509_algor = X509_ALGOR_new(); + if (x509_algor == NULL) { + return NULL; + } + x509_algor->algorithm = algorithm; + x509_algor->parameter = ASN1_TYPE_new(); + ASN1_TYPE_set(x509_algor->parameter, V_ASN1_NULL, NULL); + + /* OCTET_STRING with the actual hash */ + octet = ASN1_OCTET_STRING_new(); + if (octet == NULL) { + X509_ALGOR_free(x509_algor); + return NULL; + } + ASN1_OCTET_STRING_set(octet, buf, len); + + /* HASH structure containing algorithm + hash */ + hash = HASH_new(); + if (hash == NULL) { + ASN1_OCTET_STRING_free(octet); + X509_ALGOR_free(x509_algor); + return NULL; + } + hash->hashAlgorithm = x509_algor; + hash->dataHash = octet; + + /* DER encoded HASH */ + sz = i2d_HASH(hash, &p); + if ((sz <= 0) || (p == NULL)) { + HASH_free(hash); + X509_ALGOR_free(x509_algor); + return NULL; + } /* Create the extension */ ex = ext_new(nid, crit, p, sz); /* Clean up */ OPENSSL_free(p); - ASN1_OCTET_STRING_free(hash); + HASH_free(hash); return ex; } diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c index b5737d93..2137bf7d 100644 --- a/tools/cert_create/src/key.c +++ b/tools/cert_create/src/key.c @@ -46,41 +46,81 @@ #define MAX_FILENAME_LEN 1024 /* - * Create a new key + * Create a new key container */ -int key_new(key_t *key) +static int key_new(key_t *key) { - RSA *rsa = NULL; - EVP_PKEY *k = NULL; - /* Create key pair container */ - k = EVP_PKEY_new(); - if (k == NULL) { + key->key = EVP_PKEY_new(); + if (key->key == NULL) { return 0; } - /* Generate a new RSA key */ - rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL); - if (EVP_PKEY_assign_RSA(k, rsa)) { - key->key = k; - return 1; - } else { - printf("Cannot assign RSA key\n"); + return 1; +} + +int key_create(key_t *key, int type) +{ + RSA *rsa = NULL; + EC_KEY *ec = NULL; + + /* Create OpenSSL key container */ + if (!key_new(key)) { + goto err; } - if (k) - EVP_PKEY_free(k); + switch (type) { + case KEY_ALG_RSA: + /* Generate a new RSA key */ + rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL); + if (rsa == NULL) { + printf("Cannot create RSA key\n"); + goto err; + } + if (!EVP_PKEY_assign_RSA(key->key, rsa)) { + printf("Cannot assign RSA key\n"); + goto err; + } + break; + case KEY_ALG_ECDSA: + /* Generate a new ECDSA key */ + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (ec == NULL) { + printf("Cannot create EC key\n"); + goto err; + } + if (!EC_KEY_generate_key(ec)) { + printf("Cannot generate EC key\n"); + goto err; + } + EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); + EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); + if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { + printf("Cannot assign EC key\n"); + goto err; + } + break; + default: + goto err; + } + + return 1; + +err: + RSA_free(rsa); + EC_KEY_free(ec); + return 0; } -int key_load(key_t *key) +int key_load(key_t *key, unsigned int *err_code) { FILE *fp = NULL; EVP_PKEY *k = NULL; - /* Create key pair container */ - k = EVP_PKEY_new(); - if (k == NULL) { + /* Create OpenSSL key container */ + if (!key_new(key)) { + *err_code = KEY_ERR_MALLOC; return 0; } @@ -88,24 +128,24 @@ int key_load(key_t *key) /* Load key from file */ fp = fopen(key->fn, "r"); if (fp) { - k = PEM_read_PrivateKey(fp, &k, NULL, NULL); + k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); fclose(fp); if (k) { - key->key = k; + *err_code = KEY_ERR_NONE; return 1; } else { - ERROR("Cannot read key from %s\n", key->fn); + ERROR("Cannot load key from %s\n", key->fn); + *err_code = KEY_ERR_LOAD; } } else { - ERROR("Cannot open file %s\n", key->fn); + WARN("Cannot open file %s\n", key->fn); + *err_code = KEY_ERR_OPEN; } } else { - ERROR("Key filename not specified\n"); + WARN("Key filename not specified\n"); + *err_code = KEY_ERR_FILENAME; } - if (k) - EVP_PKEY_free(k); - return 0; } diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c index 6df367a2..77faf42e 100644 --- a/tools/cert_create/src/main.c +++ b/tools/cert_create/src/main.c @@ -80,6 +80,7 @@ #define VAL_DAYS 7300 #define ID_TO_BIT_MASK(id) (1 << id) #define NVCOUNTER_VALUE 0 +#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) /* Files */ enum { @@ -112,6 +113,7 @@ enum { }; /* Global options */ +static int key_alg; static int new_keys; static int save_keys; static int print_cert; @@ -138,6 +140,11 @@ static char *strdup(const char *str) return dup; } +static const char *key_algs_str[] = { + [KEY_ALG_RSA] = "rsa", + [KEY_ALG_ECDSA] = "ecdsa" +}; + /* Command line options */ static const struct option long_opt[] = { /* Binary images */ @@ -166,6 +173,7 @@ static const struct option long_opt[] = { {"bl32-key", required_argument, 0, BL32_KEY_ID}, {"bl33-key", required_argument, 0, BL33_KEY_ID}, /* Common options */ + {"key-alg", required_argument, 0, 'a'}, {"help", no_argument, 0, 'h'}, {"save-keys", no_argument, 0, 'k'}, {"new-chain", no_argument, 0, 'n'}, @@ -189,6 +197,7 @@ static void print_help(const char *cmd) printf(" --%s <file> \\\n", long_opt[i].name); } printf("\n"); + printf("-a Key algorithm: rsa (default), ecdsa\n"); printf("-h Print help and exit\n"); printf("-k Save key pairs into files. Filenames must be provided\n"); printf("-n Generate new key pairs if no key files are provided\n"); @@ -198,8 +207,27 @@ static void print_help(const char *cmd) exit(0); } +static int get_key_alg(const char *key_alg_str) +{ + int i; + + for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { + if (0 == strcmp(key_alg_str, key_algs_str[i])) { + return i; + } + } + + return -1; +} + static void check_cmd_params(void) { + /* Only save new keys */ + if (save_keys && !new_keys) { + ERROR("Only new keys can be saved to disk\n"); + exit(1); + } + /* BL2, BL31 and BL33 are mandatory */ if (certs[BL2_CERT].bin == NULL) { ERROR("BL2 image not specified\n"); @@ -276,14 +304,19 @@ int main(int argc, char *argv[]) FILE *file = NULL; int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid; int c, opt_idx = 0; + unsigned int err_code; unsigned char md[SHA256_DIGEST_LENGTH]; + const EVP_MD *md_info; NOTICE("CoT Generation Tool: %s\n", build_msg); NOTICE("Target platform: %s\n", platform_msg); + /* Set default options */ + key_alg = KEY_ALG_RSA; + while (1) { /* getopt_long stores the option index here. */ - c = getopt_long(argc, argv, "hknp", long_opt, &opt_idx); + c = getopt_long(argc, argv, "ahknp", long_opt, &opt_idx); /* Detect the end of the options. */ if (c == -1) { @@ -291,6 +324,13 @@ int main(int argc, char *argv[]) } switch (c) { + case 'a': + key_alg = get_key_alg(optarg); + if (key_alg < 0) { + ERROR("Invalid key algorithm '%s'\n", optarg); + exit(1); + } + break; case 'h': print_help(argv[0]); break; @@ -389,24 +429,50 @@ int main(int argc, char *argv[]) exit(1); } + /* Indicate SHA256 as image hash algorithm in the certificate + * extension */ + md_info = EVP_sha256(); + /* Get non-volatile counters NIDs */ CHECK_OID(tz_nvctr_nid, TZ_FW_NVCOUNTER_OID); CHECK_OID(ntz_nvctr_nid, NTZ_FW_NVCOUNTER_OID); /* Load private keys from files (or generate new ones) */ - if (new_keys) { - for (i = 0 ; i < NUM_KEYS ; i++) { - if (!key_new(&keys[i])) { - ERROR("Error creating %s\n", keys[i].desc); - exit(1); - } + for (i = 0 ; i < NUM_KEYS ; i++) { + /* First try to load the key from disk */ + if (key_load(&keys[i], &err_code)) { + /* Key loaded successfully */ + continue; } - } else { - for (i = 0 ; i < NUM_KEYS ; i++) { - if (!key_load(&keys[i])) { - ERROR("Error loading %s\n", keys[i].desc); + + /* Key not loaded. Check the error code */ + if (err_code == KEY_ERR_MALLOC) { + /* Cannot allocate memory. Abort. */ + ERROR("Malloc error while loading '%s'\n", keys[i].fn); + exit(1); + } else if (err_code == KEY_ERR_LOAD) { + /* File exists, but it does not contain a valid private + * key. Abort. */ + ERROR("Error loading '%s'\n", keys[i].fn); + exit(1); + } + + /* File does not exist, could not be opened or no filename was + * given */ + if (new_keys) { + /* Try to create a new key */ + NOTICE("Creating new key for '%s'\n", keys[i].desc); + if (!key_create(&keys[i], key_alg)) { + ERROR("Error creating key '%s'\n", keys[i].desc); exit(1); } + } else { + if (err_code == KEY_ERR_OPEN) { + ERROR("Error opening '%s'\n", keys[i].fn); + } else { + ERROR("Key '%s' not specified\n", keys[i].desc); + } + exit(1); } } @@ -430,7 +496,7 @@ int main(int argc, char *argv[]) exit(1); } CHECK_OID(hash_nid, BL2_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); @@ -509,8 +575,8 @@ int main(int argc, char *argv[]) exit(1); } CHECK_OID(hash_nid, BL30_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, + md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) { @@ -559,7 +625,7 @@ int main(int argc, char *argv[]) exit(1); } CHECK_OID(hash_nid, BL31_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); @@ -612,8 +678,8 @@ int main(int argc, char *argv[]) exit(1); } CHECK_OID(hash_nid, BL32_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, + md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) { @@ -662,7 +728,7 @@ int main(int argc, char *argv[]) exit(1); } CHECK_OID(hash_nid, BL33_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); |