diff options
Diffstat (limited to 'tools/cert_create/src')
-rw-r--r-- | tools/cert_create/src/cert.c | 180 | ||||
-rw-r--r-- | tools/cert_create/src/ext.c | 233 | ||||
-rw-r--r-- | tools/cert_create/src/key.c | 131 | ||||
-rw-r--r-- | tools/cert_create/src/main.c | 719 | ||||
-rw-r--r-- | tools/cert_create/src/sha.c | 64 | ||||
-rw-r--r-- | tools/cert_create/src/tbb_cert.c | 111 | ||||
-rw-r--r-- | tools/cert_create/src/tbb_ext.c | 118 | ||||
-rw-r--r-- | tools/cert_create/src/tbb_key.c | 67 |
8 files changed, 1623 insertions, 0 deletions
diff --git a/tools/cert_create/src/cert.c b/tools/cert_create/src/cert.c new file mode 100644 index 00000000..9705643d --- /dev/null +++ b/tools/cert_create/src/cert.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <openssl/conf.h> +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/sha.h> +#include <openssl/x509v3.h> + +#include "cert.h" +#include "debug.h" +#include "key.h" +#include "platform_oid.h" +#include "sha.h" + +#define SERIAL_RAND_BITS 64 + +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) +{ + BIGNUM *btmp; + int ret = 0; + if (b) + btmp = b; + else + btmp = BN_new(); + + if (!btmp) + return 0; + + if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) + goto error; + if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) + goto error; + + ret = 1; + +error: + + if (!b) + BN_free(btmp); + + return ret; +} + +int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value) +{ + X509_EXTENSION *ex; + X509V3_CTX ctx; + + /* No configuration database */ + X509V3_set_ctx_nodb(&ctx); + + /* Set issuer and subject certificates in the context */ + X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0); + ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); + if (!ex) { + ERR_print_errors_fp(stdout); + return 0; + } + + X509_add_ext(subject, ex, -1); + X509_EXTENSION_free(ex); + + return 1; +} + + +int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk) +{ + EVP_PKEY *pkey = cert->key->key; + EVP_PKEY *ikey = cert->issuer->key->key; + X509 *issuer = cert->issuer->x; + X509 *x = NULL; + X509_EXTENSION *ex = NULL; + X509_NAME *name = NULL; + ASN1_INTEGER *sno = NULL; + int i, num; + + /* Create the certificate structure */ + x = X509_new(); + if (!x) { + return 0; + } + + /* If we do not have a key, use the issuer key (the certificate will + * become self signed). This happens in content certificates. */ + if (!pkey) { + pkey = ikey; + } + + /* If we do not have an issuer certificate, use our own (the certificate + * will become self signed) */ + if (!issuer) { + issuer = x; + } + + /* x509.v3 */ + X509_set_version(x, 2); + + /* Random serial number */ + sno = ASN1_INTEGER_new(); + rand_serial(NULL, sno); + X509_set_serialNumber(x, sno); + ASN1_INTEGER_free(sno); + + X509_gmtime_adj(X509_get_notBefore(x), 0); + X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days); + X509_set_pubkey(x, pkey); + + /* Subject name */ + name = X509_get_subject_name(x); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, + (const unsigned char *)cert->cn, -1, -1, 0); + X509_set_subject_name(x, name); + + /* Issuer name */ + name = X509_get_issuer_name(x); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, + (const unsigned char *)cert->issuer->cn, -1, -1, 0); + X509_set_issuer_name(x, name); + + /* Add various extensions: standard extensions */ + cert_add_ext(issuer, x, NID_subject_key_identifier, "hash"); + cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always"); + if (ca) { + cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE"); + cert_add_ext(issuer, x, NID_key_usage, "keyCertSign"); + } else { + cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE"); + } + + /* Add custom extensions */ + if (sk != NULL) { + num = sk_X509_EXTENSION_num(sk); + for (i = 0; i < num; i++) { + ex = sk_X509_EXTENSION_value(sk, i); + X509_add_ext(x, ex, -1); + } + } + + /* Sign the certificate with the issuer key */ + if (!X509_sign(x, ikey, EVP_sha1())) { + ERR_print_errors_fp(stdout); + return 0; + } + + cert->x = x; + return 1; +} diff --git a/tools/cert_create/src/ext.c b/tools/cert_create/src/ext.c new file mode 100644 index 00000000..31f84a86 --- /dev/null +++ b/tools/cert_create/src/ext.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <openssl/err.h> +#include <openssl/x509v3.h> +#include "ext.h" + +DECLARE_ASN1_ITEM(ASN1_INTEGER) +DECLARE_ASN1_ITEM(ASN1_OCTET_STRING) + +/* + * This function adds the TBB extensions to the internal extension list + * maintained by OpenSSL so they can be used later. + * + * It also initializes the methods to print the contents of the extension. If an + * alias is specified in the TBB extension, we reuse the methods of the alias. + * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are + * provided. Any other type will be printed as a raw ascii string. + * + * Return: 0 = success, Otherwise: error + */ +int ext_init(ext_t *tbb_ext) +{ + ext_t *ext; + X509V3_EXT_METHOD *m; + int i = 0, nid, ret; + + while ((ext = &tbb_ext[i++]) && ext->oid) { + nid = OBJ_create(ext->oid, ext->sn, ext->ln); + if (ext->alias) { + X509V3_EXT_add_alias(nid, ext->alias); + } else { + m = &ext->method; + memset(m, 0x0, sizeof(X509V3_EXT_METHOD)); + switch (ext->type) { + case V_ASN1_INTEGER: + m->it = ASN1_ITEM_ref(ASN1_INTEGER); + m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER; + m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER; + break; + case V_ASN1_OCTET_STRING: + m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING); + m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING; + m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING; + break; + default: + continue; + } + m->ext_nid = nid; + ret = X509V3_EXT_add(m); + if (!ret) { + ERR_print_errors_fp(stdout); + return 1; + } + } + } + return 0; +} + +/* + * Create a new extension + * + * Extension ::= SEQUENCE { + * id OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * value OCTET STRING } + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * data: extension data. This data will be encapsulated in an Octet String + * + * Return: Extension address, NULL if error + */ +static +X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len) +{ + X509_EXTENSION *ex; + ASN1_OCTET_STRING *ext_data; + + /* Octet string containing the extension data */ + ext_data = ASN1_OCTET_STRING_new(); + ASN1_OCTET_STRING_set(ext_data, data, len); + + /* Create the extension */ + ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data); + + /* The extension makes a copy of the data, so we can free this object */ + ASN1_OCTET_STRING_free(ext_data); + + return ex; +} + +/* + * Creates a x509v3 extension containing a hash encapsulated in an ASN1 Octet + * String + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * 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 *ex = NULL; + ASN1_OCTET_STRING *hash = 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); + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Clean up */ + OPENSSL_free(p); + ASN1_OCTET_STRING_free(hash); + + return ex; +} + +/* + * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1 + * Integer + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * value: nvcounter value + * + * Return: Extension address, NULL if error + */ +X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value) +{ + X509_EXTENSION *ex = NULL; + ASN1_INTEGER *counter = NULL; + unsigned char *p = NULL; + int sz = -1; + + /* Encode counter */ + counter = ASN1_INTEGER_new(); + ASN1_INTEGER_set(counter, value); + sz = i2d_ASN1_INTEGER(counter, NULL); + i2d_ASN1_INTEGER(counter, &p); + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Free objects */ + OPENSSL_free(p); + ASN1_INTEGER_free(counter); + + return ex; +} + +/* + * Creates a x509v3 extension containing a public key in DER format: + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * k: key + * + * Return: Extension address, NULL if error + */ +X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k) +{ + X509_EXTENSION *ex = NULL; + unsigned char *p = NULL; + int sz = -1; + + /* Encode key */ + BIO *mem = BIO_new(BIO_s_mem()); + if (i2d_PUBKEY_bio(mem, k) <= 0) { + ERR_print_errors_fp(stderr); + return NULL; + } + p = (unsigned char *)OPENSSL_malloc(4096); + sz = BIO_read(mem, p, 4096); + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Clean up */ + OPENSSL_free(p); + + return ex; +} diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c new file mode 100644 index 00000000..b5737d93 --- /dev/null +++ b/tools/cert_create/src/key.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <openssl/conf.h> +#include <openssl/evp.h> +#include <openssl/pem.h> + +#include "cert.h" +#include "debug.h" +#include "key.h" +#include "platform_oid.h" +#include "sha.h" + +#define MAX_FILENAME_LEN 1024 + +/* + * Create a new key + */ +int key_new(key_t *key) +{ + RSA *rsa = NULL; + EVP_PKEY *k = NULL; + + /* Create key pair container */ + k = EVP_PKEY_new(); + if (k == 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"); + } + + if (k) + EVP_PKEY_free(k); + return 0; +} + +int key_load(key_t *key) +{ + FILE *fp = NULL; + EVP_PKEY *k = NULL; + + /* Create key pair container */ + k = EVP_PKEY_new(); + if (k == NULL) { + return 0; + } + + if (key->fn) { + /* Load key from file */ + fp = fopen(key->fn, "r"); + if (fp) { + k = PEM_read_PrivateKey(fp, &k, NULL, NULL); + fclose(fp); + if (k) { + key->key = k; + return 1; + } else { + ERROR("Cannot read key from %s\n", key->fn); + } + } else { + ERROR("Cannot open file %s\n", key->fn); + } + } else { + ERROR("Key filename not specified\n"); + } + + if (k) + EVP_PKEY_free(k); + + return 0; +} + +int key_store(key_t *key) +{ + FILE *fp = NULL; + + if (key->fn) { + fp = fopen(key->fn, "w"); + if (fp) { + PEM_write_PrivateKey(fp, key->key, + NULL, NULL, 0, NULL, NULL); + fclose(fp); + return 1; + } else { + ERROR("Cannot create file %s\n", key->fn); + } + } else { + ERROR("Key filename not specified\n"); + } + + return 0; +} diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c new file mode 100644 index 00000000..6df367a2 --- /dev/null +++ b/tools/cert_create/src/main.c @@ -0,0 +1,719 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <openssl/conf.h> +#include <openssl/engine.h> +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/sha.h> +#include <openssl/x509v3.h> + +#include "cert.h" +#include "debug.h" +#include "ext.h" +#include "key.h" +#include "platform_oid.h" +#include "sha.h" +#include "tbb_ext.h" +#include "tbb_cert.h" +#include "tbb_key.h" + +/* + * Helper macros to simplify the code. This macro assigns the return value of + * the 'fn' function to 'v' and exits if the value is NULL. + */ +#define CHECK_NULL(v, fn) \ + do { \ + v = fn; \ + if (v == NULL) { \ + ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ + exit(1); \ + } \ + } while (0) + +/* + * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the + * NID is undefined. + */ +#define CHECK_OID(v, oid) \ + do { \ + v = OBJ_txt2nid(oid); \ + if (v == NID_undef) { \ + ERROR("Cannot find TBB extension %s\n", oid); \ + exit(1); \ + } \ + } while (0) + +#define MAX_FILENAME_LEN 1024 +#define VAL_DAYS 7300 +#define ID_TO_BIT_MASK(id) (1 << id) +#define NVCOUNTER_VALUE 0 + +/* Files */ +enum { + /* Image file names (inputs) */ + BL2_ID = 0, + BL30_ID, + BL31_ID, + BL32_ID, + BL33_ID, + /* Certificate file names (outputs) */ + BL2_CERT_ID, + TRUSTED_KEY_CERT_ID, + BL30_KEY_CERT_ID, + BL30_CERT_ID, + BL31_KEY_CERT_ID, + BL31_CERT_ID, + BL32_KEY_CERT_ID, + BL32_CERT_ID, + BL33_KEY_CERT_ID, + BL33_CERT_ID, + /* Key file names (input/output) */ + ROT_KEY_ID, + TRUSTED_WORLD_KEY_ID, + NON_TRUSTED_WORLD_KEY_ID, + BL30_KEY_ID, + BL31_KEY_ID, + BL32_KEY_ID, + BL33_KEY_ID, + NUM_OPTS +}; + +/* Global options */ +static int new_keys; +static int save_keys; +static int print_cert; +static int bl30_present; +static int bl32_present; + +/* We are not checking nvcounters in TF. Include them in the certificates but + * the value will be set to 0 */ +static int tf_nvcounter; +static int non_tf_nvcounter; + +/* Info messages created in the Makefile */ +extern const char build_msg[]; +extern const char platform_msg[]; + + +static char *strdup(const char *str) +{ + int n = strlen(str) + 1; + char *dup = malloc(n); + if (dup) { + strcpy(dup, str); + } + return dup; +} + +/* Command line options */ +static const struct option long_opt[] = { + /* Binary images */ + {"bl2", required_argument, 0, BL2_ID}, + {"bl30", required_argument, 0, BL30_ID}, + {"bl31", required_argument, 0, BL31_ID}, + {"bl32", required_argument, 0, BL32_ID}, + {"bl33", required_argument, 0, BL33_ID}, + /* Certificate files */ + {"bl2-cert", required_argument, 0, BL2_CERT_ID}, + {"trusted-key-cert", required_argument, 0, TRUSTED_KEY_CERT_ID}, + {"bl30-key-cert", required_argument, 0, BL30_KEY_CERT_ID}, + {"bl30-cert", required_argument, 0, BL30_CERT_ID}, + {"bl31-key-cert", required_argument, 0, BL31_KEY_CERT_ID}, + {"bl31-cert", required_argument, 0, BL31_CERT_ID}, + {"bl32-key-cert", required_argument, 0, BL32_KEY_CERT_ID}, + {"bl32-cert", required_argument, 0, BL32_CERT_ID}, + {"bl33-key-cert", required_argument, 0, BL33_KEY_CERT_ID}, + {"bl33-cert", required_argument, 0, BL33_CERT_ID}, + /* Private key files */ + {"rot-key", required_argument, 0, ROT_KEY_ID}, + {"trusted-world-key", required_argument, 0, TRUSTED_WORLD_KEY_ID}, + {"non-trusted-world-key", required_argument, 0, NON_TRUSTED_WORLD_KEY_ID}, + {"bl30-key", required_argument, 0, BL30_KEY_ID}, + {"bl31-key", required_argument, 0, BL31_KEY_ID}, + {"bl32-key", required_argument, 0, BL32_KEY_ID}, + {"bl33-key", required_argument, 0, BL33_KEY_ID}, + /* Common options */ + {"help", no_argument, 0, 'h'}, + {"save-keys", no_argument, 0, 'k'}, + {"new-chain", no_argument, 0, 'n'}, + {"print-cert", no_argument, 0, 'p'}, + {0, 0, 0, 0} +}; + +static void print_help(const char *cmd) +{ + int i = 0; + printf("\n\n"); + printf("The certificate generation tool loads the binary images and\n" + "optionally the RSA keys, and outputs the key and content\n" + "certificates properly signed to implement the chain of trust.\n" + "If keys are provided, they must be in PEM format.\n" + "Certificates are generated in DER format.\n"); + printf("\n"); + printf("Usage:\n\n"); + printf(" %s [-hknp] \\\n", cmd); + for (i = 0; i < NUM_OPTS; i++) { + printf(" --%s <file> \\\n", long_opt[i].name); + } + printf("\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"); + printf("-p Print the certificates in the standard output\n"); + printf("\n"); + + exit(0); +} + +static void check_cmd_params(void) +{ + /* BL2, BL31 and BL33 are mandatory */ + if (certs[BL2_CERT].bin == NULL) { + ERROR("BL2 image not specified\n"); + exit(1); + } + + if (certs[BL31_CERT].bin == NULL) { + ERROR("BL31 image not specified\n"); + exit(1); + } + + if (certs[BL33_CERT].bin == NULL) { + ERROR("BL33 image not specified\n"); + exit(1); + } + + /* BL30 and BL32 are optional */ + if (certs[BL30_CERT].bin != NULL) { + bl30_present = 1; + } + + if (certs[BL32_CERT].bin != NULL) { + bl32_present = 1; + } + + /* TODO: Certificate filenames */ + + /* Filenames to store keys must be specified */ + if (save_keys || !new_keys) { + if (keys[ROT_KEY].fn == NULL) { + ERROR("ROT key not specified\n"); + exit(1); + } + + if (keys[TRUSTED_WORLD_KEY].fn == NULL) { + ERROR("Trusted World key not specified\n"); + exit(1); + } + + if (keys[NON_TRUSTED_WORLD_KEY].fn == NULL) { + ERROR("Non-trusted World key not specified\n"); + exit(1); + } + + if (keys[BL31_KEY].fn == NULL) { + ERROR("BL31 key not specified\n"); + exit(1); + } + + if (keys[BL33_KEY].fn == NULL) { + ERROR("BL33 key not specified\n"); + exit(1); + } + + if (bl30_present && (keys[BL30_KEY].fn == NULL)) { + ERROR("BL30 key not specified\n"); + exit(1); + } + + if (bl32_present && (keys[BL32_KEY].fn == NULL)) { + ERROR("BL32 key not specified\n"); + exit(1); + } + } +} + +int main(int argc, char *argv[]) +{ + STACK_OF(X509_EXTENSION) * sk = NULL; + X509_EXTENSION *hash_ext = NULL; + X509_EXTENSION *nvctr_ext = NULL; + X509_EXTENSION *trusted_key_ext = NULL; + X509_EXTENSION *non_trusted_key_ext = NULL; + FILE *file = NULL; + int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid; + int c, opt_idx = 0; + unsigned char md[SHA256_DIGEST_LENGTH]; + + NOTICE("CoT Generation Tool: %s\n", build_msg); + NOTICE("Target platform: %s\n", platform_msg); + + while (1) { + /* getopt_long stores the option index here. */ + c = getopt_long(argc, argv, "hknp", long_opt, &opt_idx); + + /* Detect the end of the options. */ + if (c == -1) { + break; + } + + switch (c) { + case 'h': + print_help(argv[0]); + break; + case 'k': + save_keys = 1; + break; + case 'n': + new_keys = 1; + break; + case 'p': + print_cert = 1; + break; + case BL2_ID: + certs[BL2_CERT].bin = strdup(optarg); + break; + case BL30_ID: + certs[BL30_CERT].bin = strdup(optarg); + break; + case BL31_ID: + certs[BL31_CERT].bin = strdup(optarg); + break; + case BL32_ID: + certs[BL32_CERT].bin = strdup(optarg); + break; + case BL33_ID: + certs[BL33_CERT].bin = strdup(optarg); + break; + case BL2_CERT_ID: + certs[BL2_CERT].fn = strdup(optarg); + break; + case TRUSTED_KEY_CERT_ID: + certs[TRUSTED_KEY_CERT].fn = strdup(optarg); + break; + case BL30_KEY_CERT_ID: + certs[BL30_KEY_CERT].fn = strdup(optarg); + break; + case BL30_CERT_ID: + certs[BL30_CERT].fn = strdup(optarg); + break; + case BL31_KEY_CERT_ID: + certs[BL31_KEY_CERT].fn = strdup(optarg); + break; + case BL31_CERT_ID: + certs[BL31_CERT].fn = strdup(optarg); + break; + case BL32_KEY_CERT_ID: + certs[BL32_KEY_CERT].fn = strdup(optarg); + break; + case BL32_CERT_ID: + certs[BL32_CERT].fn = strdup(optarg); + break; + case BL33_KEY_CERT_ID: + certs[BL33_KEY_CERT].fn = strdup(optarg); + break; + case BL33_CERT_ID: + certs[BL33_CERT].fn = strdup(optarg); + break; + case ROT_KEY_ID: + keys[ROT_KEY].fn = strdup(optarg); + break; + case TRUSTED_WORLD_KEY_ID: + keys[TRUSTED_WORLD_KEY].fn = strdup(optarg); + break; + case NON_TRUSTED_WORLD_KEY_ID: + keys[NON_TRUSTED_WORLD_KEY].fn = strdup(optarg); + break; + case BL30_KEY_ID: + keys[BL30_KEY].fn = strdup(optarg); + break; + case BL31_KEY_ID: + keys[BL31_KEY].fn = strdup(optarg); + break; + case BL32_KEY_ID: + keys[BL32_KEY].fn = strdup(optarg); + break; + case BL33_KEY_ID: + keys[BL33_KEY].fn = strdup(optarg); + break; + case '?': + default: + printf("%s\n", optarg); + exit(1); + } + } + + /* Set the value of the NVCounters */ + tf_nvcounter = NVCOUNTER_VALUE; + non_tf_nvcounter = NVCOUNTER_VALUE; + + /* Check command line arguments */ + check_cmd_params(); + + /* Register the new types and OIDs for the extensions */ + if (ext_init(tbb_ext) != 0) { + ERROR("Cannot initialize TBB extensions\n"); + exit(1); + } + + /* 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); + } + } + } else { + for (i = 0 ; i < NUM_KEYS ; i++) { + if (!key_load(&keys[i])) { + ERROR("Error loading %s\n", keys[i].desc); + exit(1); + } + } + } + + /* ********************************************************************* + * BL2 certificate (Trusted Boot Firmware certificate): + * - Self-signed with OEM ROT private key + * - Extensions: + * - TrustedFirmwareNVCounter (TODO) + * - BL2 hash + **********************************************************************/ + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + + /* Add the NVCounter as a critical extension */ + CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, + tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + + /* Add hash of BL2 as an extension */ + if (!sha_file(certs[BL2_CERT].bin, md)) { + ERROR("Cannot calculate the hash of %s\n", certs[BL2_CERT].bin); + exit(1); + } + CHECK_OID(hash_nid, BL2_HASH_OID); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + SHA256_DIGEST_LENGTH)); + sk_X509_EXTENSION_push(sk, hash_ext); + + /* Create certificate. Signed with ROT key */ + if (!cert_new(&certs[BL2_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL2_CERT].cn); + exit(1); + } + sk_X509_EXTENSION_free(sk); + + /* ********************************************************************* + * Trusted Key certificate: + * - Self-signed with OEM ROT private key + * - Extensions: + * - TrustedFirmwareNVCounter (TODO) + * - TrustedWorldPK + * - NonTrustedWorldPK + **********************************************************************/ + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, + tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + CHECK_OID(pk_nid, TZ_WORLD_PK_OID); + CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, + keys[TRUSTED_WORLD_KEY].key)); + sk_X509_EXTENSION_push(sk, trusted_key_ext); + CHECK_OID(pk_nid, NTZ_WORLD_PK_OID); + CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, + keys[NON_TRUSTED_WORLD_KEY].key)); + sk_X509_EXTENSION_push(sk, non_trusted_key_ext); + if (!cert_new(&certs[TRUSTED_KEY_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[TRUSTED_KEY_CERT].cn); + exit(1); + } + sk_X509_EXTENSION_free(sk); + + /* ********************************************************************* + * BL30 Key certificate (Trusted SCP Firmware Key certificate): + * - Self-signed with Trusted World key + * - Extensions: + * - TrustedFirmwareNVCounter (TODO) + * - SCPFirmwareContentCertPK + **********************************************************************/ + if (bl30_present) { + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, + tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + CHECK_OID(pk_nid, BL30_CONTENT_CERT_PK_OID); + CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, + keys[BL30_KEY].key)); + sk_X509_EXTENSION_push(sk, trusted_key_ext); + if (!cert_new(&certs[BL30_KEY_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL30_KEY_CERT].cn); + exit(1); + } + sk_X509_EXTENSION_free(sk); + } + + /* ********************************************************************* + * BL30 certificate (SCP Firmware Content certificate): + * - Signed with Trusted World Key + * - Extensions: + * - TrustedFirmwareNVCounter (TODO) + * - SCPFirmwareHash + **********************************************************************/ + if (bl30_present) { + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, + tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + + if (!sha_file(certs[BL30_CERT].bin, md)) { + ERROR("Cannot calculate the hash of %s\n", + certs[BL30_CERT].bin); + exit(1); + } + CHECK_OID(hash_nid, BL30_HASH_OID); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + SHA256_DIGEST_LENGTH)); + sk_X509_EXTENSION_push(sk, hash_ext); + + if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL30_CERT].cn); + exit(1); + } + + sk_X509_EXTENSION_free(sk); + } + + /* ********************************************************************* + * BL31 Key certificate (Trusted SoC Firmware Key certificate): + * - Self-signed with Trusted World key + * - Extensions: + * - TrustedFirmwareNVCounter (TODO) + * - SoCFirmwareContentCertPK + **********************************************************************/ + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, + tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + CHECK_OID(pk_nid, BL31_CONTENT_CERT_PK_OID); + CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, + keys[BL31_KEY].key)); + sk_X509_EXTENSION_push(sk, trusted_key_ext); + if (!cert_new(&certs[BL31_KEY_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL31_KEY_CERT].cn); + exit(1); + } + sk_X509_EXTENSION_free(sk); + + /* ********************************************************************* + * BL31 certificate (SOC Firmware Content certificate): + * - Signed with Trusted World Key + * - Extensions: + * - TrustedFirmwareNVCounter (TODO) + * - BL31 hash + **********************************************************************/ + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, + tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + + if (!sha_file(certs[BL31_CERT].bin, md)) { + ERROR("Cannot calculate the hash of %s\n", certs[BL31_CERT].bin); + exit(1); + } + CHECK_OID(hash_nid, BL31_HASH_OID); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + SHA256_DIGEST_LENGTH)); + sk_X509_EXTENSION_push(sk, hash_ext); + + if (!cert_new(&certs[BL31_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL31_CERT].cn); + exit(1); + } + + sk_X509_EXTENSION_free(sk); + + /* ********************************************************************* + * BL32 Key certificate (Trusted OS Firmware Key certificate): + * - Self-signed with Trusted World key + * - Extensions: + * - TrustedFirmwareNVCounter (TODO) + * - TrustedOSFirmwareContentCertPK + **********************************************************************/ + if (bl32_present) { + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, + tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + CHECK_OID(pk_nid, BL32_CONTENT_CERT_PK_OID); + CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, + keys[BL32_KEY].key)); + sk_X509_EXTENSION_push(sk, trusted_key_ext); + if (!cert_new(&certs[BL32_KEY_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL32_KEY_CERT].cn); + exit(1); + } + sk_X509_EXTENSION_free(sk); + } + + /* ********************************************************************* + * BL32 certificate (TrustedOS Firmware Content certificate): + * - Signed with Trusted World Key + * - Extensions: + * - TrustedFirmwareNVCounter (TODO) + * - BL32 hash + **********************************************************************/ + if (bl32_present) { + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, + tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + + if (!sha_file(certs[BL32_CERT].bin, md)) { + ERROR("Cannot calculate the hash of %s\n", + certs[BL32_CERT].bin); + exit(1); + } + CHECK_OID(hash_nid, BL32_HASH_OID); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + SHA256_DIGEST_LENGTH)); + sk_X509_EXTENSION_push(sk, hash_ext); + + if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL32_CERT].cn); + exit(1); + } + + sk_X509_EXTENSION_free(sk); + } + + /* ********************************************************************* + * BL33 Key certificate (Non Trusted Firmware Key certificate): + * - Self-signed with Non Trusted World key + * - Extensions: + * - NonTrustedFirmwareNVCounter (TODO) + * - NonTrustedFirmwareContentCertPK + **********************************************************************/ + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT, + non_tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + CHECK_OID(pk_nid, BL33_CONTENT_CERT_PK_OID); + CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, + keys[BL33_KEY].key)); + sk_X509_EXTENSION_push(sk, non_trusted_key_ext); + if (!cert_new(&certs[BL33_KEY_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL33_KEY_CERT].cn); + exit(1); + } + sk_X509_EXTENSION_free(sk); + + /* ********************************************************************* + * BL33 certificate (Non-Trusted World Content certificate): + * - Signed with Non-Trusted World Key + * - Extensions: + * - NonTrustedFirmwareNVCounter (TODO) + * - BL33 hash + **********************************************************************/ + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT, + non_tf_nvcounter)); + sk_X509_EXTENSION_push(sk, nvctr_ext); + + if (!sha_file(certs[BL33_CERT].bin, md)) { + ERROR("Cannot calculate the hash of %s\n", certs[BL33_CERT].bin); + exit(1); + } + CHECK_OID(hash_nid, BL33_HASH_OID); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + SHA256_DIGEST_LENGTH)); + sk_X509_EXTENSION_push(sk, hash_ext); + + if (!cert_new(&certs[BL33_CERT], VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", certs[BL33_CERT].cn); + exit(1); + } + sk_X509_EXTENSION_free(sk); + + /* Print the certificates */ + if (print_cert) { + for (i = 0 ; i < NUM_CERTIFICATES ; i++) { + if (!certs[i].x) { + continue; + } + printf("\n\n=====================================\n\n"); + X509_print_fp(stdout, certs[i].x); + } + } + + /* Save created certificates to files */ + for (i = 0 ; i < NUM_CERTIFICATES ; i++) { + if (certs[i].x && certs[i].fn) { + file = fopen(certs[i].fn, "w"); + if (file != NULL) { + i2d_X509_fp(file, certs[i].x); + fclose(file); + } else { + ERROR("Cannot create file %s\n", certs[i].fn); + } + } + } + + /* Save keys */ + if (save_keys) { + for (i = 0 ; i < NUM_KEYS ; i++) { + if (!key_store(&keys[i])) { + ERROR("Cannot save %s\n", keys[i].desc); + } + } + } + + X509_EXTENSION_free(hash_ext); + X509_EXTENSION_free(nvctr_ext); + X509_EXTENSION_free(trusted_key_ext); + X509_EXTENSION_free(non_trusted_key_ext); + +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + CRYPTO_cleanup_all_ex_data(); + + return 0; +} diff --git a/tools/cert_create/src/sha.c b/tools/cert_create/src/sha.c new file mode 100644 index 00000000..57026b56 --- /dev/null +++ b/tools/cert_create/src/sha.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <openssl/sha.h> + +#include "debug.h" + +#define BUFFER_SIZE 256 + +int sha_file(const char *filename, unsigned char *md) +{ + FILE *inFile; + SHA256_CTX shaContext; + int bytes; + unsigned char data[BUFFER_SIZE]; + + if ((filename == NULL) || (md == NULL)) { + ERROR("%s(): NULL argument\n", __FUNCTION__); + return 0; + } + + inFile = fopen(filename, "rb"); + if (inFile == NULL) { + ERROR("Cannot read %s\n", filename); + return 0; + } + + SHA256_Init(&shaContext); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA256_Update(&shaContext, data, bytes); + } + SHA256_Final(md, &shaContext); + + fclose(inFile); + return 1; +} diff --git a/tools/cert_create/src/tbb_cert.c b/tools/cert_create/src/tbb_cert.c new file mode 100644 index 00000000..8dfda605 --- /dev/null +++ b/tools/cert_create/src/tbb_cert.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tbb_cert.h" +#include "tbb_key.h" + +/* + * Certificates used in the chain of trust + * + * The order of the certificates must follow the enumeration specified in + * tbb_cert.h. All certificates are self-signed. + */ +cert_t certs[NUM_CERTIFICATES] = { + { + .id = BL2_CERT, + .fn = NULL, + .cn = "BL2 Certificate", + .key = &keys[ROT_KEY], + .issuer = &certs[BL2_CERT], + }, + { + .id = TRUSTED_KEY_CERT, + .fn = NULL, + .cn = "Trusted Key Certificate", + .key = &keys[ROT_KEY], + .issuer = &certs[TRUSTED_KEY_CERT], + }, + { + .id = BL30_KEY_CERT, + .fn = NULL, + .cn = "BL3-0 Key Certificate", + .key = &keys[TRUSTED_WORLD_KEY], + .issuer = &certs[BL30_KEY_CERT], + }, + { + .id = BL30_CERT, + .fn = NULL, + .cn = "BL3-0 Content Certificate", + .key = &keys[BL30_KEY], + .issuer = &certs[BL30_CERT], + }, + { + .id = BL31_KEY_CERT, + .fn = NULL, + .cn = "BL3-1 Key Certificate", + .key = &keys[TRUSTED_WORLD_KEY], + .issuer = &certs[BL31_KEY_CERT], + }, + { + .id = BL31_CERT, + .fn = NULL, + .cn = "BL3-1 Content Certificate", + .key = &keys[BL31_KEY], + .issuer = &certs[BL31_CERT], + }, + { + .id = BL32_KEY_CERT, + .fn = NULL, + .cn = "BL3-2 Key Certificate", + .key = &keys[TRUSTED_WORLD_KEY], + .issuer = &certs[BL32_KEY_CERT], + }, + { + .id = BL32_CERT, + .fn = NULL, + .cn = "BL3-2 Content Certificate", + .key = &keys[BL32_KEY], + .issuer = &certs[BL32_CERT], + }, + { + .id = BL33_KEY_CERT, + .fn = NULL, + .cn = "BL3-3 Key Certificate", + .key = &keys[NON_TRUSTED_WORLD_KEY], + .issuer = &certs[BL33_KEY_CERT], + }, + { + .id = BL33_CERT, + .fn = NULL, + .cn = "BL3-3 Content Certificate", + .key = &keys[BL33_KEY], + .issuer = &certs[BL33_CERT], + } +}; diff --git a/tools/cert_create/src/tbb_ext.c b/tools/cert_create/src/tbb_ext.c new file mode 100644 index 00000000..0022611c --- /dev/null +++ b/tools/cert_create/src/tbb_ext.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <openssl/err.h> +#include <openssl/x509v3.h> +#include "ext.h" +#include "platform_oid.h" + +ext_t tbb_ext[] = { + { + .oid = TZ_FW_NVCOUNTER_OID, + .sn = "TrustedNvCounter", + .ln = "Non-volatile trusted counter", + .type = V_ASN1_INTEGER + }, + { + .oid = NTZ_FW_NVCOUNTER_OID, + .sn = "NonTrustedNvCounter", + .ln = "Non-volatile non-trusted counter", + .type = V_ASN1_INTEGER + }, + { + .oid = BL2_HASH_OID, + .sn = "TrustedBootFirmwareHash", + .ln = "Trusted Boot Firmware (BL2) hash (SHA256)", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = TZ_WORLD_PK_OID, + .sn = "TrustedWorldPublicKey", + .ln = "Trusted World Public Key", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = NTZ_WORLD_PK_OID, + .sn = "NonTrustedWorldPublicKey", + .ln = "Non-Trusted World Public Key", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = BL31_CONTENT_CERT_PK_OID, + .sn = "SoCFirmwareContentCertPK", + .ln = "SoC Firmware content certificate public key", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = BL31_HASH_OID, + .sn = "APROMPatchHash", + .ln = "AP ROM patch hash", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = BL30_CONTENT_CERT_PK_OID, + .sn = "SCPFirmwareContentCertPK", + .ln = "SCP Firmware content certificate public key", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = BL30_HASH_OID, + .sn = "SCPFirmwareHash", + .ln = "SCP Firmware (BL30) hash (SHA256)", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = BL32_CONTENT_CERT_PK_OID, + .sn = "TrustedOSFirmwareContentCertPK", + .ln = "Trusted OS Firmware content certificate public key", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = BL32_HASH_OID, + .sn = "TrustedOSHash", + .ln = "Trusted OS (BL32) hash (SHA256)", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = BL33_CONTENT_CERT_PK_OID, + .sn = "NonTrustedFirmwareContentCertPK", + .ln = "Non-Trusted Firmware content certificate public key", + .type = V_ASN1_OCTET_STRING + }, + { + .oid = BL33_HASH_OID, + .sn = "NonTrustedWorldBootloaderHash", + .ln = "Non-Trusted World (BL33) hash (SHA256)", + .type = V_ASN1_OCTET_STRING + }, + { 0, 0, 0, 0 } +}; diff --git a/tools/cert_create/src/tbb_key.c b/tools/cert_create/src/tbb_key.c new file mode 100644 index 00000000..140aeda1 --- /dev/null +++ b/tools/cert_create/src/tbb_key.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tbb_key.h" + +/* + * Keys used to establish the chain of trust + * + * The order of the keys must follow the enumeration specified in tbb_key.h + */ +key_t keys[NUM_KEYS] = { + { + .id = ROT_KEY, + .desc = "Root Of Trust key" + }, + { + .id = TRUSTED_WORLD_KEY, + .desc = "Trusted World key" + }, + { + .id = NON_TRUSTED_WORLD_KEY, + .desc = "Non Trusted World key" + }, + { + .id = BL30_KEY, + .desc = "BL30 key" + }, + { + .id = BL31_KEY, + .desc = "BL31 key" + }, + { + .id = BL32_KEY, + .desc = "BL32 key" + }, + { + .id = BL33_KEY, + .desc = "BL33 key" + } +}; |