aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJuan Castillo <juan.castillo@arm.com>2015-06-01 16:34:23 +0100
committerJuan Castillo <juan.castillo@arm.com>2015-06-25 08:53:27 +0100
commitccbf890e5e2fb75b4df30f50f06c505702a0e01c (patch)
tree42a35e2e0f737b9eba3f92b20c5ccac9024a0672 /tools
parentdff93c8675e5c7929c2c001034a82c115cdc1e6a (diff)
downloadtrusted-firmware-a-ccbf890e5e2fb75b4df30f50f06c505702a0e01c.tar.gz
TBB: add ECDSA support to the certificate generation tool
This patch extends the 'cert_create' tool to support ECDSA keys to sign the certificates. The '--key-alg' command line option can be used to specify the key algorithm when invoking the tool. Available options are: * 'rsa': create RSA-2048 keys (default option) * 'ecdsa': create ECDSA-SECP256R1 keys The TF Makefile has been updated to allow the platform to specify the key algorithm by declaring the 'KEY_ALG' variable in the platform makefile. The behaviour regarding key management has changed. After applying this patch, the tool will try first to open the keys from disk. If one key does not exist or no key is specified, and the command line option to create keys has been specified, new keys will be created. Otherwise an error will be generated and the tool will exit. This way, the user may specify certain keys while the tool will create the remaining ones. This feature is useful for testing purposes and CI infrastructures. The OpenSSL directory may be specified using the build option 'OPENSSL_DIR' when building the certificate generation tool. Default is '/usr'. Change-Id: I98bcc2bfab28dd7179f17f1177ea7a65698df4e7
Diffstat (limited to 'tools')
-rw-r--r--tools/cert_create/Makefile5
-rw-r--r--tools/cert_create/include/key.h19
-rw-r--r--tools/cert_create/src/key.c96
-rw-r--r--tools/cert_create/src/main.c83
4 files changed, 160 insertions, 43 deletions
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index eac8cec80a..a4bd76fb83 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/key.h b/tools/cert_create/include/key.h
index 8819750056..dfb3150866 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/key.c b/tools/cert_create/src/key.c
index b5737d93ef..2137bf7d2e 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 2af5247fc5..77faf42e13 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,15 +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) {
@@ -292,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;
@@ -399,19 +438,41 @@ int main(int argc, char *argv[])
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);
}
}