summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authordanh-arm <dan.handley@arm.com>2015-06-25 09:45:53 +0100
committerdanh-arm <dan.handley@arm.com>2015-06-25 09:45:53 +0100
commit84f95bed549eab4ca40fbd0505e0e3720384880c (patch)
tree024e625474533cb0bd8928dae8321be9060736db /tools
parentdba12894030db45c495643e4320365dd8f0e6f68 (diff)
parentd337aaaf53ef27897f52e66718a2741399c8a021 (diff)
Merge pull request #315 from jcastillo-arm/jc/tbb_tmp9
Authentication Framework
Diffstat (limited to 'tools')
-rw-r--r--tools/cert_create/Makefile5
-rw-r--r--tools/cert_create/include/ext.h3
-rw-r--r--tools/cert_create/include/key.h19
-rw-r--r--tools/cert_create/src/ext.c86
-rw-r--r--tools/cert_create/src/key.c96
-rw-r--r--tools/cert_create/src/main.c102
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);