diff --git a/Makefile b/Makefile index c33670b..6d3c5cb 100644 --- a/Makefile +++ b/Makefile @@ -73,9 +73,9 @@ # Flags to generate the Chain of Trust GENERATE_COT := 0 CREATE_KEYS := 1 +SAVE_KEYS := 0 # Flags to build TF with Trusted Boot support TRUSTED_BOARD_BOOT := 0 -AUTH_MOD := none # By default, consider that the platform's reset address is not programmable. # The platform Makefile is free to override this value. PROGRAMMABLE_RESET_ADDRESS := 0 @@ -214,6 +214,7 @@ -Iinclude/common \ -Iinclude/drivers \ -Iinclude/drivers/arm \ + -Iinclude/drivers/auth \ -Iinclude/drivers/io \ -Iinclude/drivers/ti/uart \ -Iinclude/lib \ @@ -270,6 +271,7 @@ # Process Generate CoT flags $(eval $(call assert_boolean,GENERATE_COT)) $(eval $(call assert_boolean,CREATE_KEYS)) +$(eval $(call assert_boolean,SAVE_KEYS)) # Process TRUSTED_BOARD_BOOT flag $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT)) @@ -327,28 +329,15 @@ ifneq (${CREATE_KEYS},0) $(eval CRT_ARGS += -n) + ifneq (${SAVE_KEYS},0) + $(eval CRT_ARGS += -k) + endif endif $(eval CRT_ARGS += $(if ${ROT_KEY}, --rot-key ${ROT_KEY})) $(eval CRT_ARGS += $(if ${TRUSTED_WORLD_KEY}, --trusted-world-key ${TRUSTED_WORLD_KEY})) $(eval CRT_ARGS += $(if ${NON_TRUSTED_WORLD_KEY}, --non-trusted-world-key ${NON_TRUSTED_WORLD_KEY})) $(eval CRT_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT}) -endif - -# Check Trusted Board Boot options -ifneq (${TRUSTED_BOARD_BOOT},0) - ifeq (${AUTH_MOD},none) - $(error Error: When TRUSTED_BOARD_BOOT=1, AUTH_MOD has to be the name of a valid authentication module) - else - # We expect to locate an *.mk file under the specified AUTH_MOD directory - AUTH_MAKE := $(shell m="common/auth/${AUTH_MOD}/${AUTH_MOD}.mk"; [ -f "$$m" ] && echo "$$m") - ifeq (${AUTH_MAKE},) - $(error Error: No common/auth/${AUTH_MOD}/${AUTH_MOD}.mk located) - endif - $(info Including ${AUTH_MAKE}) - include ${AUTH_MAKE} - endif - - BL_COMMON_SOURCES += common/auth.c + $(eval CRT_ARGS += $(if ${KEY_ALG}, --key-alg ${KEY_ALG})) endif # Check if -pedantic option should be used @@ -514,7 +503,6 @@ $(eval FIP_ARGS += $(if $4,$(if $5,--bl$(1)-key-cert $(BUILD_PLAT)/bl$(1)_key.crt))) $(eval CRT_DEPS += $(if $4,$(2),)) -$(eval CRT_DEPS += $(if $4,$(if $6,$(6),))) $(eval CRT_ARGS += $(if $4,--bl$(1) $(2))) $(eval CRT_ARGS += $(if $4,$(if $6,--bl$(1)-key $(6)))) $(eval CRT_ARGS += $(if $4,--bl$(1)-cert $(BUILD_PLAT)/bl$(1).crt)) diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S index d682384..df9a799 100644 --- a/bl1/bl1.ld.S +++ b/bl1/bl1.ld.S @@ -51,6 +51,12 @@ *(.text*) *(.rodata*) + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PARSER_LIB_DESCS_START__ = .; + KEEP(*(.img_parser_lib_descs)) + __PARSER_LIB_DESCS_END__ = .; + /* * Ensure 8-byte alignment for cpu_ops so that its fields are also * aligned. Also ensure cpu_ops inclusion. diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c index a7a872c..e322531 100644 --- a/bl1/bl1_main.c +++ b/bl1/bl1_main.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -157,40 +157,20 @@ /* Find out how much free trusted ram remains after BL1 load */ bl1_tzram_layout = bl1_plat_sec_mem_layout(); + INFO("BL1: Loading BL2\n"); + #if TRUSTED_BOARD_BOOT /* Initialize authentication module */ - auth_init(); - - /* - * Load the BL2 certificate into the BL2 region. This region will be - * overwritten by the image, so the authentication module is responsible - * for storing the relevant data from the certificate (keys, hashes, - * etc.) so it can be used later. - */ - err = load_image(bl1_tzram_layout, - BL2_CERT_NAME, - BL2_BASE, - &bl2_image_info, - NULL); - if (err) { - ERROR("Failed to load BL2 certificate.\n"); - panic(); - } - - err = auth_verify_obj(AUTH_BL2_IMG_CERT, bl2_image_info.image_base, - bl2_image_info.image_size); - if (err) { - ERROR("Failed to validate BL2 certificate.\n"); - panic(); - } + auth_mod_init(); #endif /* TRUSTED_BOARD_BOOT */ /* Load the BL2 image */ - err = load_image(bl1_tzram_layout, - BL2_IMAGE_NAME, + err = load_auth_image(bl1_tzram_layout, + BL2_IMAGE_ID, BL2_BASE, &bl2_image_info, &bl2_ep); + if (err) { /* * TODO: print failure to load BL2 but also add a tzwdog timer @@ -200,19 +180,6 @@ panic(); } -#if TRUSTED_BOARD_BOOT - err = auth_verify_obj(AUTH_BL2_IMG, bl2_image_info.image_base, - bl2_image_info.image_size); - if (err) { - ERROR("Failed to validate BL2 image.\n"); - panic(); - } - - /* After working with data, invalidate the data cache */ - inv_dcache_range(bl2_image_info.image_base, - (size_t)bl2_image_info.image_size); -#endif /* TRUSTED_BOARD_BOOT */ - /* * Create a new layout of memory for BL2 as seen by BL1 i.e. * tell it the amount of total and free memory available. diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S index 9933339..33588e6 100644 --- a/bl2/bl2.ld.S +++ b/bl2/bl2.ld.S @@ -50,6 +50,13 @@ *bl2_entrypoint.o(.text*) *(.text*) *(.rodata*) + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PARSER_LIB_DESCS_START__ = .; + KEEP(*(.img_parser_lib_descs)) + __PARSER_LIB_DESCS_END__ = .; + *(.vectors) __RO_END_UNALIGNED__ = .; /* diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index fb79f04..4c19002 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -31,149 +31,14 @@ #include #include #include -#include +#include #include #include #include #include +#include #include "bl2_private.h" -#if TRUSTED_BOARD_BOOT - -#ifdef BL32_BASE -static int bl32_cert_error; -#endif - -/* - * Load and authenticate the key and content certificates for a BL3-x image - * - * Parameters: - * key_cert_blob: key certificate blob id (see auth.h) - * key_cert_name: key certificate filename - * cont_cert_blob: content certificate blob id (see auth.h) - * cont_cert_name: content certificate filename - * mem_layout: Trusted SRAM memory layout - * load_addr: load the certificates at this address - * - * Return: 0 = success, Otherwise = error - */ -static int load_cert_bl3x(int key_cert_blob, const char *key_cert_name, - int cont_cert_blob, const char *cont_cert_name, - meminfo_t *mem_layout, uint64_t load_addr) -{ - image_info_t image_info; - int err; - - /* Load Key certificate */ - image_info.h.version = VERSION_1; - err = load_image(mem_layout, key_cert_name, load_addr, &image_info, NULL); - if (err) { - ERROR("Cannot load %s.\n", key_cert_name); - return err; - } - - err = auth_verify_obj(key_cert_blob, image_info.image_base, - image_info.image_size); - if (err) { - ERROR("Invalid key certificate %s.\n", key_cert_name); - return err; - } - - /* Load Content certificate */ - image_info.h.version = VERSION_1; - err = load_image(mem_layout, cont_cert_name, load_addr, &image_info, NULL); - if (err) { - ERROR("Cannot load %s.\n", cont_cert_name); - return err; - } - - err = auth_verify_obj(cont_cert_blob, image_info.image_base, - image_info.image_size); - if (err) { - ERROR("Invalid content certificate %s.\n", cont_cert_name); - return err; - } - - return 0; -} - -/* - * Load and authenticate the Trusted Key certificate the key and content - * certificates for each of the BL3-x images. - * - * Return: 0 = success, Otherwise = error - */ -static int load_certs(void) -{ - const uint64_t load_addr = BL31_BASE; - image_info_t image_info; - meminfo_t *mem_layout; - int err; - - /* Find out how much free trusted ram remains after BL2 load */ - mem_layout = bl2_plat_sec_mem_layout(); - - /* Load the Trusted Key certificate in the BL31 region */ - image_info.h.version = VERSION_1; - err = load_image(mem_layout, TRUSTED_KEY_CERT_NAME, load_addr, - &image_info, NULL); - if (err) { - ERROR("Failed to load Trusted Key certificate.\n"); - return err; - } - - /* Validate the certificate */ - err = auth_verify_obj(AUTH_TRUSTED_KEY_CERT, image_info.image_base, - image_info.image_size); - if (err) { - ERROR("Invalid Trusted Key certificate.\n"); - return err; - } - - /* Load and validate Key and Content certificates for BL3-x images */ -#ifdef BL30_BASE - err = load_cert_bl3x(AUTH_BL30_KEY_CERT, BL30_KEY_CERT_NAME, - AUTH_BL30_IMG_CERT, BL30_CERT_NAME, - mem_layout, load_addr); - if (err) { - ERROR("Failed to verify BL3-0 authenticity\n"); - return err; - } -#endif /* BL30_BASE */ - - err = load_cert_bl3x(AUTH_BL31_KEY_CERT, BL31_KEY_CERT_NAME, - AUTH_BL31_IMG_CERT, BL31_CERT_NAME, - mem_layout, load_addr); - if (err) { - ERROR("Failed to verify BL3-1 authenticity\n"); - return err; - } - -#ifdef BL32_BASE - /* BL3-2 image is optional, but keep the return value in case the - * image is present but the certificate is missing */ - err = load_cert_bl3x(AUTH_BL32_KEY_CERT, BL32_KEY_CERT_NAME, - AUTH_BL32_IMG_CERT, BL32_CERT_NAME, - mem_layout, load_addr); - if (err) { - WARN("Failed to verify BL3-2 authenticity\n"); - } - bl32_cert_error = err; -#endif /* BL32_BASE */ - - err = load_cert_bl3x(AUTH_BL33_KEY_CERT, BL33_KEY_CERT_NAME, - AUTH_BL33_IMG_CERT, BL33_CERT_NAME, - mem_layout, load_addr); - if (err) { - ERROR("Failed to verify BL3-3 authenticity\n"); - return err; - } - - return 0; -} - -#endif /* TRUSTED_BOARD_BOOT */ - /******************************************************************************* * Load the BL3-0 image if there's one. * If a platform does not want to attempt to load BL3-0 image it must leave @@ -199,34 +64,18 @@ INFO("BL2: Loading BL3-0\n"); bl2_plat_get_bl30_meminfo(&bl30_mem_info); bl30_image_info.h.version = VERSION_1; - e = load_image(&bl30_mem_info, - BL30_IMAGE_NAME, - BL30_BASE, - &bl30_image_info, - NULL); + e = load_auth_image(&bl30_mem_info, + BL30_IMAGE_ID, + BL30_BASE, + &bl30_image_info, + NULL); - if (e) - return e; - -#if TRUSTED_BOARD_BOOT - e = auth_verify_obj(AUTH_BL30_IMG, - bl30_image_info.image_base, - bl30_image_info.image_size); - if (e) { - ERROR("Failed to authenticate BL3-0 image.\n"); - return e; - } - - /* After working with data, invalidate the data cache */ - inv_dcache_range(bl30_image_info.image_base, - (size_t)bl30_image_info.image_size); -#endif /* TRUSTED_BOARD_BOOT */ - - /* The subsequent handling of BL3-0 is platform specific */ - e = bl2_plat_handle_bl30(&bl30_image_info); - if (e) { - ERROR("Failure in platform-specific handling of BL3-0 image.\n"); - return e; + if (e == 0) { + /* The subsequent handling of BL3-0 is platform specific */ + e = bl2_plat_handle_bl30(&bl30_image_info); + if (e) { + ERROR("Failure in platform-specific handling of BL3-0 image.\n"); + } } #endif /* BL30_BASE */ @@ -256,31 +105,17 @@ bl31_ep_info->args.arg0 = (unsigned long)bl2_to_bl31_params; /* Load the BL3-1 image */ - e = load_image(bl2_tzram_layout, - BL31_IMAGE_NAME, - BL31_BASE, - bl2_to_bl31_params->bl31_image_info, - bl31_ep_info); - if (e) - return e; + e = load_auth_image(bl2_tzram_layout, + BL31_IMAGE_ID, + BL31_BASE, + bl2_to_bl31_params->bl31_image_info, + bl31_ep_info); -#if TRUSTED_BOARD_BOOT - e = auth_verify_obj(AUTH_BL31_IMG, - bl2_to_bl31_params->bl31_image_info->image_base, - bl2_to_bl31_params->bl31_image_info->image_size); - if (e) { - ERROR("Failed to authenticate BL3-1 image.\n"); - return e; + if (e == 0) { + bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info, + bl31_ep_info); } - /* After working with data, invalidate the data cache */ - inv_dcache_range(bl2_to_bl31_params->bl31_image_info->image_base, - (size_t)bl2_to_bl31_params->bl31_image_info->image_size); -#endif /* TRUSTED_BOARD_BOOT */ - - bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info, - bl31_ep_info); - return e; } @@ -308,37 +143,17 @@ * completely different memory. */ bl2_plat_get_bl32_meminfo(&bl32_mem_info); - e = load_image(&bl32_mem_info, - BL32_IMAGE_NAME, - BL32_BASE, - bl2_to_bl31_params->bl32_image_info, - bl2_to_bl31_params->bl32_ep_info); + e = load_auth_image(&bl32_mem_info, + BL32_IMAGE_ID, + BL32_BASE, + bl2_to_bl31_params->bl32_image_info, + bl2_to_bl31_params->bl32_ep_info); - if (e) - return e; - -#if TRUSTED_BOARD_BOOT - /* Image is present. Check if there is a valid certificate */ - if (bl32_cert_error) { - ERROR("Failed to authenticate BL3-2 certificates.\n"); - return bl32_cert_error; + if (e == 0) { + bl2_plat_set_bl32_ep_info( + bl2_to_bl31_params->bl32_image_info, + bl2_to_bl31_params->bl32_ep_info); } - - e = auth_verify_obj(AUTH_BL32_IMG, - bl2_to_bl31_params->bl32_image_info->image_base, - bl2_to_bl31_params->bl32_image_info->image_size); - if (e) { - ERROR("Failed to authenticate BL3-2 image.\n"); - return e; - } - /* After working with data, invalidate the data cache */ - inv_dcache_range(bl2_to_bl31_params->bl32_image_info->image_base, - (size_t)bl2_to_bl31_params->bl32_image_info->image_size); -#endif /* TRUSTED_BOARD_BOOT */ - - bl2_plat_set_bl32_ep_info( - bl2_to_bl31_params->bl32_image_info, - bl2_to_bl31_params->bl32_ep_info); #endif /* BL32_BASE */ return e; @@ -361,30 +176,16 @@ bl2_plat_get_bl33_meminfo(&bl33_mem_info); /* Load the BL3-3 image in non-secure memory provided by the platform */ - e = load_image(&bl33_mem_info, - BL33_IMAGE_NAME, - plat_get_ns_image_entrypoint(), - bl2_to_bl31_params->bl33_image_info, - bl2_to_bl31_params->bl33_ep_info); + e = load_auth_image(&bl33_mem_info, + BL33_IMAGE_ID, + plat_get_ns_image_entrypoint(), + bl2_to_bl31_params->bl33_image_info, + bl2_to_bl31_params->bl33_ep_info); - if (e) - return e; - -#if TRUSTED_BOARD_BOOT - e = auth_verify_obj(AUTH_BL33_IMG, - bl2_to_bl31_params->bl33_image_info->image_base, - bl2_to_bl31_params->bl33_image_info->image_size); - if (e) { - ERROR("Failed to authenticate BL3-3 image.\n"); - return e; + if (e == 0) { + bl2_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info, + bl2_to_bl31_params->bl33_ep_info); } - /* After working with data, invalidate the data cache */ - inv_dcache_range(bl2_to_bl31_params->bl33_image_info->image_base, - (size_t)bl2_to_bl31_params->bl33_image_info->image_size); -#endif /* TRUSTED_BOARD_BOOT */ - - bl2_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info, - bl2_to_bl31_params->bl33_ep_info); return e; } @@ -408,14 +209,7 @@ #if TRUSTED_BOARD_BOOT /* Initialize authentication module */ - auth_init(); - - /* Validate the certificates involved in the Chain of Trust */ - e = load_certs(); - if (e) { - ERROR("Chain of Trust invalid. Aborting...\n"); - panic(); - } + auth_mod_init(); #endif /* TRUSTED_BOARD_BOOT */ /* diff --git a/common/auth.c b/common/auth.c deleted file mode 100644 index 37234b8..0000000 --- a/common/auth.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 -#include -#include - -/* - * Initialize the authentication module - */ -void auth_init(void) -{ - assert(auth_mod.name); - assert(auth_mod.init); - assert(auth_mod.verify); - - INFO("Using authentication module '%s'\n", auth_mod.name); - if (auth_mod.init() != 0) - assert(0); -} - -/* - * Authenticate a certificate/image - * - * Return: 0 = success, Otherwise = error - */ -int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len) -{ - assert(obj_id < AUTH_NUM_OBJ); - assert(obj_buf != 0); - assert(auth_mod.verify); - - return auth_mod.verify(obj_id, obj_buf, len); -} diff --git a/common/auth/polarssl/polarssl.c b/common/auth/polarssl/polarssl.c deleted file mode 100644 index e099f50..0000000 --- a/common/auth/polarssl/polarssl.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * 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. - */ - -/* Authentication module based on PolarSSL */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * At each authentication stage, the module is responsible for extracting and - * storing those elements (keys, hashes, etc.) that will be needed later on - * during the Trusted Boot process. - */ - -/* SHA256 algorithm */ -#define SHA_BYTES 32 - -/* - * An 8 KB stack has been proven to be enough for the current Trusted Boot - * process - */ -#define POLARSSL_HEAP_SIZE (8*1024) -static unsigned char heap[POLARSSL_HEAP_SIZE]; - -/* - * RSA public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 9 (rsa oid) - * + 1 + 1 (params null) - * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) - * RSAPublicKey ::= SEQUENCE { 1 + 3 - * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 - * } - * - * POLARSSL_MPI_MAX_SIZE is set to 256 bytes (RSA-2048 bit keys) in the - * configuration file - */ -#define RSA_PUB_DER_MAX_BYTES 38 + 2 * POLARSSL_MPI_MAX_SIZE - -/* - * Buffer for storing public keys extracted from certificates while they are - * verified - */ -static unsigned char pk_buf[RSA_PUB_DER_MAX_BYTES]; - -/* We use this variable to parse and authenticate the certificates */ -static x509_crt cert; - -/* BL specific variables */ -#if IMAGE_BL1 -static unsigned char sha_bl2[SHA_BYTES]; -#elif IMAGE_BL2 -/* Buffers to store the hash of BL3-x images */ -static unsigned char sha_bl30[SHA_BYTES]; -static unsigned char sha_bl31[SHA_BYTES]; -static unsigned char sha_bl32[SHA_BYTES]; -static unsigned char sha_bl33[SHA_BYTES]; -/* Buffers to store the Trusted and Non-Trusted world public keys */ -static unsigned char tz_world_pk[RSA_PUB_DER_MAX_BYTES]; -static unsigned char ntz_world_pk[RSA_PUB_DER_MAX_BYTES]; -static size_t tz_world_pk_len, ntz_world_pk_len; -/* Buffer to store the BL3-x public keys */ -static unsigned char content_pk[RSA_PUB_DER_MAX_BYTES]; -static size_t content_pk_len; -#endif - - -static int x509_get_crt_ext_data(const unsigned char **ext_data, - size_t *ext_len, - x509_crt *crt, - const char *oid) -{ - int ret; - size_t len; - unsigned char *end_ext_data, *end_ext_octet; - unsigned char *p; - const unsigned char *end; - char oid_str[64]; - - p = crt->v3_ext.p; - end = crt->v3_ext.p + crt->v3_ext.len; - - ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); - if (ret != 0) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret; - - if (end != p + len) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH; - - while (p < end) { - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - x509_buf extn_oid = {0, 0, NULL}; - int is_critical = 0; /* DEFAULT FALSE */ - - ret = asn1_get_tag(&p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE); - if (ret != 0) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret; - - end_ext_data = p + len; - - /* Get extension ID */ - extn_oid.tag = *p; - - ret = asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID); - if (ret != 0) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret; - - extn_oid.p = p; - p += extn_oid.len; - - if ((end - p) < 1) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_OUT_OF_DATA; - - /* Get optional critical */ - ret = asn1_get_bool(&p, end_ext_data, &is_critical); - if (ret != 0 && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG)) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret; - - /* Data should be octet string type */ - ret = asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING); - if (ret != 0) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret; - - end_ext_octet = p + len; - - if (end_ext_octet != end_ext_data) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH; - - /* Detect requested extension */ - oid_get_numeric_string(oid_str, 64, &extn_oid); - if (memcmp(oid, oid_str, sizeof(oid)) == 0) { - *ext_data = p; - *ext_len = len; - return 0; - } - - /* Next */ - p = end_ext_octet; - } - - if (p != end) - return POLARSSL_ERR_X509_INVALID_EXTENSIONS + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH; - - return POLARSSL_ERR_X509_UNKNOWN_OID; -} - -#if IMAGE_BL1 -/* - * Parse and verify the BL2 certificate - * - * This function verifies the integrity of the BL2 certificate, checks that it - * has been signed with the ROT key and extracts the BL2 hash stored in the - * certificate so it can be matched later against the calculated hash. - * - * Return: 0 = success, Otherwise = error - */ -static int check_bl2_cert(unsigned char *buf, size_t len) -{ - const unsigned char *p; - size_t sz; - int err, flags; - - x509_crt_init(&cert); - - /* Parse the BL2 certificate */ - err = x509_crt_parse(&cert, buf, len); - if (err) { - ERROR("BL2 certificate parse error %d.\n", err); - goto error; - } - - /* Check that it has been signed with the ROT key */ - err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf)); - if (err < 0) { - ERROR("Error loading ROT key in DER format %d.\n", err); - goto error; - } - - sz = (size_t)err; - p = pk_buf + sizeof(pk_buf) - sz; - - err = plat_match_rotpk(p, sz); - if (err) { - ERROR("ROT and BL2 certificate key mismatch\n"); - goto error; - } - - /* Verify certificate */ - err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL); - if (err) { - ERROR("BL2 certificate verification error %d. Flags: 0x%x.\n", - err, flags); - goto error; - } - - /* Extract BL2 image hash from certificate */ - err = x509_get_crt_ext_data(&p, &sz, &cert, BL2_HASH_OID); - if (err) { - ERROR("Cannot read BL2 hash from certificate\n"); - goto error; - } - - assert(sz == SHA_BYTES + 2); - - /* Skip the tag and length bytes and copy the hash */ - p += 2; - memcpy(sha_bl2, p, SHA_BYTES); - -error: - x509_crt_free(&cert); - - return err; -} -#endif /* IMAGE_BL1 */ - -#if IMAGE_BL2 -static int check_trusted_key_cert(unsigned char *buf, size_t len) -{ - const unsigned char *p; - size_t sz; - int err, flags; - - x509_crt_init(&cert); - - /* Parse the Trusted Key certificate */ - err = x509_crt_parse(&cert, buf, len); - if (err) { - ERROR("Trusted Key certificate parse error %d.\n", err); - goto error; - } - - /* Verify Trusted Key certificate */ - err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL); - if (err) { - ERROR("Trusted Key certificate verification error %d. Flags: " - "0x%x.\n", err, flags); - goto error; - } - - /* Check that it has been signed with the ROT key */ - err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf)); - if (err < 0) { - ERROR("Error loading ROT key in DER format %d.\n", err); - goto error; - } - - sz = (size_t)err; - p = pk_buf + sizeof(pk_buf) - sz; - - if (plat_match_rotpk(p, sz)) { - ERROR("ROT and Trusted Key certificate key mismatch\n"); - goto error; - } - - /* Extract Trusted World key from extensions */ - err = x509_get_crt_ext_data(&p, &tz_world_pk_len, - &cert, TZ_WORLD_PK_OID); - if (err) { - ERROR("Cannot read Trusted World key\n"); - goto error; - } - - assert(tz_world_pk_len <= RSA_PUB_DER_MAX_BYTES); - memcpy(tz_world_pk, p, tz_world_pk_len); - - /* Extract Non-Trusted World key from extensions */ - err = x509_get_crt_ext_data(&p, &ntz_world_pk_len, - &cert, NTZ_WORLD_PK_OID); - if (err) { - ERROR("Cannot read Non-Trusted World key\n"); - goto error; - } - - assert(tz_world_pk_len <= RSA_PUB_DER_MAX_BYTES); - memcpy(ntz_world_pk, p, ntz_world_pk_len); - -error: - x509_crt_free(&cert); - - return err; -} - -static int check_bl3x_key_cert(const unsigned char *buf, size_t len, - const unsigned char *i_key, size_t i_key_len, - unsigned char *s_key, size_t *s_key_len, - const char *key_oid) -{ - const unsigned char *p; - size_t sz; - int err, flags; - - x509_crt_init(&cert); - - /* Parse key certificate */ - err = x509_crt_parse(&cert, buf, len); - if (err) { - ERROR("Key certificate parse error %d.\n", err); - goto error; - } - - /* Verify certificate */ - err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL); - if (err) { - ERROR("Key certificate verification error %d. Flags: " - "0x%x.\n", err, flags); - goto error; - } - - /* Check that the certificate has been signed by the issuer */ - err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf)); - if (err < 0) { - ERROR("Error loading key in DER format %d.\n", err); - goto error; - } - - sz = (size_t)err; - p = pk_buf + sizeof(pk_buf) - sz; - if ((sz != i_key_len) || memcmp(p, i_key, sz)) { - ERROR("Key certificate not signed with issuer key\n"); - err = 1; - goto error; - } - - /* Get the content certificate key */ - err = x509_get_crt_ext_data(&p, &sz, &cert, key_oid); - if (err) { - ERROR("Extension %s not found in Key certificate\n", key_oid); - goto error; - } - - assert(sz <= RSA_PUB_DER_MAX_BYTES); - memcpy(s_key, p, sz); - *s_key_len = sz; - -error: - x509_crt_free(&cert); - - return err; -} - -static int check_bl3x_cert(unsigned char *buf, size_t len, - const unsigned char *i_key, size_t i_key_len, - const char *hash_oid, unsigned char *sha) -{ - const unsigned char *p; - size_t sz; - int err, flags; - - x509_crt_init(&cert); - - /* Parse BL31 content certificate */ - err = x509_crt_parse(&cert, buf, len); - if (err) { - ERROR("Content certificate parse error %d.\n", err); - goto error; - } - - /* Verify certificate */ - err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL); - if (err) { - ERROR("Content certificate verification error %d. Flags: " - "0x%x.\n", err, flags); - goto error; - } - - /* Check that content certificate has been signed with the content - * certificate key corresponding to this image */ - sz = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf)); - p = pk_buf + sizeof(pk_buf) - sz; - - if ((sz != i_key_len) || memcmp(p, i_key, sz)) { - ERROR("Content certificate not signed with content " - "certificate key\n"); - err = 1; - goto error; - } - - /* Extract image hash from certificate */ - err = x509_get_crt_ext_data(&p, &sz, &cert, hash_oid); - if (err) { - ERROR("Cannot read hash from certificate\n"); - goto error; - } - - assert(sz == SHA_BYTES + 2); - - /* Skip the tag and length bytes and copy the hash */ - p += 2; - memcpy(sha, p, SHA_BYTES); - -error: - x509_crt_free(&cert); - - return err; -} -#endif /* IMAGE_BL2 */ - -/* - * Calculate the hash of the image and check it against the hash extracted - * previously from the certificate - * - * Parameters: - * buf: buffer where image is loaded - * len: size of the image - * sha: matching hash (extracted from the image certificate) - * - * Return: 0 = match, Otherwise = mismatch - */ -static int check_bl_img(unsigned char *buf, size_t len, - const unsigned char *sha) -{ - unsigned char img_sha[SHA_BYTES]; - - /* Calculate the hash of the image */ - sha256(buf, len, img_sha, 0); - - /* Match the hash with the one extracted from the certificate */ - if (memcmp(img_sha, sha, SHA_BYTES)) { - ERROR("Image hash mismatch\n"); - return 1; - } - - return 0; -} - -/* - * Object verification function - * - * The id parameter will indicate the expected format of the object - * (certificate, image, etc). - * - * Return: 0 = success, Otherwise = error - */ -static int polarssl_mod_verify(unsigned int id, uintptr_t obj, size_t len) -{ - int ret; - - switch (id) { -#if IMAGE_BL1 - case AUTH_BL2_IMG_CERT: - ret = check_bl2_cert((unsigned char *)obj, len); - break; - case AUTH_BL2_IMG: - ret = check_bl_img((unsigned char *)obj, len, sha_bl2); - break; -#endif /* IMAGE_BL1 */ - -#if IMAGE_BL2 - case AUTH_TRUSTED_KEY_CERT: - ret = check_trusted_key_cert((unsigned char *)obj, len); - break; - case AUTH_BL30_KEY_CERT: - ret = check_bl3x_key_cert((unsigned char *)obj, len, - tz_world_pk, tz_world_pk_len, - content_pk, &content_pk_len, - BL30_CONTENT_CERT_PK_OID); - break; - case AUTH_BL31_KEY_CERT: - ret = check_bl3x_key_cert((unsigned char *)obj, len, - tz_world_pk, tz_world_pk_len, - content_pk, &content_pk_len, - BL31_CONTENT_CERT_PK_OID); - break; - case AUTH_BL32_KEY_CERT: - ret = check_bl3x_key_cert((unsigned char *)obj, len, - tz_world_pk, tz_world_pk_len, - content_pk, &content_pk_len, - BL32_CONTENT_CERT_PK_OID); - break; - case AUTH_BL33_KEY_CERT: - ret = check_bl3x_key_cert((unsigned char *)obj, len, - ntz_world_pk, ntz_world_pk_len, - content_pk, &content_pk_len, - BL33_CONTENT_CERT_PK_OID); - break; - case AUTH_BL30_IMG_CERT: - ret = check_bl3x_cert((unsigned char *)obj, len, - content_pk, content_pk_len, - BL30_HASH_OID, sha_bl30); - break; - case AUTH_BL31_IMG_CERT: - ret = check_bl3x_cert((unsigned char *)obj, len, - content_pk, content_pk_len, - BL31_HASH_OID, sha_bl31); - break; - case AUTH_BL32_IMG_CERT: - ret = check_bl3x_cert((unsigned char *)obj, len, - content_pk, content_pk_len, - BL32_HASH_OID, sha_bl32); - break; - case AUTH_BL33_IMG_CERT: - ret = check_bl3x_cert((unsigned char *)obj, len, - content_pk, content_pk_len, - BL33_HASH_OID, sha_bl33); - break; - case AUTH_BL30_IMG: - ret = check_bl_img((unsigned char *)obj, len, sha_bl30); - break; - case AUTH_BL31_IMG: - ret = check_bl_img((unsigned char *)obj, len, sha_bl31); - break; - case AUTH_BL32_IMG: - ret = check_bl_img((unsigned char *)obj, len, sha_bl32); - break; - case AUTH_BL33_IMG: - ret = check_bl_img((unsigned char *)obj, len, sha_bl33); - break; -#endif /* IMAGE_BL2 */ - default: - ret = -1; - break; - } - - return ret; -} - -/* - * Module initialization function - * - * Return: 0 = success, Otherwise = error - */ -static int polarssl_mod_init(void) -{ - /* Initialize the PolarSSL heap */ - return memory_buffer_alloc_init(heap, POLARSSL_HEAP_SIZE); -} - -const auth_mod_t auth_mod = { - .name = "PolarSSL", - .init = polarssl_mod_init, - .verify = polarssl_mod_verify -}; diff --git a/common/auth/polarssl/polarssl.mk b/common/auth/polarssl/polarssl.mk deleted file mode 100644 index 69c741f..0000000 --- a/common/auth/polarssl/polarssl.mk +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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. -# - -# POLARSSL_DIR must be set to the PolarSSL main directory (it must contain -# the 'include' and 'library' subdirectories). -ifeq (${POLARSSL_DIR},) - $(error Error: POLARSSL_DIR not set) -endif - -INCLUDES += -I${POLARSSL_DIR}/include \ - -Icommon/auth/polarssl - -POLARSSL_CONFIG_FILE := "" -$(eval $(call add_define,POLARSSL_CONFIG_FILE)) - -POLARSSL_SOURCES := $(addprefix ${POLARSSL_DIR}/library/, \ - asn1parse.c \ - asn1write.c \ - bignum.c \ - md.c \ - md_wrap.c \ - memory_buffer_alloc.c \ - oid.c \ - pk.c \ - pk_wrap.c \ - pkparse.c \ - pkwrite.c \ - platform.c \ - rsa.c \ - sha256.c \ - x509.c \ - x509_crt.c \ - ) - -BL1_SOURCES += ${POLARSSL_SOURCES} \ - common/auth/polarssl/polarssl.c - -BL2_SOURCES += ${POLARSSL_SOURCES} \ - common/auth/polarssl/polarssl.c - -DISABLE_PEDANTIC := 1 diff --git a/common/auth/polarssl/polarssl_config.h b/common/auth/polarssl/polarssl_config.h deleted file mode 100644 index b419bf9..0000000 --- a/common/auth/polarssl/polarssl_config.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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. - */ -#ifndef __POLARSSL_CONFIG_H__ -#define __POLARSSL_CONFIG_H__ - - -/* - * Configuration file to build PolarSSL with the required features for - * Trusted Boot - */ - -#define POLARSSL_PLATFORM_MEMORY -#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS - -#define POLARSSL_PKCS1_V15 -#define POLARSSL_PKCS1_V21 - -#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -#define POLARSSL_X509_CHECK_KEY_USAGE -#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE - -#define POLARSSL_ASN1_PARSE_C -#define POLARSSL_ASN1_WRITE_C - -#define POLARSSL_BASE64_C -#define POLARSSL_BIGNUM_C - -#define POLARSSL_ERROR_C -#define POLARSSL_MD_C - -#define POLARSSL_MEMORY_BUFFER_ALLOC_C -#define POLARSSL_OID_C - -#define POLARSSL_PK_C -#define POLARSSL_PK_PARSE_C -#define POLARSSL_PK_WRITE_C - -#define POLARSSL_PLATFORM_C - -#define POLARSSL_RSA_C -#define POLARSSL_SHA256_C - -#define POLARSSL_VERSION_C - -#define POLARSSL_X509_USE_C -#define POLARSSL_X509_CRT_PARSE_C - -/* MPI / BIGNUM options */ -#define POLARSSL_MPI_WINDOW_SIZE 2 -#define POLARSSL_MPI_MAX_SIZE 256 - -/* Memory buffer allocator options */ -#define POLARSSL_MEMORY_ALIGN_MULTIPLE 8 - -#include "polarssl/check_config.h" - -#endif /* __POLARSSL_CONFIG_H__ */ diff --git a/common/bl_common.c b/common/bl_common.c index b9cc0f2..b8558a6 100644 --- a/common/bl_common.c +++ b/common/bl_common.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -156,7 +157,7 @@ } /* Generic function to return the size of an image */ -unsigned long image_size(const char *image_name) +unsigned long image_size(unsigned int image_id) { uintptr_t dev_handle; uintptr_t image_handle; @@ -164,29 +165,27 @@ size_t image_size = 0; int io_result = IO_FAIL; - assert(image_name != NULL); - /* Obtain a reference to the image by querying the platform layer */ - io_result = plat_get_image_source(image_name, &dev_handle, &image_spec); + io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); if (io_result != IO_SUCCESS) { - WARN("Failed to obtain reference to image '%s' (%i)\n", - image_name, io_result); + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, io_result); return 0; } /* Attempt to access the image */ io_result = io_open(dev_handle, image_spec, &image_handle); if (io_result != IO_SUCCESS) { - WARN("Failed to access image '%s' (%i)\n", - image_name, io_result); + WARN("Failed to access image id=%u (%i)\n", + image_id, io_result); return 0; } /* Find the size of the image */ io_result = io_size(image_handle, &image_size); if ((io_result != IO_SUCCESS) || (image_size == 0)) { - WARN("Failed to determine the size of the image '%s' file (%i)\n", - image_name, io_result); + WARN("Failed to determine the size of the image id=%u (%i)\n", + image_id, io_result); } io_result = io_close(image_handle); /* Ignore improbable/unrecoverable error in 'close' */ @@ -210,8 +209,8 @@ * Returns 0 on success, a negative error code otherwise. ******************************************************************************/ int load_image(meminfo_t *mem_layout, - const char *image_name, - uint64_t image_base, + unsigned int image_id, + uintptr_t image_base, image_info_t *image_data, entry_point_info_t *entry_point_info) { @@ -223,33 +222,32 @@ int io_result = IO_FAIL; assert(mem_layout != NULL); - assert(image_name != NULL); assert(image_data != NULL); assert(image_data->h.version >= VERSION_1); /* Obtain a reference to the image by querying the platform layer */ - io_result = plat_get_image_source(image_name, &dev_handle, &image_spec); + io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); if (io_result != IO_SUCCESS) { - WARN("Failed to obtain reference to image '%s' (%i)\n", - image_name, io_result); + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, io_result); return io_result; } /* Attempt to access the image */ io_result = io_open(dev_handle, image_spec, &image_handle); if (io_result != IO_SUCCESS) { - WARN("Failed to access image '%s' (%i)\n", - image_name, io_result); + WARN("Failed to access image id=%u (%i)\n", + image_id, io_result); return io_result; } - INFO("Loading file '%s' at address 0x%lx\n", image_name, image_base); + INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base); /* Find the size of the image */ io_result = io_size(image_handle, &image_size); if ((io_result != IO_SUCCESS) || (image_size == 0)) { - WARN("Failed to determine the size of the image '%s' file (%i)\n", - image_name, io_result); + WARN("Failed to determine the size of the image id=%u (%i)\n", + image_id, io_result); goto exit; } @@ -267,7 +265,7 @@ /* TODO: Consider whether to try to recover/retry a partially successful read */ io_result = io_read(image_handle, image_base, image_size, &bytes_read); if ((io_result != IO_SUCCESS) || (bytes_read < image_size)) { - WARN("Failed to load '%s' file (%i)\n", image_name, io_result); + WARN("Failed to load image id=%u (%i)\n", image_id, io_result); goto exit; } @@ -298,7 +296,7 @@ */ flush_dcache_range(image_base, image_size); - INFO("File '%s' loaded: 0x%lx - 0x%lx\n", image_name, image_base, + INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base, image_base + image_size); exit: @@ -311,3 +309,54 @@ return io_result; } + +/******************************************************************************* + * Generic function to load and authenticate an image. The image is actually + * loaded by calling the 'load_image()' function. In addition, this function + * uses recursion to authenticate the parent images up to the root of trust. + ******************************************************************************/ +int load_auth_image(meminfo_t *mem_layout, + unsigned int image_id, + uintptr_t image_base, + image_info_t *image_data, + entry_point_info_t *entry_point_info) +{ + int rc; + +#if TRUSTED_BOARD_BOOT + unsigned int parent_id; + + /* Use recursion to authenticate parent images */ + rc = auth_mod_get_parent_id(image_id, &parent_id); + if (rc == 0) { + rc = load_auth_image(mem_layout, parent_id, image_base, + image_data, NULL); + if (rc != IO_SUCCESS) { + return rc; + } + } +#endif /* TRUSTED_BOARD_BOOT */ + + /* Load the image */ + rc = load_image(mem_layout, image_id, image_base, image_data, + entry_point_info); + if (rc != IO_SUCCESS) { + return rc; + } + +#if TRUSTED_BOARD_BOOT + /* Authenticate it */ + rc = auth_mod_verify_img(image_id, + (void *)image_data->image_base, + image_data->image_size); + if (rc != 0) { + return IO_FAIL; + } + + /* After working with data, invalidate the data cache */ + inv_dcache_range(image_data->image_base, + (size_t)image_data->image_size); +#endif /* TRUSTED_BOARD_BOOT */ + + return IO_SUCCESS; +} diff --git a/docs/auth-framework.md b/docs/auth-framework.md new file mode 100644 index 0000000..488fa26 --- /dev/null +++ b/docs/auth-framework.md @@ -0,0 +1,918 @@ +Abstracting a Chain of Trust +============================ + +Contents : + +1. [Introduction](#1--introduction) +2. [Framework design](#2--framework-design) +3. [Specifying a Chain of Trust](#3--specifying-a-chain-of-trust) +4. [Implementation example](#4--implementation-example) + + +1. Introduction +---------------- + +The aim of this document is to describe the authentication framework implemented +in the Trusted Firmware. This framework fulfills the following requirements: + +1. It should be possible for a platform port to specify the Chain of Trust in + terms of certificate hierarchy and the mechanisms used to verify a + particular image/certificate. + +2. The framework should distinguish between: + + - The mechanism used to encode and transport information, e.g. DER encoded + X.509v3 certificates to ferry Subject Public Keys, hashes and non-volatile + counters. + + - The mechanism used to verify the transported information i.e. the + cryptographic libraries. + +The framework has been designed following a modular approach illustrated in the +next diagram: + +``` + +---------------+---------------+------------+ + | Trusted | Trusted | Trusted | + | Firmware | Firmware | Firmware | + | Generic | IO Framework | Platform | + | Code i.e. | (IO) | Port | + | BL1/BL2 (GEN) | | (PP) | + +---------------+---------------+------------+ + ^ ^ ^ + | | | + v v v + +-----------+ +-----------+ +-----------+ + | | | | | Image | + | Crypto | | Auth | | Parser | + | Module |<->| Module |<->| Module | + | (CM) | | (AM) | | (IPM) | + | | | | | | + +-----------+ +-----------+ +-----------+ + ^ ^ + | | + v v + +----------------+ +-----------------+ + | Cryptographic | | Image Parser | + | Libraries (CL) | | Libraries (IPL) | + +----------------+ +-----------------+ + | | + | | + | | + v v + +-----------------+ + | Misc. Libs e.g. | + | ASN.1 decoder | + | | + +-----------------+ + + DIAGRAM 1. +``` + +This document describes the inner details of the authentication framework and +the abstraction mechanisms available to specify a Chain of Trust. + + +2. Framework design +-------------------- + +This section describes some aspects of the framework design and the rationale +behind them. These aspects are key to verify a Chain of Trust. + +### 2.1 Chain of Trust + +A CoT is basically a sequence of authentication images which usually starts with +a root of trust and culminates in a single data image. The following diagram +illustrates how this maps to a CoT for the BL3-1 image described in the +TBBR-Client specification. + +``` + +------------------+ +-------------------+ + | ROTPK/ROTPK Hash |------>| Trusted Key | + +------------------+ | Certificate | + | (Auth Image) | + /+-------------------+ + / | + / | + / | + / | + L v + +------------------+ +-------------------+ + | Trusted World |------>| BL3-1 Key | + | Public Key | | Certificate | + +------------------+ | (Auth Image) | + +-------------------+ + / | + / | + / | + / | + / v + +------------------+ L +-------------------+ + | BL3-1 Content |------>| BL3-1 Content | + | Certificate PK | | Certificate | + +------------------+ | (Auth Image) | + +-------------------+ + / | + / | + / | + / | + / v + +------------------+ L +-------------------+ + | BL3-1 Hash |------>| BL3-1 Image | + | | | (Data Image) | + +------------------+ | | + +-------------------+ + + DIAGRAM 2. +``` + +The root of trust is usually a public key (ROTPK) that has been burnt in the +platform and cannot be modified. + +### 2.2 Image types + +Images in a CoT are categorised as authentication and data images. An +authentication image contains information to authenticate a data image or +another authentication image. A data image is usually a boot loader binary, but +it could be any other data that requires authentication. + +### 2.3 Component responsibilities + +For every image in a Chain of Trust, the following high level operations are +performed to verify it: + +1. Allocate memory for the image either statically or at runtime. + +2. Identify the image and load it in the allocated memory. + +3. Check the integrity of the image as per its type. + +4. Authenticate the image as per the cryptographic algorithms used. + +5. If the image is an authentication image, extract the information that will + be used to authenticate the next image in the CoT. + +In Diagram 1, each component is responsible for one or more of these operations. +The responsibilities are briefly described below. + + +#### 2.2.1 TF Generic code and IO framework (GEN/IO) + +These components are responsible for initiating the authentication process for a +particular image in BL1 or BL2. For each BL image that requires authentication, +the Generic code asks recursively the Authentication module what is the parent +image until either an authenticated image or the ROT is reached. Then the +Generic code calls the IO framewotk to load the image and calls the +Authentication module to authenticate it, following the CoT from ROT to Image. + + +#### 2.2.2 TF Platform Port (PP) + +The platform is responsible for: + +1. Specifying the CoT for each image that needs to be authenticated. Details of + how a CoT can be specified by the platform are explained later. The platform + also specifies the authentication methods and the parsing method used for + each image. + +2. Statically allocating memory for each parameter in each image which is + used for verifying the CoT, e.g. memory for public keys, hashes etc. + +3. Providing the ROTPK or a hash of it. + +4. Providing additional information to the IPM to enable it to identify and + extract authentication parameters contained in an image, e.g. if the + parameters are stored as X509v3 extensions, the corresponding OID must be + provided. + +5. Fulfill any other memory requirements of the IPM and the CM (not currently + described in this document). + +6. Export functions to verify an image which uses an authentication method that + cannot be interpreted by the CM, e.g. if an image has to be verified using a + NV counter, then the value of the counter to compare with can only be + provided by the platform. + +7. Export a custom IPM if a proprietary image format is being used (described + later). + + +#### 2.2.3 Authentication Module (AM) + +It is responsible for: + +1. Providing the necessary abstraction mechanisms to describe a CoT. Amongst + other things, the authentication and image parsing methods must be specified + by the PP in the CoT. + +2. Verifying the CoT passed by GEN by utilising functionality exported by the + PP, IPM and CM. + +3. Tracking which images have been verified. In case an image is a part of + multiple CoTs then it should be verified only once e.g. the Trusted World + Key Certificate in the TBBR-Client spec. contains information to verify + BL3-0, BL3-1, BL3-2 each of which have a separate CoT. (This responsibility + has not been described in this document but should be trivial to implement). + +4. Reusing memory meant for a data image to verify authentication images e.g. + in the CoT described in Diagram 2, each certificate can be loaded and + verified in the memory reserved by the platform for the BL3-1 image. By the + time BL3-1 (the data image) is loaded, all information to authenticate it + will have been extracted from the parent image i.e. BL3-1 content + certificate. It is assumed that the size of an authentication image will + never exceed the size of a data image. It should be possible to verify this + at build time using asserts. + + +#### 2.2.4 Cryptographic Module (CM) + +The CM is responsible for providing an API to: + +1. Verify a digital signature. +2. Verify a hash. + +The CM does not include any cryptography related code, but it relies on an +external library to perform the cryptographic operations. A Crypto-Library (CL) +linking the CM and the external library must be implemented. The following +functions must be provided by the CL: + +``` +void (*init)(void); +int (*verify_signature)(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); +int (*verify_hash)(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); +``` + +These functions are registered in the CM using the macro: +``` +REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash); +``` + +`_name` must be a string containing the name of the CL. This name is used for +debugging purposes. + +#### 2.2.5 Image Parser Module (IPM) + +The IPM is responsible for: + +1. Checking the integrity of each image loaded by the IO framework. +2. Extracting parameters used for authenticating an image based upon a + description provided by the platform in the CoT descriptor. + +Images may have different formats (for example, authentication images could be +x509v3 certificates, signed ELF files or any other platform specific format). +The IPM allows to register an Image Parser Library (IPL) for every image format +used in the CoT. This library must implement the specific methods to parse the +image. The IPM obtains the image format from the CoT and calls the right IPL to +check the image integrity and extract the authentication parameters. + +See Section "Describing the image parsing methods" for more details about the +mechanism the IPM provides to define and register IPLs. + + +### 2.3 Authentication methods + +The AM supports the following authentication methods: + +1. Hash +2. Digital signature + +The platform may specify these methods in the CoT in case it decides to define +a custom CoT instead of reusing a predefined one. + +If a data image uses multiple methods, then all the methods must be a part of +the same CoT. The number and type of parameters are method specific. These +parameters should be obtained from the parent image using the IPM. + +1. Hash + + Parameters: + + 1. A pointer to data to hash + 2. Length of the data + 4. A pointer to the hash + 5. Length of the hash + + The hash will be represented by the DER encoding of the following ASN.1 + type: + + ``` + DigestInfo ::= SEQUENCE { + digestAlgorithm DigestAlgorithmIdentifier, + digest Digest + } + ``` + + This ASN.1 structure makes it possible to remove any assumption about the + type of hash algorithm used as this information accompanies the hash. This + should allow the Cryptography Library (CL) to support multiple hash + algorithm implementations. + +2. Digital Signature + + Parameters: + + 1. A pointer to data to sign + 2. Length of the data + 3. Public Key Algorithm + 4. Public Key value + 5. Digital Signature Algorithm + 6. Digital Signature value + + The Public Key parameters will be represented by the DER encoding of the + following ASN.1 type: + + ``` + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}}, + subjectPublicKey BIT STRING } + ``` + + The Digital Signature Algorithm will be represented by the DER encoding of + the following ASN.1 types. + + ``` + AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE { + algorithm ALGORITHM.&id({IOSet}), + parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL + } + ``` + + The digital signature will be represented by: + ``` + signature ::= BIT STRING + ``` + +The authentication framework will use the image descriptor to extract all the +information related to authentication. + + +3. Specifying a Chain of Trust +------------------------------- + +A CoT can be described as a set of image descriptors linked together in a +particular order. The order dictates the sequence in which they must be +verified. Each image has a set of properties which allow the AM to verify it. +These properties are described below. + +The PP is responsible for defining a single or multiple CoTs for a data image. +Unless otherwise specified, the data structures described in the following +sections are populated by the PP statically. + + +### 3.1 Describing the image parsing methods + +The parsing method refers to the format of a particular image. For example, an +authentication image that represents a certificate could be in the X.509v3 +format. A data image that represents a boot loader stage could be in raw binary +or ELF format. The IPM supports three parsing methods. An image has to use one +of the three methods described below. An IPL is responsible for interpreting a +single parsing method. There has to be one IPL for every method used by the +platform. + +1. Raw format: This format is effectively a nop as an image using this method + is treated as being in raw binary format e.g. boot loader images used by ARM + TF. This method should only be used by data images. + +2. X509V3 method: This method uses industry standards like X.509 to represent + PKI certificates (authentication images). It is expected that open source + libraries will be available which can be used to parse an image represented + by this method. Such libraries can be used to write the corresponding IPL + e.g. the X.509 parsing library code in PolarSSL. + +3. Platform defined method: This method caters for platform specific + proprietary standards to represent authentication or data images. For + example, The signature of a data image could be appended to the data image + raw binary. A header could be prepended to the combined blob to specify the + extents of each component. The platform will have to implement the + corresponding IPL to interpret such a format. + +The following enum can be used to define these three methods. + +``` +typedef enum img_type_enum { + IMG_RAW, /* Binary image */ + IMG_PLAT, /* Platform specific format */ + IMG_CERT, /* X509v3 certificate */ + IMG_MAX_TYPES, +} img_type_t; +``` + +An IPL must provide functions with the following prototypes: + +``` +void init(void); +int check_integrity(void *img, unsigned int img_len); +int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); +``` + +An IPL for each type must be registered using the following macro: + +``` +REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param) +``` + +* `_type`: one of the types described above. +* `_name`: a string containing the IPL name for debugging purposes. +* `_init`: initialization function pointer. +* `_check_int`: check image integrity function pointer. +* `_get_param`: extract authentication parameter funcion pointer. + +The `init()` function will be used to initialize the IPL. + +The `check_integrity()` function is passed a pointer to the memory where the +image has been loaded by the IO framework and the image length. It should ensure +that the image is in the format corresponding to the parsing method and has not +been tampered with. For example, RFC-2459 describes a validation sequence for an +X.509 certificate. + +The `get_auth_param()` function is passed a parameter descriptor containing +information about the parameter (`type_desc` and `cookie`) to identify and +extract the data corresponding to that parameter from an image. This data will +be used to verify either the current or the next image in the CoT sequence. + +Each image in the CoT will specify the parsing method it uses. This information +will be used by the IPM to find the right parser descriptor for the image. + + +### 3.2 Describing the authentication method(s) + +As part of the CoT, each image has to specify one or more authentication methods +which will be used to verify it. As described in the Section "Authentication +methods", there are three methods supported by the AM. + +``` +typedef enum { + AUTH_METHOD_NONE, + AUTH_METHOD_HASH, + AUTH_METHOD_SIG, + AUTH_METHOD_NUM +} auth_method_type_t; +``` + +The AM defines the type of each parameter used by an authentication method. It +uses this information to: + +1. Specify to the `get_auth_param()` function exported by the IPM, which + parameter should be extracted from an image. + +2. Correctly marshall the parameters while calling the verification function + exported by the CM and PP. + +3. Extract authentication parameters from a parent image in order to verify a + child image e.g. to verify the certificate image, the public key has to be + obtained from the parent image. + +``` +typedef enum { + AUTH_PARAM_NONE, + AUTH_PARAM_RAW_DATA, /* Raw image data */ + AUTH_PARAM_SIG, /* The image signature */ + AUTH_PARAM_SIG_ALG, /* The image signature algorithm */ + AUTH_PARAM_HASH, /* A hash (including the algorithm) */ + AUTH_PARAM_PUB_KEY, /* A public key */ +} auth_param_type_t; +``` + +The AM defines the following structure to identify an authentication parameter +required to verify an image. + +``` +typedef struct auth_param_type_desc_s { + auth_param_type_t type; + void *cookie; +} auth_param_type_desc_t; +``` + +`cookie` is used by the platform to specify additional information to the IPM +which enables it to uniquely identify the parameter that should be extracted +from an image. For example, the hash of a BL3-x image in its corresponding +content certificate is stored in an X509v3 custom extension field. An extension +field can only be identified using an OID. In this case, the `cookie` could +contain the pointer to the OID defined by the platform for the hash extension +field while the `type` field could be set to `AUTH_PARAM_HASH`. A value of 0 for +the `cookie` field means that it is not used. + +For each method, the AM defines a structure with the parameters required to +verify the image. + +``` +/* + * Parameters for authentication by hash matching + */ +typedef struct auth_method_param_hash_s { + auth_param_type_desc_t *data; /* Data to hash */ + auth_param_type_desc_t *hash; /* Hash to match with */ +} auth_method_param_hash_t; + +/* + * Parameters for authentication by signature + */ +typedef struct auth_method_param_sig_s { + auth_param_type_desc_t *pk; /* Public key */ + auth_param_type_desc_t *sig; /* Signature to check */ + auth_param_type_desc_t *alg; /* Signature algorithm */ + auth_param_type_desc_t *tbs; /* Data signed */ +} auth_method_param_sig_t; + +``` + +The AM defines the following structure to describe an authentication method for +verifying an image + +``` +/* + * Authentication method descriptor + */ +typedef struct auth_method_desc_s { + auth_method_type_t type; + union { + auth_method_param_hash_t hash; + auth_method_param_sig_t sig; + } param; +} auth_method_desc_t; +``` + +Using the method type specified in the `type` field, the AM finds out what field +needs to access within the `param` union. + +### 3.3 Storing Authentication parameters + +A parameter described by `auth_param_type_desc_t` to verify an image could be +obtained from either the image itself or its parent image. The memory allocated +for loading the parent image will be reused for loading the child image. Hence +parameters which are obtained from the parent for verifying a child image need +to have memory allocated for them separately where they can be stored. This +memory must be statically allocated by the platform port. + +The AM defines the following structure to store the data corresponding to an +authentication parameter. + +``` +typedef struct auth_param_data_desc_s { + void *auth_param_ptr; + unsigned int auth_param_len; +} auth_param_data_desc_t; +``` + +The `auth_param_ptr` field is initialized by the platform. The `auth_param_len` +field is used to specify the length of the data in the memory. + +For parameters that can be obtained from the child image itself, the IPM is +responsible for populating the `auth_param_ptr` and `auth_param_len` fields +while executing the `img_get_auth_param()` function. + +The AM defines the following structure to enable an image to describe the +parameters that should be extracted from it and used to verify the next image +(child) in a CoT. + +``` +typedef struct auth_param_desc_s { + auth_param_type_desc_t type_desc; + auth_param_data_desc_t data; +} auth_param_desc_t; +``` + +### 3.4 Describing an image in a CoT + +An image in a CoT is a consolidation of the following aspects of a CoT described +above. + +1. A unique identifier specified by the platform which allows the IO framework + to locate the image in a FIP and load it in the memory reserved for the data + image in the CoT. + +2. A parsing method which is used by the AM to find the appropriate IPM. + +3. Authentication methods and their parameters as described in the previous + section. These are used to verify the current image. + +4. Parameters which are used to verify the next image in the current CoT. These + parameters are specified only by authentication images and can be extracted + from the current image once it has been verified. + +The following data structure describes an image in a CoT. +``` +typedef struct auth_img_desc_s { + unsigned int img_id; + const struct auth_img_desc_s *parent; + img_type_t img_type; + auth_method_desc_t img_auth_methods[AUTH_METHOD_NUM]; + auth_param_desc_t authenticated_data[COT_MAX_VERIFIED_PARAMS]; +} auth_img_desc_t; +``` +A CoT is defined as an array of `auth_image_desc_t` structures linked together +by the `parent` field. Those nodes with no parent must be authenticated using +the ROTPK stored in the platform. + + +4. Implementation example +-------------------------- + +This section is a detailed guide explaining a trusted boot implementation using +the authentication framework. This example corresponds to the Applicative +Functional Mode (AFM) as specified in the TBBR-Client document. It is +recommended to read this guide along with the source code. + +### 4.1 The TBBR CoT + +The CoT can be found in `drivers/auth/tbbr/tbbr_cot.c`. This CoT consists of an +array of image descriptors and it is registered in the framework using the macro +`REGISTER_COT(cot_desc)`, where 'cot_desc' must be the name of the array +(passing a pointer or any other type of indirection will cause the registration +process to fail). + +The number of images participating in the boot process depends on the CoT. There +is, however, a minimum set of images that are mandatory in the Trusted Firmware +and thus all CoTs must present: + +* `BL2` +* `BL3-0` (platform specific) +* `BL3-1` +* `BL3-2` (optional) +* `BL3-3` + +The TBBR specifies the additional certificates that must accompany these images +for a proper authentication. Details about the TBBR CoT may be found in the +[Trusted Board Boot] document. + +Following the [Platform Porting Guide], a platform must provide unique +identifiers for all the images and certificates that will be loaded during the +boot process. If a platform is using the TBBR as a reference for trusted boot, +these identifiers can be obtained from `include/common/tbbr/tbbr_img_def.h`. +ARM platforms include this file in `include/plat/arm/common/arm_def.h`. Other +platforms may also include this file or provide their own identifiers. + +**Important**: the authentication module uses these identifiers to index the +CoT array, so the descriptors location in the array must match the identifiers. + +Each image descriptor must specify: + +* `img_id`: the corresponding image unique identifier defined by the platform. +* `img_type`: the image parser module uses the image type to call the proper + parsing library to check the image integrity and extract the required + authentication parameters. Three types of images are currently supported: + * `IMG_RAW`: image is a raw binary. No parsing functions are available, + other than reading the whole image. + * `IMG_PLAT`: image format is platform specific. The platform may use this + type for custom images not directly supported by the authentication + framework. + * `IMG_CERT`: image is an x509v3 certificate. +* `parent`: pointer to the parent image descriptor. The parent will contain + the information required to authenticate the current image. If the parent + is NULL, the authentication parameters will be obtained from the platform + (i.e. the BL2 and Trusted Key certificates are signed with the ROT private + key, whose public part is stored in the platform). +* `img_auth_methods`: this array defines the authentication methods that must + be checked to consider an image authenticated. Each method consists of a + type and a list of parameter descriptors. A parameter descriptor consists of + a type and a cookie which will point to specific information required to + extract that parameter from the image (i.e. if the parameter is stored in an + x509v3 extension, the cookie will point to the extension OID). Depending on + the method type, a different number of parameters must be specified. + Supported methods are: + * `AUTH_METHOD_HASH`: the hash of the image must match the hash extracted + from the parent image. The following parameter descriptors must be + specified: + * `data`: data to be hashed (obtained from current image) + * `hash`: reference hash (obtained from parent image) + * `AUTH_METHOD_SIG`: the image (usually a certificate) must be signed with + the private key whose public part is extracted from the parent image (or + the platform if the parent is NULL). The following parameter descriptors + must be specified: + * `pk`: the public key (obtained from parent image) + * `sig`: the digital signature (obtained from current image) + * `alg`: the signature algorithm used (obtained from current image) + * `data`: the data to be signed (obtained from current image) +* `authenticated_data`: this array indicates what authentication parameters + must be extracted from an image once it has been authenticated. Each + parameter consists of a parameter descriptor and the buffer address/size + to store the parameter. The CoT is responsible for allocating the required + memory to store the parameters. + +In the `tbbr_cot.c` file, a set of buffers are allocated to store the parameters +extracted from the certificates. In the case of the TBBR CoT, these parameters +are hashes and public keys. In DER format, an RSA-2048 public key requires 294 +bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication +process, some of the buffers may be reused at different stages during the boot. + +Next in that file, the parameter descriptors are defined. These descriptors will +be used to extract the parameter data from the corresponding image. + +#### 4.1.1 Example: the BL3-1 Chain of Trust + +Four image descriptors form the BL3-1 Chain of Trust: + +``` +[TRUSTED_KEY_CERT_ID] = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &tz_world_pk, + .data = { + .ptr = (void *)plat_tz_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &ntz_world_pk, + .data = { + .ptr = (void *)plat_ntz_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}, +[BL31_KEY_CERT_ID] = { + .img_id = BL31_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[TRUSTED_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tz_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl31_content_pk, + .data = { + .ptr = (void *)plat_content_pk, + .len = (unsigned int)PK_DER_LEN + } + } + } +}, +[BL31_CERT_ID] = { + .img_id = BL31_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[BL31_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &bl31_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl31_hash, + .data = { + .ptr = (void *)plat_bl31_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}, +[BL31_IMAGE_ID] = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &cot_desc[BL31_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl31_hash, + } + } + } +} +``` +The **Trusted Key certificate** is signed with the ROT private key and contains +the Trusted World public key and the Non-Trusted World public key as x509v3 +extensions. This must be specified in the image descriptor using the +`img_auth_methods` and `authenticated_data` arrays, respectively. + +The Trusted Key certificate is authenticated by checking its digital signature +using the ROTPK. Four parameters are required to check a signature: the public +key, the algorithm, the signature and the data that has been signed. Therefore, +four parameter descriptors must be specified with the authentication method: + +* `subject_pk`: parameter descriptor of type `AUTH_PARAM_PUB_KEY`. This type + is used to extract a public key from the parent image. If the cookie is an + OID, the key is extracted from the corresponding x509v3 extension. If the + cookie is NULL, the subject public key is retrieved. In this case, because + the parent image is NULL, the public key is obtained from the platform + (this key will be the ROTPK). +* `sig`: parameter descriptor of type `AUTH_PARAM_SIG`. It is used to extract + the signature from the certificate. +* `sig_alg`: parameter descriptor of type `AUTH_PARAM_SIG`. It is used to + extract the signature algorithm from the certificate. +* `raw_data`: parameter descriptor of type `AUTH_PARAM_RAW_DATA`. It is used + to extract the data to be signed from the certificate. + +Once the signature has been checked and the certificate authenticated, the +Trusted World public key needs to be extracted from the certificate. A new entry +is created in the `authenticated_data` array for that purpose. In that entry, +the corresponding parameter descriptor must be specified along with the buffer +address to store the parameter value. In this case, the `tz_world_pk` descriptor +is used to extract the public key from an x509v3 extension with OID +`TZ_WORLD_PK_OID`. The BL3-1 key certificate will use this descriptor as +parameter in the signature authentication method. The key is stored in the +`plat_tz_world_pk_buf` buffer. + +The **BL3-1 Key certificate** is authenticated by checking its digital signature +using the Trusted World public key obtained previously from the Trusted Key +certificate. In the image descriptor, we specify a single authentication method +by signature whose public key is the `tz_world_pk`. Once this certificate has +been authenticated, we have to extract the BL3-1 public key, stored in the +extension specified by `bl31_content_pk`. This key will be copied to the +`plat_content_pk` buffer. + +The **BL3-1 certificate** is authenticated by checking its digital signature +using the BL3-1 public key obtained previously from the BL3-1 Key certificate. +We specify the authentication method using `bl31_content_pk` as public key. +After authentication, we need to extract the BL3-1 hash, stored in the extension +specified by `bl31_hash`. This hash will be copied to the `plat_bl31_hash_buf` +buffer. + +The **BL3-1 image** is authenticated by calculating its hash and matching it +with the hash obtained from the BL3-1 certificate. The image descriptor contains +a single authentication method by hash. The parameters to the hash method are +the reference hash, `bl31_hash`, and the data to be hashed. In this case, it is +the whole image, so we specify `raw_data`. + +### 4.2 The image parser library + +The image parser module relies on libraries to check the image integrity and +extract the authentication parameters. The number and type of parser libraries +depend on the images used in the CoT. Raw images do not need a library, so +only an x509v3 library is required for the TBBR CoT. + +ARM platforms will use an x509v3 library based on mbedTLS. This library may be +found in `drivers/auth/mbedtls/mbedtls_x509_parser.c`. It exports three +functions: + +``` +void init(void); +int check_integrity(void *img, unsigned int img_len); +int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); +``` + +The library is registered in the framework using the macro +`REGISTER_IMG_PARSER_LIB()`. Each time the image parser module needs to access +an image of type `IMG_CERT`, it will call the corresponding function exported +in this file. + +The build system must be updated to include the corresponding library and +mbedTLS sources. ARM platforms use the `arm_common.mk` file to pull the sources. + +### 4.3 The cryptographic library + +The cryptographic module relies on a library to perform the required operations, +i.e. verify a hash or a digital signature. ARM platforms will use a library +based on mbedTLS, which can be found in `drivers/auth/mbedtls/mbedtls_crypto.c`. +This library is registered in the authentication framework using the macro +`REGISTER_CRYPTO_LIB()` and exports three functions: + +``` +void init(void); +int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); +int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); +``` + +The key algorithm (rsa, ecdsa) must be specified in the build system using the +`MBEDTLS_KEY_ALG` variable, so the Makefile can include the corresponding +sources in the build. + +- - - - - - - - - - - - - - - - - - - - - - - - - - + +_Copyright (c) 2015, ARM Limited and Contributors. All rights reserved._ + + +[Trusted Board Boot]: ./trusted-board-boot.md +[Platform Porting Guide]: ./porting-guide.md diff --git a/docs/porting-guide.md b/docs/porting-guide.md index 436dc10..2f01353 100644 --- a/docs/porting-guide.md +++ b/docs/porting-guide.md @@ -134,51 +134,6 @@ Defines the character string printed by BL1 upon entry into the `bl1_main()` function. -* **#define : BL2_IMAGE_NAME** - - Name of the BL2 binary image on the host file-system. This name is used by - BL1 to load BL2 into secure memory from non-volatile storage. - -* **#define : BL31_IMAGE_NAME** - - Name of the BL3-1 binary image on the host file-system. This name is used by - BL2 to load BL3-1 into secure memory from platform storage. - -* **#define : BL33_IMAGE_NAME** - - Name of the BL3-3 binary image on the host file-system. This name is used by - BL2 to load BL3-3 into non-secure memory from platform storage. - -* **#define : BL2_CERT_NAME** - - Name of the BL2 content certificate on the host file-system (mandatory when - Trusted Board Boot is enabled). - -* **#define : TRUSTED_KEY_CERT_NAME** - - Name of the Trusted Key certificate on the host file-system (mandatory when - Trusted Board Boot is enabled). - -* **#define : BL31_KEY_CERT_NAME** - - Name of the BL3-1 Key certificate on the host file-system (mandatory when - Trusted Board Boot is enabled). - -* **#define : BL31_CERT_NAME** - - Name of the BL3-1 Content certificate on the host file-system (mandatory - when Trusted Board Boot is enabled). - -* **#define : BL33_KEY_CERT_NAME** - - Name of the BL3-3 Key certificate on the host file-system (mandatory when - Trusted Board Boot is enabled). - -* **#define : BL33_CERT_NAME** - - Name of the BL3-3 Content certificate on the host file-system (mandatory - when Trusted Board Boot is enabled). - * **#define : PLATFORM_CORE_COUNT** Defines the total number of CPUs implemented by the platform across all @@ -243,42 +198,93 @@ Defines the base address in non-secure DRAM where BL2 loads the BL3-3 binary image. Must be aligned on a page-size boundary. +For every image, the platform must define individual identifiers that will be +used by BL1 or BL2 to load the corresponding image into memory from non-volatile +storage. For the sake of performance, integer numbers will be used as +identifiers. The platform will use those identifiers to return the relevant +information about the image to be loaded (file handler, load address, +authentication information, etc.). The following image identifiers are +mandatory: + +* **#define : BL2_IMAGE_ID** + + BL2 image identifier, used by BL1 to load BL2. + +* **#define : BL31_IMAGE_ID** + + BL3-1 image identifier, used by BL2 to load BL3-1. + +* **#define : BL33_IMAGE_ID** + + BL3-3 image identifier, used by BL2 to load BL3-3. + +If Trusted Board Boot is enabled, the following certificate identifiers must +also be defined: + +* **#define : BL2_CERT_ID** + + BL2 content certificate identifier, used by BL1 to load the BL2 content + certificate. + +* **#define : TRUSTED_KEY_CERT_ID** + + Trusted key certificate identifier, used by BL2 to load the trusted key + certificate. + +* **#define : BL31_KEY_CERT_ID** + + BL3-1 key certificate identifier, used by BL2 to load the BL3-1 key + certificate. + +* **#define : BL31_CERT_ID** + + BL3-1 content certificate identifier, used by BL2 to load the BL3-1 content + certificate. + +* **#define : BL33_KEY_CERT_ID** + + BL3-3 key certificate identifier, used by BL2 to load the BL3-3 key + certificate. + +* **#define : BL33_CERT_ID** + + BL3-3 content certificate identifier, used by BL2 to load the BL3-3 content + certificate. + If a BL3-0 image is supported by the platform, the following constants must also be defined: -* **#define : BL30_IMAGE_NAME** +* **#define : BL30_IMAGE_ID** - Name of the BL3-0 binary image on the host file-system. This name is used by - BL2 to load BL3-0 into secure memory from platform storage before being - transfered to the SCP. + BL3-0 image identifier, used by BL2 to load BL3-0 into secure memory from + platform storage before being transfered to the SCP. -* **#define : BL30_KEY_CERT_NAME** +* **#define : BL30_KEY_CERT_ID** - Name of the BL3-0 Key certificate on the host file-system (mandatory when - Trusted Board Boot is enabled). + BL3-0 key certificate identifier, used by BL2 to load the BL3-0 key + certificate (mandatory when Trusted Board Boot is enabled). -* **#define : BL30_CERT_NAME** +* **#define : BL30_CERT_ID** - Name of the BL3-0 Content certificate on the host file-system (mandatory - when Trusted Board Boot is enabled). + BL3-0 content certificate identifier, used by BL2 to load the BL3-0 content + certificate (mandatory when Trusted Board Boot is enabled). If a BL3-2 image is supported by the platform, the following constants must also be defined: -* **#define : BL32_IMAGE_NAME** +* **#define : BL32_IMAGE_ID** - Name of the BL3-2 binary image on the host file-system. This name is used by - BL2 to load BL3-2 into secure memory from platform storage. + BL3-2 image identifier, used by BL2 to load BL3-2. -* **#define : BL32_KEY_CERT_NAME** +* **#define : BL32_KEY_CERT_ID** - Name of the BL3-2 Key certificate on the host file-system (mandatory when - Trusted Board Boot is enabled). + BL3-2 key certificate identifier, used by BL2 to load the BL3-2 key + certificate (mandatory when Trusted Board Boot is enabled). -* **#define : BL32_CERT_NAME** +* **#define : BL32_CERT_ID** - Name of the BL3-2 Content certificate on the host file-system (mandatory - when Trusted Board Boot is enabled). + BL3-2 content certificate identifier, used by BL2 to load the BL3-2 content + certificate (mandatory when Trusted Board Boot is enabled). * **#define : BL32_BASE** @@ -466,15 +472,36 @@ providing the warm-boot entry-point addresses. -### Function: plat_match_rotpk() +### Function: plat_get_rotpk_info() - Argument : const unsigned char *, unsigned int + Argument : void *, void **, unsigned int *, unsigned int * Return : int -This function is mandatory when Trusted Board Boot is enabled. It receives a -pointer to a buffer containing a signing key and its size as parameters and -returns 0 (success) if that key matches the ROT (Root Of Trust) key stored in -the platform. Any other return value means a mismatch. +This function is mandatory when Trusted Board Boot is enabled. It returns a +pointer to the ROTPK stored in the platform (or a hash of it) and its length. +The ROTPK must be encoded in DER format according to the following ASN.1 +structure: + + AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL + } + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING + } + +In case the function returns a hash of the key: + + DigestInfo ::= SEQUENCE { + digestAlgorithm AlgorithmIdentifier, + digest OCTET STRING + } + +The function returns 0 on success. Any other value means the ROTPK could not be +retrieved from the platform. The function also reports extra information related +to the ROTPK in the flags parameter. @@ -1528,10 +1555,11 @@ operations such as loading a bootloader image. The current implementation only allows for known images to be loaded by the -firmware. These images are specified by using their names, as defined in -[include/plat/common/platform.h]. The platform layer (`plat_get_image_source()`) -then returns a reference to a device and a driver-specific `spec` which will be -understood by the driver to allow access to the image data. +firmware. These images are specified by using their identifiers, as defined in +[include/plat/common/platform_def.h] (or a separate header file included from +there). The platform layer (`plat_get_image_source()`) then returns a reference +to a device and a driver-specific `spec` which will be understood by the driver +to allow access to the image data. The layer is designed in such a way that is it possible to chain drivers with other drivers. For example, file-system drivers may be implemented on top of diff --git a/docs/trusted-board-boot.md b/docs/trusted-board-boot.md index f3b9f14..1cfa843 100644 --- a/docs/trusted-board-boot.md +++ b/docs/trusted-board-boot.md @@ -6,7 +6,7 @@ 1. [Introduction](#1--introduction) 2. [Chain of Trust](#2--chain-of-trust) 3. [Trusted Board Boot Sequence](#3--trusted-board-boot-sequence) -4. [Authentication Module](#4--authentication-module) +4. [Authentication Framework](#4--authentication-framework) 5. [Certificate Generation Tool](#5--certificate-generation-tool) @@ -209,27 +209,15 @@ described in the following sections. -4. Authentication Module -------------------------- +4. Authentication Framework +---------------------------- -The authentication module implements the required support to authenticate the -corresponding certificates or images at each step in the Trusted Board Boot -sequence. The module relies on the PolarSSL library (v1.3.9) to perform the -following operations: +The authentication framework included in the Trusted Firmware provides support +to implement the desired trusted boot sequence. ARM platforms use this framework +to implement the boot requirements specified in the TBBR-client document. -* Parsing X.509 certificates and verifying them using SHA-256 with RSA - Encryption. -* Extracting public keys and hashes from the certificates. -* Generating hashes (SHA-256) of boot loader images - -At each step, the module is responsible for allocating memory to store the -public keys or hashes that will be used in later steps. The step identifier is -used to determine what information must be saved, according to the CoT model -detailed in the previous sections. - -The authentication module resides in the `common/auth/polarssl` directory. -Instructions for including the necessary modules of the PolarSSL SSL library and -building the authentication module can be found in the [User Guide]. +More information about the authentication framework can be found in the +[Auth Framework] document. 5. Certificate Generation Tool @@ -257,4 +245,5 @@ [X.509 v3]: http://www.ietf.org/rfc/rfc5280.txt [X.690]: http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf +[Auth Framework]: auth-framework.md [User Guide]: user-guide.md diff --git a/docs/user-guide.md b/docs/user-guide.md index ef26f11..470c69f 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -265,16 +265,8 @@ * `TRUSTED_BOARD_BOOT`: Boolean flag to include support for the Trusted Board Boot feature. When set to '1', BL1 and BL2 images include support to load and verify the certificates and images in a FIP. The default value is '0'. - A successful build, when `TRUSTED_BOARD_BOOT=1`, depends upon the correct - initialization of the `AUTH_MOD` option. Generation and inclusion of - certificates in the FIP depends upon the value of the `GENERATE_COT` option. - -* `AUTH_MOD`: This option is used when `TRUSTED_BOARD_BOOT=1`. It specifies - the name of the authentication module that will be used in the Trusted Board - Boot sequence. The module must be located in `common/auth/` - directory. The directory must contain a makefile `.mk` which - will be used to build the module. More information can be found in - [Trusted Board Boot]. The default module name is 'none'. + Generation and inclusion of certificates in the FIP depends upon the value + of the `GENERATE_COT` option. * `GENERATE_COT`: Boolean flag used to build and execute the `cert_create` tool to create certificates as per the Chain of Trust described in @@ -297,28 +289,40 @@ certificate generation tool to create new keys in case no valid keys are present or specified. Allowed options are '0' or '1'. Default is '1'. +* `SAVE_KEYS`: This option is used when `GENERATE_COT=1`. It tells the + certificate generation tool to save the keys used to establish the Chain of + Trust. Allowed options are '0' or '1'. Default is '0' (do not save). + + Note: This option depends on 'CREATE_KEYS' to be enabled. If the keys + already exist in disk, they will be overwritten without further notice. + * `ROT_KEY`: This option is used when `GENERATE_COT=1`. It specifies the - file that contains the ROT private key in PEM format. + file that contains the ROT private key in PEM format. If `SAVE_KEYS=1`, this + file name will be used to save the key. * `TRUSTED_WORLD_KEY`: This option is used when `GENERATE_COT=1`. It specifies the file that contains the Trusted World private key in PEM - format. + format. If `SAVE_KEYS=1`, this file name will be used to save the key. * `NON_TRUSTED_WORLD_KEY`: This option is used when `GENERATE_COT=1`. It specifies the file that contains the Non-Trusted World private key in PEM - format. + format. If `SAVE_KEYS=1`, this file name will be used to save the key. * `BL30_KEY`: This option is used when `GENERATE_COT=1`. It specifies the - file that contains the BL3-0 private key in PEM format. + file that contains the BL3-0 private key in PEM format. If `SAVE_KEYS=1`, + this file name will be used to save the key. * `BL31_KEY`: This option is used when `GENERATE_COT=1`. It specifies the - file that contains the BL3-1 private key in PEM format. + file that contains the BL3-1 private key in PEM format. If `SAVE_KEYS=1`, + this file name will be used to save the key. * `BL32_KEY`: This option is used when `GENERATE_COT=1`. It specifies the - file that contains the BL3-2 private key in PEM format. + file that contains the BL3-2 private key in PEM format. If `SAVE_KEYS=1`, + this file name will be used to save the key. * `BL33_KEY`: This option is used when `GENERATE_COT=1`. It specifies the - file that contains the BL3-3 private key in PEM format. + file that contains the BL3-3 private key in PEM format. If `SAVE_KEYS=1`, + this file name will be used to save the key. * `PROGRAMMABLE_RESET_ADDRESS`: This option indicates whether the reset vector address can be programmed or is fixed on the platform. It can take @@ -334,6 +338,23 @@ For a better understanding of these options, the ARM development platform memory map is explained in the [Firmware Design]. +* `ARM_ROTPK_LOCATION`: used when `TRUSTED_BOARD_BOOT=1`. It specifies the + location of the ROTPK hash returned by the function `plat_get_rotpk_info()` + for ARM platforms. Depending on the selected option, the proper private key + must be specified using the `ROT_KEY` option when building the Trusted + Firmware. This private key will be used by the certificate generation tool + to sign the BL2 and Trusted Key certificates. Available options for + `ARM_ROTPK_LOCATION` are: + + - `regs` : return the ROTPK hash stored in the Trusted root-key storage + registers. The private key corresponding to this ROTPK hash is not + currently available. + - `devel_rsa` : return a development public key hash embedded in the BL1 + and BL2 binaries. This hash has been obtained from the RSA public key + `arm_rotpk_rsa.der`, located in `plat/arm/board/common/rotpk`. To use + this option, `arm_rotprivk_rsa.pem` must be specified as `ROT_KEY` when + creating the certificates. + #### ARM CSS platform specific build options * `CSS_DETECT_PRE_1_7_0_SCP`: Boolean flag to detect SCP version @@ -486,25 +507,58 @@ following steps should be followed to build a FIP image with support for this feature. -1. Fulfill the dependencies of the `polarssl` authentication module by checking - out the tag `polarssl-1.3.9` from the [PolarSSL Repository]. +1. Fulfill the dependencies of the `mbedtls` cryptographic and image parser + modules by checking out the tag `mbedtls-1.3.11` from the + [mbedTLS Repository]. - The `common/auth/polarssl/polarssl.mk` contains the list of PolarSSL source - files the module depends upon. `common/auth/polarssl/polarssl_config.h` - contains the configuration options required to build the PolarSSL sources. + The `drivers/auth/mbedtls/mbedtls_*.mk` files contain the list of mbedTLS + source files the modules depend upon. + `include/drivers/auth/mbedtls/mbedtls_config.h` contains the configuration + options required to build the mbedTLS sources. - Note that the PolarSSL SSL library is licensed under the GNU GPL version 2 - or later license. Using PolarSSL source code will affect the licensing of + Note that the mbedTLS library is licensed under the GNU GPL version 2 + or later license. Using mbedTLS source code will affect the licensing of Trusted Firmware binaries that are built using this library. 2. Ensure that the following command line variables are set while invoking `make` to build Trusted Firmware: - * `POLARSSL_DIR=` - * `AUTH_MOD=polarssl` + * `MBEDTLS_DIR=` * `TRUSTED_BOARD_BOOT=1` * `GENERATE_COT=1` + In the case of ARM platforms, the location of the ROTPK hash must also be + specified at build time. Two locations are currently supported (see + `ARM_ROTPK_LOCATION` build option): + + * `ARM_ROTPK_LOCATION=regs`: the ROTPK hash is obtained from the Trusted + root-key storage registers present in the platform. On Juno, this + registers are read-only. On FVP Base and Cortex models, the registers + are read-only, but the value can be specified using the command line + option `bp.trusted_key_storage.public_key` when launching the model. + On both Juno and FVP models, the default value corresponds to an + ECDSA-SECP256R1 public key hash, whose private part is not currently + available. + + * `ARM_ROTPK_LOCATION=devel_rsa`: use the ROTPK hash that is hardcoded + in the ARM platform port. The private/public RSA key pair may be + found in `plat/arm/board/common/rotpk`. + + Example of command line using RSA development keys: + + CROSS_COMPILE=/bin/aarch64-none-elf- \ + BL33=/ \ + MBEDTLS_DIR= \ + make PLAT= TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + all fip + + The result of this build will be the bl1.bin and the fip.bin binaries, with + the difference that the FIP will include the certificates corresponding to + the Chain of Trust described in the TBBR-client document. These certificates + can also be found in the output build directory. + ### Checking source code style @@ -1124,5 +1178,5 @@ [Linaro Toolchain]: http://releases.linaro.org/14.07/components/toolchain/binaries/ [EDK2]: http://github.com/tianocore/edk2 [DS-5]: http://www.arm.com/products/tools/software-tools/ds-5/index.php -[Polarssl Repository]: https://github.com/polarssl/polarssl.git +[mbedTLS Repository]: https://github.com/ARMmbed/mbedtls.git [Trusted Board Boot]: trusted-board-boot.md diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c new file mode 100644 index 0000000..bdd3c5a --- /dev/null +++ b/drivers/auth/auth_mod.c @@ -0,0 +1,348 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define return_if_error(rc) \ + do { \ + if (rc != 0) { \ + return rc; \ + } \ + } while (0) + +/* Pointer to CoT */ +extern const auth_img_desc_t *const cot_desc_ptr; +extern unsigned int auth_img_flags[]; + +static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a, + const auth_param_type_desc_t *b) +{ + if ((a->type == b->type) && (a->cookie == b->cookie)) { + return 0; + } + return 1; +} + +/* + * This function obtains the requested authentication parameter data from the + * information extracted from the parent image after its authentication. + */ +static int auth_get_param(const auth_param_type_desc_t *param_type_desc, + const auth_img_desc_t *img_desc, + void **param, unsigned int *len) +{ + int i; + + for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) { + if (0 == cmp_auth_param_type_desc(param_type_desc, + img_desc->authenticated_data[i].type_desc)) { + *param = img_desc->authenticated_data[i].data.ptr; + *len = img_desc->authenticated_data[i].data.len; + return 0; + } + } + + return 1; +} + +/* + * Authenticate an image by matching the data hash + * + * This function implements 'AUTH_METHOD_HASH'. To authenticate an image using + * this method, the image must contain: + * + * - The data to calculate the hash from + * + * The parent image must contain: + * + * - The hash to be matched with (including hash algorithm) + * + * For a successful authentication, both hashes must match. The function calls + * the crypto-module to check this matching. + * + * Parameters: + * param: parameters to perform the hash authentication + * img_desc: pointer to image descriptor so we can know the image type + * and parent image + * img: pointer to image in memory + * img_len: length of image (in bytes) + * + * Return: + * 0 = success, Otherwise = error + */ +static int auth_hash(const auth_method_param_hash_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len) +{ + void *data_ptr, *hash_der_ptr; + unsigned int data_len, hash_der_len; + int rc = 0; + + /* Get the hash from the parent image. This hash will be DER encoded + * and contain the hash algorithm */ + rc = auth_get_param(param->hash, img_desc->parent, + &hash_der_ptr, &hash_der_len); + return_if_error(rc); + + /* Get the data to be hashed from the current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->data, + img, img_len, &data_ptr, &data_len); + return_if_error(rc); + + /* Ask the crypto module to verify this hash */ + rc = crypto_mod_verify_hash(data_ptr, data_len, + hash_der_ptr, hash_der_len); + + return rc; +} + +/* + * Authenticate by digital signature + * + * This function implements 'AUTH_METHOD_SIG'. To authenticate an image using + * this method, the image must contain: + * + * - Data to be signed + * - Signature + * - Signature algorithm + * + * We rely on the image parser module to extract this data from the image. + * The parent image must contain: + * + * - Public key (or a hash of it) + * + * If the parent image contains only a hash of the key, we will try to obtain + * the public key from the image itself (i.e. self-signed certificates). In that + * case, the signature verification is considered just an integrity check and + * the authentication is established by calculating the hash of the key and + * comparing it with the hash obtained from the parent. + * + * If the image has no parent (NULL), it means it has to be authenticated using + * the ROTPK stored in the platform. Again, this ROTPK could be the key itself + * or a hash of it. + * + * Return: 0 = success, Otherwise = error + */ +static int auth_signature(const auth_method_param_sig_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len) +{ + void *data_ptr, *pk_ptr, *pk_hash_ptr, *sig_ptr, *sig_alg_ptr; + unsigned int data_len, pk_len, pk_hash_len, sig_len, sig_alg_len; + unsigned int flags = 0; + int rc = 0; + + /* Get the data to be signed from current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->data, + img, img_len, &data_ptr, &data_len); + return_if_error(rc); + + /* Get the signature from current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->sig, + img, img_len, &sig_ptr, &sig_len); + return_if_error(rc); + + /* Get the signature algorithm from current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->alg, + img, img_len, &sig_alg_ptr, &sig_alg_len); + return_if_error(rc); + + /* Get the public key from the parent. If there is no parent (NULL), + * the certificate has been signed with the ROTPK, so we have to get + * the PK from the platform */ + if (img_desc->parent) { + rc = auth_get_param(param->pk, img_desc->parent, + &pk_ptr, &pk_len); + } else { + rc = plat_get_rotpk_info(param->pk->cookie, &pk_ptr, &pk_len, + &flags); + } + return_if_error(rc); + + /* If the PK is a hash of the key, retrieve the key from the image */ + if (flags & ROTPK_IS_HASH) { + pk_hash_ptr = pk_ptr; + pk_hash_len = pk_len; + rc = img_parser_get_auth_param(img_desc->img_type, + param->pk, img, img_len, + &pk_ptr, &pk_len); + return_if_error(rc); + + /* Ask the crypto module to verify the signature */ + rc = crypto_mod_verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); + return_if_error(rc); + + /* Ask the crypto-module to verify the key hash */ + rc = crypto_mod_verify_hash(pk_ptr, pk_len, + pk_hash_ptr, pk_hash_len); + } else { + /* Ask the crypto module to verify the signature */ + rc = crypto_mod_verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); + } + + return rc; +} + +/* + * Return the parent id in the output parameter '*parent_id' + * + * Return value: + * 0 = Image has parent, 1 = Image has no parent or parent is authenticated + */ +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id) +{ + const auth_img_desc_t *img_desc = NULL; + + assert(parent_id != NULL); + + /* Get the image descriptor */ + img_desc = &cot_desc_ptr[img_id]; + + /* Check if the image has no parent (ROT) */ + if (img_desc->parent == NULL) { + *parent_id = 0; + return 1; + } + + /* Check if the parent has already been authenticated */ + if (auth_img_flags[img_desc->parent->img_id] & IMG_FLAG_AUTHENTICATED) { + *parent_id = 0; + return 1; + } + + *parent_id = img_desc->parent->img_id; + return 0; +} + +/* + * Initialize the different modules in the authentication framework + */ +void auth_mod_init(void) +{ + /* Check we have a valid CoT registered */ + assert(cot_desc_ptr != NULL); + + /* Crypto module */ + crypto_mod_init(); + + /* Image parser module */ + img_parser_init(); +} + +/* + * Authenticate a certificate/image + * + * Return: 0 = success, Otherwise = error + */ +int auth_mod_verify_img(unsigned int img_id, + void *img_ptr, + unsigned int img_len) +{ + const auth_img_desc_t *img_desc = NULL; + const auth_method_desc_t *auth_method = NULL; + void *param_ptr; + unsigned int param_len; + int rc, i; + + /* Get the image descriptor from the chain of trust */ + img_desc = &cot_desc_ptr[img_id]; + + /* Ask the parser to check the image integrity */ + rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len); + return_if_error(rc); + + /* Authenticate the image using the methods indicated in the image + * descriptor. */ + for (i = 0 ; i < AUTH_METHOD_NUM ; i++) { + auth_method = &img_desc->img_auth_methods[i]; + switch (auth_method->type) { + case AUTH_METHOD_NONE: + rc = 0; + break; + case AUTH_METHOD_HASH: + rc = auth_hash(&auth_method->param.hash, + img_desc, img_ptr, img_len); + break; + case AUTH_METHOD_SIG: + rc = auth_signature(&auth_method->param.sig, + img_desc, img_ptr, img_len); + break; + default: + /* Unknown authentication method */ + rc = 1; + break; + } + return_if_error(rc); + } + + /* Extract the parameters indicated in the image descriptor to + * authenticate the children images. */ + for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) { + if (img_desc->authenticated_data[i].type_desc == NULL) { + continue; + } + + /* Get the parameter from the image parser module */ + rc = img_parser_get_auth_param(img_desc->img_type, + img_desc->authenticated_data[i].type_desc, + img_ptr, img_len, ¶m_ptr, ¶m_len); + return_if_error(rc); + + /* Check parameter size */ + if (param_len > img_desc->authenticated_data[i].data.len) { + return 1; + } + + /* Copy the parameter for later use */ + memcpy((void *)img_desc->authenticated_data[i].data.ptr, + (void *)param_ptr, param_len); + } + + /* Mark image as authenticated */ + auth_img_flags[img_desc->img_id] |= IMG_FLAG_AUTHENTICATED; + + return 0; +} diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c new file mode 100644 index 0000000..b432e6a --- /dev/null +++ b/drivers/auth/crypto_mod.c @@ -0,0 +1,129 @@ +/* + * 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 +#include +#include + +/* Variable exported by the crypto library through REGISTER_CRYPTO_LIB() */ +extern const crypto_lib_desc_t crypto_lib_desc; + +/* + * The crypto module is responsible for verifying digital signatures and hashes. + * It relies on a crypto library to perform the cryptographic operations. + * + * The crypto module itself does not impose any specific format on signatures, + * signature algorithm, keys or hashes, but most cryptographic libraries will + * take the parameters as the following DER encoded ASN.1 structures: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * SignatureAlgorithm ::= AlgorithmIdentifier + * + * SignatureValue ::= BIT STRING + */ + +/* + * Perform some static checking and call the library initialization function + */ +void crypto_mod_init(void) +{ + assert(crypto_lib_desc.name != NULL); + assert(crypto_lib_desc.init != NULL); + assert(crypto_lib_desc.verify_signature != NULL); + assert(crypto_lib_desc.verify_hash != NULL); + + /* Initialize the cryptographic library */ + crypto_lib_desc.init(); + INFO("Using crypto library '%s'\n", crypto_lib_desc.name); +} + +/* + * Function to verify a digital signature + * + * Parameters: + * + * data_ptr, data_len: signed data + * sig_ptr, sig_len: the digital signature + * sig_alg_ptr, sig_alg_len: the digital signature algorithm + * pk_ptr, pk_len: the public key + */ +int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg_ptr, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + assert(data_ptr != NULL); + assert(data_len != 0); + assert(sig_ptr != NULL); + assert(sig_len != 0); + assert(sig_alg_ptr != NULL); + assert(sig_alg_len != 0); + assert(pk_ptr != NULL); + assert(pk_len != 0); + + return crypto_lib_desc.verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); +} + +/* + * Verify a hash by comparison + * + * Parameters: + * + * data_ptr, data_len: data to be hashed + * digest_info_ptr, digest_info_len: hash to be compared + */ +int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + assert(data_ptr != NULL); + assert(data_len != 0); + assert(digest_info_ptr != NULL); + assert(digest_info_len != 0); + + return crypto_lib_desc.verify_hash(data_ptr, data_len, + digest_info_ptr, digest_info_len); +} diff --git a/drivers/auth/img_parser_mod.c b/drivers/auth/img_parser_mod.c new file mode 100644 index 0000000..c8cbe34 --- /dev/null +++ b/drivers/auth/img_parser_mod.c @@ -0,0 +1,151 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +extern uintptr_t __PARSER_LIB_DESCS_START__; +extern uintptr_t __PARSER_LIB_DESCS_END__; +#define PARSER_LIB_DESCS_START ((uintptr_t) (&__PARSER_LIB_DESCS_START__)) +#define PARSER_LIB_DESCS_END ((uintptr_t) (&__PARSER_LIB_DESCS_END__)) +static unsigned int parser_lib_indices[IMG_MAX_TYPES]; +static img_parser_lib_desc_t *parser_lib_descs; + +#define INVALID_IDX UINT_MAX + +static void validate_desc(img_parser_lib_desc_t *desc) +{ + assert(desc != NULL); + assert(desc->init != NULL); + assert(desc->name != NULL); + assert(desc->check_integrity != NULL); + assert(desc->get_auth_param != NULL); +} + +void img_parser_init(void) +{ + unsigned int index, mod_num; + + /* Initialise internal variables to invalid state */ + for (index = 0; index < IMG_MAX_TYPES; index++) { + parser_lib_indices[index] = INVALID_IDX; + } + + /* Calculate how many image parsers are registered. At least one parser + * must be present */ + mod_num = PARSER_LIB_DESCS_END - PARSER_LIB_DESCS_START; + mod_num /= sizeof(img_parser_lib_desc_t); + assert(mod_num > 0); + + parser_lib_descs = (img_parser_lib_desc_t *) PARSER_LIB_DESCS_START; + for (index = 0; index < mod_num; index++) { + + /* Check that the image parser library descriptor is valid */ + validate_desc(&parser_lib_descs[index]); + + /* Initialize image parser */ + parser_lib_descs[index].init(); + + /* Ensure only one parser is registered for each image type */ + assert(parser_lib_indices[parser_lib_descs[index].img_type] == + INVALID_IDX); + + /* Keep the index of this hash calculator */ + parser_lib_indices[parser_lib_descs[index].img_type] = index; + } +} + +int img_parser_check_integrity(img_type_t img_type, + void *img_ptr, unsigned int img_len) +{ + unsigned int idx; + + assert(img_ptr != NULL); + assert(img_len != 0); + + /* No integrity checks on raw images */ + if (img_type == IMG_RAW) { + return IMG_PARSER_OK; + } + + /* Find the index of the required image parser */ + idx = parser_lib_indices[img_type]; + assert(idx != INVALID_IDX); + + /* Call the function to check the image integrity */ + return parser_lib_descs[idx].check_integrity(img_ptr, img_len); +} + +/* + * Extract an authentication parameter from an image + * + * Parameters: + * img_type: image type (certificate, raw image, etc) + * type_desc: provides info to obtain the parameter + * img_ptr: pointer to image data + * img_len: image length + * param_ptr: [out] stores a pointer to the parameter + * param_len: [out] stores the length of the parameter + */ +int img_parser_get_auth_param(img_type_t img_type, + const auth_param_type_desc_t *type_desc, + void *img_ptr, unsigned int img_len, + void **param_ptr, unsigned int *param_len) +{ + unsigned int idx; + + assert(type_desc != NULL); + assert(img_ptr != NULL); + assert(img_len != 0); + assert(param_ptr != NULL); + assert(param_len != NULL); + + /* In a raw image we can only get the data itself */ + if (img_type == IMG_RAW) { + assert(type_desc->type == AUTH_PARAM_RAW_DATA); + *param_ptr = img_ptr; + *param_len = img_len; + return IMG_PARSER_OK; + } + + /* Find the index of the required image parser library */ + idx = parser_lib_indices[img_type]; + assert(idx != INVALID_IDX); + + /* Call the function to obtain the parameter */ + return parser_lib_descs[idx].get_auth_param(type_desc, img_ptr, img_len, + param_ptr, param_len); +} diff --git a/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c new file mode 100644 index 0000000..2978260 --- /dev/null +++ b/drivers/auth/mbedtls/mbedtls_common.c @@ -0,0 +1,65 @@ +/* + * 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 + +/* mbedTLS headers */ +#include + +/* + * mbedTLS heap + */ +#if (MBEDTLS_KEY_ALG_ID == MBEDTLS_ECDSA) +#define MBEDTLS_HEAP_SIZE (14*1024) +#elif (MBEDTLS_KEY_ALG_ID == MBEDTLS_RSA) +#define MBEDTLS_HEAP_SIZE (8*1024) +#endif +static unsigned char heap[MBEDTLS_HEAP_SIZE]; + +/* + * mbedTLS initialization function + * + * Return: 0 = success, Otherwise = error + */ +void mbedtls_init(void) +{ + static int ready; + int rc; + + if (!ready) { + /* Initialize the mbedTLS heap */ + rc = memory_buffer_alloc_init(heap, MBEDTLS_HEAP_SIZE); + if (rc == 0) { + ready = 1; + } else { + assert(0); + } + } +} diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk new file mode 100644 index 0000000..b71bbc9 --- /dev/null +++ b/drivers/auth/mbedtls/mbedtls_common.mk @@ -0,0 +1,60 @@ +# +# 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. +# + +ifneq (${MBEDTLS_COMMON_MK},1) +MBEDTLS_COMMON_MK := 1 + +# MBEDTLS_DIR must be set to the mbedTLS main directory (it must contain +# the 'include' and 'library' subdirectories). +ifeq (${MBEDTLS_DIR},) + $(error Error: MBEDTLS_DIR not set) +endif + +INCLUDES += -I${MBEDTLS_DIR}/include \ + -Iinclude/drivers/auth/mbedtls + +# Specify mbedTLS configuration file +POLARSSL_CONFIG_FILE := "" +$(eval $(call add_define,POLARSSL_CONFIG_FILE)) + +MBEDTLS_COMMON_SOURCES := drivers/auth/mbedtls/mbedtls_common.c \ + $(addprefix ${MBEDTLS_DIR}/library/, \ + asn1parse.c \ + asn1write.c \ + memory_buffer_alloc.c \ + oid.c \ + platform.c \ + ) + +BL1_SOURCES += ${MBEDTLS_COMMON_SOURCES} +BL2_SOURCES += ${MBEDTLS_COMMON_SOURCES} +DISABLE_PEDANTIC := 1 + +endif diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c new file mode 100644 index 0000000..f69f930 --- /dev/null +++ b/drivers/auth/mbedtls/mbedtls_crypto.c @@ -0,0 +1,229 @@ +/* + * 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 +#include +#include +#include +#include + +/* mbedTLS headers */ +#include +#include +#include +#include + +#define LIB_NAME "mbedTLS" + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + /* Initialize mbedTLS */ + mbedtls_init(); +} + +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + asn1_buf sig_oid, sig_params; + asn1_buf signature; + md_type_t md_alg; + pk_type_t pk_alg; + pk_context pk; + int rc; + void *sig_opts = NULL; + const md_info_t *md_info; + unsigned char *p, *end; + unsigned char hash[POLARSSL_MD_MAX_SIZE]; + + /* Get pointers to signature OID and parameters */ + p = (unsigned char *)sig_alg; + end = (unsigned char *)(p + sig_alg_len); + rc = asn1_get_alg(&p, end, &sig_oid, &sig_params); + if (rc != 0) { + return CRYPTO_ERR_SIGNATURE; + } + + /* Get the actual signature algorithm (MD + PK) */ + rc = oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); + if (rc != 0) { + return CRYPTO_ERR_SIGNATURE; + } + + /* Parse the public key */ + pk_init(&pk); + p = (unsigned char *)pk_ptr; + end = (unsigned char *)(p + pk_len); + rc = pk_parse_subpubkey(&p, end, &pk); + if (rc != 0) { + return CRYPTO_ERR_SIGNATURE; + } + + /* Get the signature (bitstring) */ + p = (unsigned char *)sig_ptr; + end = (unsigned char *)(p + sig_len); + signature.tag = *p; + rc = asn1_get_bitstring_null(&p, end, &signature.len); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end; + } + signature.p = p; + + /* Calculate the hash of the data */ + md_info = md_info_from_type(md_alg); + if (md_info == NULL) { + rc = CRYPTO_ERR_SIGNATURE; + goto end; + } + p = (unsigned char *)data_ptr; + rc = md(md_info, p, data_len, hash); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end; + } + + /* Verify the signature */ + rc = pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, + md_info->size, signature.p, signature.len); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end; + } + + /* Signature verification success */ + rc = CRYPTO_SUCCESS; + +end: + pk_free(&pk); + return rc; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + asn1_buf hash_oid, params; + md_type_t md_alg; + const md_info_t *md_info; + unsigned char *p, *end, *hash; + unsigned char data_hash[POLARSSL_MD_MAX_SIZE]; + size_t len; + int rc; + + /* Digest info should be an ASN1_SEQUENCE */ + p = (unsigned char *)digest_info_ptr; + end = (unsigned char *)(digest_info_ptr + digest_info_len); + rc = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Get the hash algorithm */ + rc = asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + rc = oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + md_info = md_info_from_type(md_alg); + if (md_info == NULL) { + return CRYPTO_ERR_HASH; + } + + /* Hash should be octet string type */ + rc = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Length of hash must match the algorithm's size */ + if (len != md_info->size) { + return CRYPTO_ERR_HASH; + } + hash = p; + + /* Calculate the hash of the data */ + p = (unsigned char *)data_ptr; + rc = md(md_info, p, data_len, data_hash); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Compare values */ + rc = memcmp(data_hash, hash, md_info->size); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + return CRYPTO_SUCCESS; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash); diff --git a/drivers/auth/mbedtls/mbedtls_crypto.mk b/drivers/auth/mbedtls/mbedtls_crypto.mk new file mode 100644 index 0000000..67d2eb4 --- /dev/null +++ b/drivers/auth/mbedtls/mbedtls_crypto.mk @@ -0,0 +1,72 @@ +# +# 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 drivers/auth/mbedtls/mbedtls_common.mk + +# The platform may define the variable 'MBEDTLS_KEY_ALG' to select the key +# algorithm to use. Default algorithm is ECDSA. +ifeq (${MBEDTLS_KEY_ALG},) + MBEDTLS_KEY_ALG := rsa +endif + +MBEDTLS_CRYPTO_SOURCES := drivers/auth/mbedtls/mbedtls_crypto.c \ + $(addprefix ${MBEDTLS_DIR}/library/, \ + bignum.c \ + md.c \ + md_wrap.c \ + pk.c \ + pk_wrap.c \ + pkparse.c \ + pkwrite.c \ + sha256.c \ + ) + +# Key algorithm specific files +ifeq (${MBEDTLS_KEY_ALG},ecdsa) + MBEDTLS_CRYPTO_SOURCES += $(addprefix ${MBEDTLS_DIR}/library/, \ + ecdsa.c \ + ecp_curves.c \ + ecp.c \ + ) + MBEDTLS_KEY_ALG_ID := MBEDTLS_ECDSA +else ifeq (${MBEDTLS_KEY_ALG},rsa) + MBEDTLS_CRYPTO_SOURCES += $(addprefix ${MBEDTLS_DIR}/library/, \ + rsa.c \ + ) + MBEDTLS_KEY_ALG_ID := MBEDTLS_RSA +else + $(error "MBEDTLS_KEY_ALG=${MBEDTLS_KEY_ALG} not supported on mbedTLS") +endif + +# mbedTLS libraries rely on this define to build correctly +$(eval $(call add_define,MBEDTLS_KEY_ALG_ID)) + +BL1_SOURCES += ${MBEDTLS_CRYPTO_SOURCES} +BL2_SOURCES += ${MBEDTLS_CRYPTO_SOURCES} diff --git a/drivers/auth/mbedtls/mbedtls_x509.mk b/drivers/auth/mbedtls/mbedtls_x509.mk new file mode 100644 index 0000000..3f9420d --- /dev/null +++ b/drivers/auth/mbedtls/mbedtls_x509.mk @@ -0,0 +1,40 @@ +# +# 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 drivers/auth/mbedtls/mbedtls_common.mk + +MBEDTLS_X509_SOURCES := drivers/auth/mbedtls/mbedtls_x509_parser.c \ + $(addprefix ${MBEDTLS_DIR}/library/, \ + x509.c \ + x509_crt.c \ + ) + +BL1_SOURCES += ${MBEDTLS_X509_SOURCES} +BL2_SOURCES += ${MBEDTLS_X509_SOURCES} diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c new file mode 100644 index 0000000..a8605ce --- /dev/null +++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c @@ -0,0 +1,438 @@ +/* + * 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. + */ + +/* + * X509 parser based on PolarSSL + * + * This module implements functions to check the integrity of a X509v3 + * certificate ASN.1 structure and extract authentication parameters from the + * extensions field, such as an image hash or a public key. + */ + +#include +#include +#include +#include +#include +#include + +/* mbedTLS headers */ +#include +#include +#include + +/* Maximum OID string length ("a.b.c.d.e.f ...") */ +#define MAX_OID_STR_LEN 64 + +#define LIB_NAME "mbedTLS X509v3" + +/* Temporary variables to speed up the authentication parameters search. These + * variables are assigned once during the integrity check and used any time an + * authentication parameter is requested, so we do not have to parse the image + * again */ +static asn1_buf tbs; +static asn1_buf v3_ext; +static asn1_buf pk; +static asn1_buf sig_alg; +static asn1_buf signature; + +/* + * Get X509v3 extension + * + * Global variable 'v3_ext' must point to the extensions region + * in the certificate. No need to check for errors since the image has passed + * the integrity check. + */ +static int get_ext(const char *oid, void **ext, unsigned int *ext_len) +{ + int oid_len; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + unsigned char *p; + const unsigned char *end; + char oid_str[MAX_OID_STR_LEN]; + asn1_buf extn_oid; + int is_critical; + + assert(oid != NULL); + + p = v3_ext.p; + end = v3_ext.p + v3_ext.len; + + asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + + while (p < end) { + memset(&extn_oid, 0x0, sizeof(extn_oid)); + is_critical = 0; /* DEFAULT FALSE */ + + asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + end_ext_data = p + len; + + /* Get extension ID */ + extn_oid.tag = *p; + asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID); + extn_oid.p = p; + p += extn_oid.len; + + /* Get optional critical */ + asn1_get_bool(&p, end_ext_data, &is_critical); + + /* Extension data */ + asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING); + end_ext_octet = p + len; + + /* Detect requested extension */ + oid_len = oid_get_numeric_string(oid_str, + MAX_OID_STR_LEN, &extn_oid); + if (oid_len == POLARSSL_ERR_OID_BUF_TOO_SMALL) { + return IMG_PARSER_ERR; + } + if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { + *ext = (void *)p; + *ext_len = (unsigned int)len; + return IMG_PARSER_OK; + } + + /* Next */ + p = end_ext_octet; + } + + return IMG_PARSER_ERR_NOT_FOUND; +} + + +/* + * Check the integrity of the certificate ASN.1 structure. + * Extract the relevant data that will be used later during authentication. + */ +static int cert_parse(void *img, unsigned int img_len) +{ + int ret, is_critical; + size_t len; + unsigned char *p, *end, *crt_end; + asn1_buf sig_alg1, sig_alg2; + + p = (unsigned char *)img; + len = img_len; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + if (len > (size_t)(end - p)) { + return IMG_PARSER_ERR_FORMAT; + } + crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + tbs.p = p; + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + end = p + len; + tbs.len = end - tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + ret = asn1_get_tag(&p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * CertificateSerialNumber ::= INTEGER + */ + ret = asn1_get_tag(&p, end, &len, ASN1_INTEGER); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * signature AlgorithmIdentifier + */ + sig_alg1.p = p; + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + if ((end - p) < 1) { + return IMG_PARSER_ERR_FORMAT; + } + sig_alg1.len = (p + len) - sig_alg1.p; + p += len; + + /* + * issuer Name + */ + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * subject Name + */ + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * SubjectPublicKeyInfo + */ + pk.p = p; + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + pk.len = (p + len) - pk.p; + p += len; + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + */ + ret = asn1_get_tag(&p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1); + if (ret != 0) { + if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) { + return IMG_PARSER_ERR_FORMAT; + } + } else { + p += len; + } + + /* + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + */ + ret = asn1_get_tag(&p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2); + if (ret != 0) { + if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) { + return IMG_PARSER_ERR_FORMAT; + } + } else { + p += len; + } + + /* + * extensions [3] EXPLICIT Extensions OPTIONAL + */ + ret = asn1_get_tag(&p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + v3_ext.p = p; + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + v3_ext.len = (p + len) - v3_ext.p; + + /* + * Check extensions integrity + */ + while (p < end) { + ret = asn1_get_tag(&p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + /* Get extension ID */ + ret = asn1_get_tag(&p, end, &len, ASN1_OID); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* Get optional critical */ + ret = asn1_get_bool(&p, end, &is_critical); + if ((ret != 0) && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG)) { + return IMG_PARSER_ERR_FORMAT; + } + + /* Data should be octet string type */ + ret = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + } + + if (p != end) { + return IMG_PARSER_ERR_FORMAT; + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier + */ + sig_alg2.p = p; + ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + if ((end - p) < 1) { + return IMG_PARSER_ERR_FORMAT; + } + sig_alg2.len = (p + len) - sig_alg2.p; + p += len; + + /* Compare both signature algorithms */ + if (sig_alg1.len != sig_alg2.len) { + return IMG_PARSER_ERR_FORMAT; + } + if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) { + return IMG_PARSER_ERR_FORMAT; + } + memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg)); + + /* + * signatureValue BIT STRING + */ + signature.p = p; + ret = asn1_get_tag(&p, end, &len, ASN1_BIT_STRING); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + signature.len = (p + len) - signature.p; + p += len; + + /* Check certificate length */ + if (p != end) { + return IMG_PARSER_ERR_FORMAT; + } + + return IMG_PARSER_OK; +} + + +/* Exported functions */ + +static void init(void) +{ + mbedtls_init(); +} + +static int check_integrity(void *img, unsigned int img_len) +{ + return cert_parse(img, img_len); +} + +/* + * Extract an authentication parameter from an X509v3 certificate + */ +static int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len) +{ + int rc = IMG_PARSER_OK; + + /* We do not use img because the check_integrity function has already + * extracted the relevant data (v3_ext, pk, sig_alg, etc) */ + + switch (type_desc->type) { + case AUTH_PARAM_RAW_DATA: + /* Data to be signed */ + *param = (void *)tbs.p; + *param_len = (unsigned int)tbs.len; + break; + case AUTH_PARAM_HASH: + /* All these parameters are included as X509v3 extensions */ + rc = get_ext(type_desc->cookie, param, param_len); + break; + case AUTH_PARAM_PUB_KEY: + if (type_desc->cookie != 0) { + /* Get public key from extension */ + rc = get_ext(type_desc->cookie, param, param_len); + } else { + /* Get the subject public key */ + *param = (void *)pk.p; + *param_len = (unsigned int)pk.len; + } + break; + case AUTH_PARAM_SIG_ALG: + /* Get the certificate signature algorithm */ + *param = (void *)sig_alg.p; + *param_len = (unsigned int)sig_alg.len; + break; + case AUTH_PARAM_SIG: + /* Get the certificate signature */ + *param = (void *)signature.p; + *param_len = (unsigned int)signature.len; + break; + default: + rc = IMG_PARSER_ERR_NOT_FOUND; + break; + } + + return rc; +} + +REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \ + check_integrity, get_auth_param); diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c new file mode 100644 index 0000000..79a8965 --- /dev/null +++ b/drivers/auth/tbbr/tbbr_cot.c @@ -0,0 +1,445 @@ +/* + * 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 +#include +#include +#include + +/* + * Maximum key and hash sizes (in DER format) + */ +#define PK_DER_LEN 294 +#define HASH_DER_LEN 51 + +/* + * The platform must allocate buffers to store the authentication parameters + * extracted from the certificates. In this case, because of the way the CoT is + * established, we can reuse some of the buffers on different stages + */ +static unsigned char plat_bl2_hash_buf[HASH_DER_LEN]; +static unsigned char plat_bl30_hash_buf[HASH_DER_LEN]; +static unsigned char plat_bl31_hash_buf[HASH_DER_LEN]; +static unsigned char plat_bl32_hash_buf[HASH_DER_LEN]; +static unsigned char plat_bl33_hash_buf[HASH_DER_LEN]; +static unsigned char plat_tz_world_pk_buf[PK_DER_LEN]; +static unsigned char plat_ntz_world_pk_buf[PK_DER_LEN]; +static unsigned char plat_content_pk[PK_DER_LEN]; + +/* + * Parameter type descriptors + */ +static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, 0); +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + +static auth_param_type_desc_t tz_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TZ_WORLD_PK_OID); +static auth_param_type_desc_t ntz_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NTZ_WORLD_PK_OID); + +static auth_param_type_desc_t bl30_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, BL30_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t bl31_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, BL31_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t bl32_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, BL32_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t bl33_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, BL33_CONTENT_CERT_PK_OID); + +static auth_param_type_desc_t bl2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, BL2_HASH_OID); +static auth_param_type_desc_t bl30_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, BL30_HASH_OID); +static auth_param_type_desc_t bl31_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, BL31_HASH_OID); +static auth_param_type_desc_t bl32_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, BL32_HASH_OID); +static auth_param_type_desc_t bl33_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, BL33_HASH_OID); + +/* + * TBBR Chain of trust definition + */ +static const auth_img_desc_t cot_desc[] = { + /* + * BL2 + */ + [BL2_CERT_ID] = { + .img_id = BL2_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl2_hash, + .data = { + .ptr = (void *)plat_bl2_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }, + [BL2_IMAGE_ID] = { + .img_id = BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &cot_desc[BL2_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl2_hash, + } + } + } + }, + /* + * Trusted key certificate + */ + [TRUSTED_KEY_CERT_ID] = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &tz_world_pk, + .data = { + .ptr = (void *)plat_tz_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &ntz_world_pk, + .data = { + .ptr = (void *)plat_ntz_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } + }, + /* + * BL3-0 + */ + [BL30_KEY_CERT_ID] = { + .img_id = BL30_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[TRUSTED_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tz_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl30_content_pk, + .data = { + .ptr = (void *)plat_content_pk, + .len = (unsigned int)PK_DER_LEN + } + } + } + }, + [BL30_CERT_ID] = { + .img_id = BL30_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[BL30_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &bl30_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl30_hash, + .data = { + .ptr = (void *)plat_bl30_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }, + [BL30_IMAGE_ID] = { + .img_id = BL30_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &cot_desc[BL30_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl30_hash, + } + } + } + }, + /* + * BL3-1 + */ + [BL31_KEY_CERT_ID] = { + .img_id = BL31_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[TRUSTED_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tz_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl31_content_pk, + .data = { + .ptr = (void *)plat_content_pk, + .len = (unsigned int)PK_DER_LEN + } + } + } + }, + [BL31_CERT_ID] = { + .img_id = BL31_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[BL31_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &bl31_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl31_hash, + .data = { + .ptr = (void *)plat_bl31_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }, + [BL31_IMAGE_ID] = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &cot_desc[BL31_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl31_hash, + } + } + } + }, + /* + * BL3-2 + */ + [BL32_KEY_CERT_ID] = { + .img_id = BL32_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[TRUSTED_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tz_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl32_content_pk, + .data = { + .ptr = (void *)plat_content_pk, + .len = (unsigned int)PK_DER_LEN + } + } + } + }, + [BL32_CERT_ID] = { + .img_id = BL32_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[BL32_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &bl32_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl32_hash, + .data = { + .ptr = (void *)plat_bl32_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }, + [BL32_IMAGE_ID] = { + .img_id = BL32_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &cot_desc[BL32_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl32_hash, + } + } + } + }, + /* + * BL3-3 + */ + [BL33_KEY_CERT_ID] = { + .img_id = BL33_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[TRUSTED_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &ntz_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl33_content_pk, + .data = { + .ptr = (void *)plat_content_pk, + .len = (unsigned int)PK_DER_LEN + } + } + } + }, + [BL33_CERT_ID] = { + .img_id = BL33_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[BL33_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &bl33_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &bl33_hash, + .data = { + .ptr = (void *)plat_bl33_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }, + [BL33_IMAGE_ID] = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &cot_desc[BL33_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl33_hash, + } + } + } + } +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c index 9dcd901..5a8a294 100644 --- a/drivers/io/io_fip.c +++ b/drivers/io/io_fip.c @@ -51,11 +51,6 @@ x.node[4], x.node[5] typedef struct { - const char *name; - const uuid_t uuid; -} plat_fip_name_uuid_t; - -typedef struct { /* Put file_pos above the struct to allow {0} on static init. * It is a workaround for a known bug in GCC * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 @@ -64,37 +59,6 @@ fip_toc_entry_t entry; } file_state_t; -static const plat_fip_name_uuid_t name_uuid[] = { - {BL2_IMAGE_NAME, UUID_TRUSTED_BOOT_FIRMWARE_BL2}, -#ifdef BL30_IMAGE_NAME - /* BL3-0 is optional in the platform */ - {BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30}, -#endif /* BL30_IMAGE_NAME */ - {BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31}, -#ifdef BL32_IMAGE_NAME - /* BL3-2 is optional in the platform */ - {BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32}, -#endif /* BL32_IMAGE_NAME */ - {BL33_IMAGE_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33}, -#if TRUSTED_BOARD_BOOT - /* Certificates */ - {BL2_CERT_NAME, UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT}, - {TRUSTED_KEY_CERT_NAME, UUID_TRUSTED_KEY_CERT}, -#ifdef BL30_KEY_CERT_NAME - {BL30_KEY_CERT_NAME, UUID_SCP_FIRMWARE_BL30_KEY_CERT}, -#endif - {BL31_KEY_CERT_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT}, - {BL32_KEY_CERT_NAME, UUID_SECURE_PAYLOAD_BL32_KEY_CERT}, - {BL33_KEY_CERT_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT}, -#ifdef BL30_CERT_NAME - {BL30_CERT_NAME, UUID_SCP_FIRMWARE_BL30_CERT}, -#endif - {BL31_CERT_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT}, - {BL32_CERT_NAME, UUID_SECURE_PAYLOAD_BL32_CERT}, - {BL33_CERT_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33_CERT}, -#endif /* TRUSTED_BOARD_BOOT */ -}; - static const uuid_t uuid_null = {0}; static file_state_t current_file = {0}; static uintptr_t backend_dev_handle; @@ -113,13 +77,6 @@ static int fip_dev_close(io_dev_info_t *dev_info); -static inline int copy_uuid(uuid_t *dst, const uuid_t *src) -{ - memcpy(dst, src, sizeof(uuid_t)); - return 0; -} - - /* Return 0 for equal uuids. */ static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2) { @@ -138,22 +95,6 @@ } -static int file_to_uuid(const char *filename, uuid_t *uuid) -{ - int i; - int status = -EINVAL; - - for (i = 0; i < ARRAY_SIZE(name_uuid); i++) { - if (strcmp(filename, name_uuid[i].name) == 0) { - copy_uuid(uuid, &name_uuid[i].uuid); - status = 0; - break; - } - } - return status; -} - - /* Identify the device type as a virtual driver */ io_type_t device_type_fip(void) { @@ -201,17 +142,17 @@ static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) { int result = IO_FAIL; - char *image_name = (char *)init_params; + unsigned int image_id = (unsigned int)init_params; uintptr_t backend_handle; fip_toc_header_t header; size_t bytes_read; /* Obtain a reference to the image by querying the platform layer */ - result = plat_get_image_source(image_name, &backend_dev_handle, + result = plat_get_image_source(image_id, &backend_dev_handle, &backend_image_spec); if (result != IO_SUCCESS) { - WARN("Failed to obtain reference to image '%s' (%i)\n", - image_name, result); + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, result); result = IO_FAIL; goto fip_dev_init_exit; } @@ -220,7 +161,7 @@ result = io_open(backend_dev_handle, backend_image_spec, &backend_handle); if (result != IO_SUCCESS) { - WARN("Failed to access image '%s' (%i)\n", image_name, result); + WARN("Failed to access image id=%u (%i)\n", image_id, result); result = IO_FAIL; goto fip_dev_init_exit; } @@ -261,12 +202,11 @@ { int result = IO_FAIL; uintptr_t backend_handle; - uuid_t file_uuid; - const io_file_spec_t *file_spec = (io_file_spec_t *)spec; + const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec; size_t bytes_read; int found_file = 0; - assert(file_spec != NULL); + assert(uuid_spec != NULL); assert(entity != NULL); /* Can only have one file open at a time for the moment. We need to @@ -297,8 +237,6 @@ goto fip_file_open_close; } - file_to_uuid(file_spec->path, &file_uuid); - found_file = 0; do { result = io_read(backend_handle, @@ -307,7 +245,7 @@ &bytes_read); if (result == IO_SUCCESS) { if (compare_uuids(¤t_file.entry.uuid, - &file_uuid) == 0) { + &uuid_spec->uuid) == 0) { found_file = 1; break; } diff --git a/include/common/auth.h b/include/common/auth.h deleted file mode 100644 index 3c3a6bd..0000000 --- a/include/common/auth.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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. - */ - -#ifndef AUTH_H_ -#define AUTH_H_ - -#include -#include - -/* - * Authentication infrastructure for Trusted Boot - * - * This infrastructure provides an API to access the authentication module. This - * module will implement the required operations for Trusted Boot by creating an - * instance of the structure 'auth_mod_t'. This instance must be called - * 'auth_mod' and must provide the functions to initialize the module and - * verify the authenticity of the images. - */ - -/* Objects (images and certificates) involved in the TBB process */ -enum { - AUTH_BL2_IMG_CERT, - AUTH_BL2_IMG, - AUTH_TRUSTED_KEY_CERT, - AUTH_BL30_KEY_CERT, - AUTH_BL30_IMG_CERT, - AUTH_BL30_IMG, - AUTH_BL31_KEY_CERT, - AUTH_BL31_IMG_CERT, - AUTH_BL31_IMG, - AUTH_BL32_KEY_CERT, - AUTH_BL32_IMG_CERT, - AUTH_BL32_IMG, - AUTH_BL33_KEY_CERT, - AUTH_BL33_IMG_CERT, - AUTH_BL33_IMG, - AUTH_NUM_OBJ -}; - -/* Authentication module structure */ -typedef struct auth_mod_s { - /* [mandatory] Module name. Printed to the log during initialization */ - const char *name; - - /* [mandatory] Initialize the authentication module */ - int (*init)(void); - - /* [mandatory] This function will be called to authenticate a new - * object loaded into memory. The obj_id corresponds to one of the - * values in the enumeration above */ - int (*verify)(unsigned int obj_id, uintptr_t obj_buf, size_t len); -} auth_mod_t; - -/* This variable must be instantiated by the authentication module */ -extern const auth_mod_t auth_mod; - -/* Public functions */ -void auth_init(void); -int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len); - -#endif /* AUTH_H_ */ diff --git a/include/common/bl_common.h b/include/common/bl_common.h index 985ec0d..b1a9c8f 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -226,12 +226,17 @@ ******************************************************************************/ unsigned long page_align(unsigned long, unsigned); void change_security_state(unsigned int); -unsigned long image_size(const char *); +unsigned long image_size(unsigned int image_id); int load_image(meminfo_t *mem_layout, - const char *image_name, - uint64_t image_base, + unsigned int image_id, + uintptr_t image_base, image_info_t *image_data, entry_point_info_t *entry_point_info); +int load_auth_image(meminfo_t *mem_layout, + unsigned int image_name, + uintptr_t image_base, + image_info_t *image_data, + entry_point_info_t *entry_point_info); extern const char build_message[]; extern const char version_string[]; diff --git a/include/common/tbbr/cot_def.h b/include/common/tbbr/cot_def.h new file mode 100644 index 0000000..d6dca4a --- /dev/null +++ b/include/common/tbbr/cot_def.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#ifndef __COT_DEF_H__ +#define __COT_DEF_H__ + +/* TBBR CoT definitions */ + +#define COT_MAX_VERIFIED_PARAMS 4 + +#endif /* __COT_DEF_H__ */ diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h new file mode 100644 index 0000000..c43c395 --- /dev/null +++ b/include/common/tbbr/tbbr_img_def.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef __TBBR_IMG_DEF_H__ +#define __TBBR_IMG_DEF_H__ + +/* Firmware Image Package */ +#define FIP_IMAGE_ID 0 + +/* Trusted Boot Firmware BL2 */ +#define BL2_IMAGE_ID 1 + +/* SCP Firmware BL3-0 */ +#define BL30_IMAGE_ID 2 + +/* EL3 Runtime Firmware BL31 */ +#define BL31_IMAGE_ID 3 + +/* Secure Payload BL32 (Trusted OS) */ +#define BL32_IMAGE_ID 4 + +/* Non-Trusted Firmware BL33 */ +#define BL33_IMAGE_ID 5 + +/* Certificates */ +#define BL2_CERT_ID 6 +#define TRUSTED_KEY_CERT_ID 7 + +#define BL30_KEY_CERT_ID 8 +#define BL31_KEY_CERT_ID 9 +#define BL32_KEY_CERT_ID 10 +#define BL33_KEY_CERT_ID 11 + +#define BL30_CERT_ID 12 +#define BL31_CERT_ID 13 +#define BL32_CERT_ID 14 +#define BL33_CERT_ID 15 + +#endif /* __TBBR_IMG_DEF_H__ */ diff --git a/include/drivers/auth/auth_common.h b/include/drivers/auth/auth_common.h new file mode 100644 index 0000000..52a895e --- /dev/null +++ b/include/drivers/auth/auth_common.h @@ -0,0 +1,141 @@ +/* + * 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. + */ + +#ifndef __AUTH_COMMON_H__ +#define __AUTH_COMMON_H__ + +/* + * Authentication framework common types + */ + +/* + * Type of parameters that can be extracted from an image and + * used for authentication + */ +typedef enum auth_param_type_enum { + AUTH_PARAM_NONE, + AUTH_PARAM_RAW_DATA, /* Raw image data */ + AUTH_PARAM_SIG, /* The image signature */ + AUTH_PARAM_SIG_ALG, /* The image signature algorithm */ + AUTH_PARAM_HASH, /* A hash (including the algorithm) */ + AUTH_PARAM_PUB_KEY, /* A public key */ +} auth_param_type_t; + +/* + * Defines an authentication parameter. The cookie will be interpreted by the + * image parser module. + */ +typedef struct auth_param_type_desc_s { + auth_param_type_t type; + void *cookie; +} auth_param_type_desc_t; + +/* + * Store a pointer to the authentication parameter and its length + */ +typedef struct auth_param_data_desc_s { + void *ptr; + unsigned int len; +} auth_param_data_desc_t; + +/* + * Authentication parameter descriptor, including type and value + */ +typedef struct auth_param_desc_s { + auth_param_type_desc_t *type_desc; + auth_param_data_desc_t data; +} auth_param_desc_t; + +/* + * The method type defines how an image is authenticated + */ +typedef enum auth_method_type_enum { + AUTH_METHOD_NONE = 0, + AUTH_METHOD_HASH, /* Authenticate by hash matching */ + AUTH_METHOD_SIG, /* Authenticate by PK operation */ + AUTH_METHOD_NUM /* Number of methods */ +} auth_method_type_t; + +/* + * Parameters for authentication by hash matching + */ +typedef struct auth_method_param_hash_s { + auth_param_type_desc_t *data; /* Data to hash */ + auth_param_type_desc_t *hash; /* Hash to match with */ +} auth_method_param_hash_t; + +/* + * Parameters for authentication by signature + */ +typedef struct auth_method_param_sig_s { + auth_param_type_desc_t *pk; /* Public key */ + auth_param_type_desc_t *sig; /* Signature to check */ + auth_param_type_desc_t *alg; /* Signature algorithm */ + auth_param_type_desc_t *data; /* Data signed */ +} auth_method_param_sig_t; + +/* + * Parameters for authentication by NV counter + */ +typedef struct auth_method_param_nv_ctr_s { + auth_param_type_desc_t *nv_ctr; /* NV counter value */ +} auth_method_param_nv_ctr_t; + +/* + * Authentication method descriptor + */ +typedef struct auth_method_desc_s { + auth_method_type_t type; + union { + auth_method_param_hash_t hash; + auth_method_param_sig_t sig; + auth_method_param_nv_ctr_t nv_ctr; + } param; +} auth_method_desc_t; + +/* + * Helper macro to define an authentication parameter type descriptor + */ +#define AUTH_PARAM_TYPE_DESC(_type, _cookie) \ + { \ + .type = _type, \ + .cookie = (void *)_cookie \ + } + +/* + * Helper macro to define an authentication parameter data descriptor + */ +#define AUTH_PARAM_DATA_DESC(_ptr, _len) \ + { \ + .ptr = (void *)_ptr, \ + .len = (unsigned int)_len \ + } + +#endif /* __AUTH_COMMON_H__ */ diff --git a/include/drivers/auth/auth_mod.h b/include/drivers/auth/auth_mod.h new file mode 100644 index 0000000..0f19b5c --- /dev/null +++ b/include/drivers/auth/auth_mod.h @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#ifndef __AUTH_MOD_H__ +#define __AUTH_MOD_H__ + +#if TRUSTED_BOARD_BOOT + +#include +#include +#include + +/* + * Image flags + */ +#define IMG_FLAG_AUTHENTICATED (1 << 0) + + +/* + * Authentication image descriptor + */ +typedef struct auth_img_desc_s { + unsigned int img_id; + const struct auth_img_desc_s *parent; + img_type_t img_type; + auth_method_desc_t img_auth_methods[AUTH_METHOD_NUM]; + auth_param_desc_t authenticated_data[COT_MAX_VERIFIED_PARAMS]; +} auth_img_desc_t; + +/* Public functions */ +void auth_mod_init(void); +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id); +int auth_mod_verify_img(unsigned int img_id, + void *img_ptr, + unsigned int img_len); + +/* Macro to register a CoT defined as an array of auth_img_desc_t */ +#define REGISTER_COT(_cot) \ + const auth_img_desc_t *const cot_desc_ptr = \ + (const auth_img_desc_t *const)&_cot[0]; \ + unsigned int auth_img_flags[sizeof(_cot)/sizeof(_cot[0])]; + +#endif /* TRUSTED_BOARD_BOOT */ + +#endif /* __AUTH_MOD_H__ */ diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h new file mode 100644 index 0000000..5a55624 --- /dev/null +++ b/include/drivers/auth/crypto_mod.h @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#ifndef __CRYPTO_MOD_H__ +#define __CRYPTO_MOD_H__ + +/* Return values */ +enum crypto_ret_value { + CRYPTO_SUCCESS = 0, + CRYPTO_ERR_INIT, + CRYPTO_ERR_HASH, + CRYPTO_ERR_SIGNATURE, + CRYPTO_ERR_UNKNOWN +}; + +/* + * Cryptographic library descriptor + */ +typedef struct crypto_lib_desc_s { + const char *name; + + /* Initialize library. This function is not expected to fail. All errors + * must be handled inside the function, asserting or panicing in case of + * a non-recoverable error */ + void (*init)(void); + + /* Verify a digital signature. Return one of the + * 'enum crypto_ret_value' options */ + int (*verify_signature)(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); + + /* Verify a hash. Return one of the 'enum crypto_ret_value' options */ + int (*verify_hash)(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); +} crypto_lib_desc_t; + +/* Public functions */ +void crypto_mod_init(void); +int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); +int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + +/* Macro to register a cryptographic library */ +#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash) \ + const crypto_lib_desc_t crypto_lib_desc = { \ + .name = _name, \ + .init = _init, \ + .verify_signature = _verify_signature, \ + .verify_hash = _verify_hash \ + } + +#endif /* __CRYPTO_MOD_H__ */ diff --git a/include/drivers/auth/img_parser_mod.h b/include/drivers/auth/img_parser_mod.h new file mode 100644 index 0000000..d80e0fb --- /dev/null +++ b/include/drivers/auth/img_parser_mod.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#ifndef __IMG_PARSER_MOD_H__ +#define __IMG_PARSER_MOD_H__ + +#include + +/* + * Return values + */ +enum img_parser_ret_value { + IMG_PARSER_OK, + IMG_PARSER_ERR, /* Parser internal error */ + IMG_PARSER_ERR_FORMAT, /* Malformed image */ + IMG_PARSER_ERR_NOT_FOUND /* Authentication data not found */ +}; + +/* + * Image types. A parser should be instantiated and registered for each type + */ +typedef enum img_type_enum { + IMG_RAW, /* Binary image */ + IMG_PLAT, /* Platform specific format */ + IMG_CERT, /* X509v3 certificate */ + IMG_MAX_TYPES, +} img_type_t; + +/* Image parser library structure */ +typedef struct img_parser_lib_desc_s { + img_type_t img_type; + const char *name; + + void (*init)(void); + int (*check_integrity)(void *img, unsigned int img_len); + int (*get_auth_param)(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); +} img_parser_lib_desc_t; + +/* Exported functions */ +void img_parser_init(void); +int img_parser_check_integrity(img_type_t img_type, + void *img, unsigned int img_len); +int img_parser_get_auth_param(img_type_t img_type, + const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param_ptr, unsigned int *param_len); + +/* Macro to register an image parser library */ +#define REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param) \ + static const img_parser_lib_desc_t __img_parser_lib_desc_##_type \ + __attribute__ ((section(".img_parser_lib_descs"), used)) = { \ + .img_type = _type, \ + .name = _name, \ + .init = _init, \ + .check_integrity = _check_int, \ + .get_auth_param = _get_param \ + } + +#endif /* __IMG_PARSER_MOD_H__ */ diff --git a/include/drivers/auth/mbedtls/mbedtls_common.h b/include/drivers/auth/mbedtls/mbedtls_common.h new file mode 100644 index 0000000..eb22e8a --- /dev/null +++ b/include/drivers/auth/mbedtls/mbedtls_common.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef __MBEDTLS_COMMON_H__ +#define __MBEDTLS_COMMON_H__ + +void mbedtls_init(void); + +#endif /* __MBEDTLS_COMMON_H__ */ diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h new file mode 100644 index 0000000..8a000f0 --- /dev/null +++ b/include/drivers/auth/mbedtls/mbedtls_config.h @@ -0,0 +1,99 @@ +/* + * 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. + */ +#ifndef __MBEDTLS_CONFIG_H__ +#define __MBEDTLS_CONFIG_H__ + +/* + * Key algorithms currently supported on mbedTLS libraries + */ +#define MBEDTLS_RSA 1 +#define MBEDTLS_ECDSA 2 + +/* + * Configuration file to build PolarSSL with the required features for + * Trusted Boot + */ + +#define POLARSSL_PLATFORM_MEMORY +#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS + +#define POLARSSL_PKCS1_V15 +#define POLARSSL_PKCS1_V21 + +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#define POLARSSL_X509_CHECK_KEY_USAGE +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE + +#define POLARSSL_ASN1_PARSE_C +#define POLARSSL_ASN1_WRITE_C + +#define POLARSSL_BASE64_C +#define POLARSSL_BIGNUM_C + +#define POLARSSL_ERROR_C +#define POLARSSL_MD_C + +#define POLARSSL_MEMORY_BUFFER_ALLOC_C +#define POLARSSL_OID_C + +#define POLARSSL_PK_C +#define POLARSSL_PK_PARSE_C +#define POLARSSL_PK_WRITE_C + +#define POLARSSL_PLATFORM_C + +#if (MBEDTLS_KEY_ALG_ID == MBEDTLS_ECDSA) +#define POLARSSL_ECDSA_C +#define POLARSSL_ECP_C +#define POLARSSL_ECP_DP_SECP256R1_ENABLED +#elif (MBEDTLS_KEY_ALG_ID == MBEDTLS_RSA) +#define POLARSSL_RSA_C +#endif + +#define POLARSSL_SHA256_C + +#define POLARSSL_VERSION_C + +#define POLARSSL_X509_USE_C +#define POLARSSL_X509_CRT_PARSE_C + +/* MPI / BIGNUM options */ +#define POLARSSL_MPI_WINDOW_SIZE 2 +#define POLARSSL_MPI_MAX_SIZE 256 + +/* Memory buffer allocator options */ +#define POLARSSL_MEMORY_ALIGN_MULTIPLE 8 + +#include "polarssl/check_config.h" + +/* System headers required to build mbedTLS with the current configuration */ +#include + +#endif /* __MBEDTLS_CONFIG_H__ */ diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h index ae1158c..e98dcd0 100644 --- a/include/drivers/io/io_storage.h +++ b/include/drivers/io/io_storage.h @@ -33,6 +33,7 @@ #include #include /* For ssize_t */ +#include /* Device type which can be used to enable policy decisions about which device @@ -67,6 +68,11 @@ unsigned int mode; } io_file_spec_t; +/* UUID specification - used to refer to data accessed using UUIDs (i.e. FIP + * images) */ +typedef struct io_uuid_spec { + const uuid_t uuid; +} io_uuid_spec_t; /* Block specification - used to refer to data on a device supporting * block-like entities */ diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h index 21dee7e..3abf235 100644 --- a/include/plat/arm/board/common/board_arm_def.h +++ b/include/plat/arm/board/common/board_arm_def.h @@ -64,29 +64,41 @@ * plat_arm_mmap array defined for each BL stage. */ #if IMAGE_BL1 -# define PLAT_ARM_MMAP_ENTRIES 6 +# if PLAT_fvp +# define PLAT_ARM_MMAP_ENTRIES 7 +# else +# define PLAT_ARM_MMAP_ENTRIES 6 +# endif #endif #if IMAGE_BL2 -# define PLAT_ARM_MMAP_ENTRIES 8 +# if PLAT_fvp +# define PLAT_ARM_MMAP_ENTRIES 9 +# else +# define PLAT_ARM_MMAP_ENTRIES 8 +# endif #endif #if IMAGE_BL31 -# define PLAT_ARM_MMAP_ENTRIES 5 +#define PLAT_ARM_MMAP_ENTRIES 5 #endif #if IMAGE_BL32 -# define PLAT_ARM_MMAP_ENTRIES 4 +#define PLAT_ARM_MMAP_ENTRIES 4 #endif /* * Platform specific page table and MMU setup constants */ #if IMAGE_BL1 -# if PLAT_fvp || PLAT_juno +# if PLAT_juno # define MAX_XLAT_TABLES 2 # else # define MAX_XLAT_TABLES 3 # endif /* PLAT_ */ #elif IMAGE_BL2 -# define MAX_XLAT_TABLES 3 +# if PLAT_juno +# define MAX_XLAT_TABLES 3 +# else +# define MAX_XLAT_TABLES 4 +# endif /* PLAT_ */ #elif IMAGE_BL31 # define MAX_XLAT_TABLES 2 #elif IMAGE_BL32 diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index c93b684..4447af2 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -32,6 +32,7 @@ #include #include +#include #include @@ -200,7 +201,7 @@ #if TRUSTED_BOARD_BOOT #define BL1_RW_BASE (ARM_BL_RAM_BASE + \ ARM_BL_RAM_SIZE - \ - 0x8000) + 0x9000) #else #define BL1_RW_BASE (ARM_BL_RAM_BASE + \ ARM_BL_RAM_SIZE - \ @@ -216,7 +217,7 @@ * size plus a little space for growth. */ #if TRUSTED_BOARD_BOOT -#define BL2_BASE (BL31_BASE - 0x1C000) +#define BL2_BASE (BL31_BASE - 0x1D000) #else #define BL2_BASE (BL31_BASE - 0xC000) #endif diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index e1221a9..d7eaac1 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -196,8 +196,9 @@ */ void plat_arm_io_setup(void); int plat_arm_get_alt_image_source( - const uintptr_t image_spec, - uintptr_t *dev_handle); + unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); void plat_arm_topology_setup(void); diff --git a/include/plat/arm/soc/common/soc_css_def.h b/include/plat/arm/soc/common/soc_css_def.h index 8b43e4c..428df4d 100644 --- a/include/plat/arm/soc/common/soc_css_def.h +++ b/include/plat/arm/soc/common/soc_css_def.h @@ -65,6 +65,14 @@ */ #define SOC_CSS_NIC400_APB4_BRIDGE 4 +/* Keys */ +#define SOC_KEYS_BASE 0x7fe80000 +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000) +#define TZ_PUB_KEY_HASH_SIZE 32 +#define HU_KEY_BASE (SOC_KEYS_BASE + 0x0020) +#define HU_KEY_SIZE 16 +#define END_KEY_BASE (SOC_KEYS_BASE + 0x0044) +#define END_KEY_SIZE 32 #define SOC_CSS_MAP_DEVICE MAP_REGION_FLAT( \ SOC_CSS_DEVICE_BASE, \ diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h index 1e2a417..1b3203e 100644 --- a/include/plat/common/common_def.h +++ b/include/plat/common/common_def.h @@ -47,40 +47,6 @@ */ #define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" -/* Trusted Boot Firmware BL2 */ -#define BL2_IMAGE_NAME "bl2.bin" - -/* SCP Firmware BL3-0 */ -#define BL30_IMAGE_NAME "bl30.bin" - -/* EL3 Runtime Firmware BL31 */ -#define BL31_IMAGE_NAME "bl31.bin" - -/* Secure Payload BL32 (Trusted OS) */ -#define BL32_IMAGE_NAME "bl32.bin" - -/* Non-Trusted Firmware BL33 */ -#define BL33_IMAGE_NAME "bl33.bin" - -/* Firmware Image Package */ -#define FIP_IMAGE_NAME "fip.bin" - -#if TRUSTED_BOARD_BOOT -/* Certificates */ -# define BL2_CERT_NAME "bl2.crt" -# define TRUSTED_KEY_CERT_NAME "trusted_key.crt" - -# define BL30_KEY_CERT_NAME "bl30_key.crt" -# define BL31_KEY_CERT_NAME "bl31_key.crt" -# define BL32_KEY_CERT_NAME "bl32_key.crt" -# define BL33_KEY_CERT_NAME "bl33_key.crt" - -# define BL30_CERT_NAME "bl30.crt" -# define BL31_CERT_NAME "bl31.crt" -# define BL32_CERT_NAME "bl32.crt" -# define BL33_CERT_NAME "bl33.crt" -#endif /* TRUSTED_BOARD_BOOT */ - /* * Some of the platform porting definitions use the 'ull' suffix in order to * avoid subtle integer overflow errors due to implicit integer type promotion diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 8188f45..469d46b 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -44,13 +44,18 @@ struct bl31_params; /******************************************************************************* + * plat_get_rotpk_info() flags + ******************************************************************************/ +#define ROTPK_IS_HASH (1 << 0) + +/******************************************************************************* * Function declarations ******************************************************************************/ /******************************************************************************* * Mandatory common functions ******************************************************************************/ uint64_t plat_get_syscnt_freq(void); -int plat_get_image_source(const char *image_name, +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, uintptr_t *image_spec); unsigned long plat_get_ns_image_entrypoint(void); @@ -191,8 +196,9 @@ void bl32_plat_enable_mmu(uint32_t flags); /******************************************************************************* - * Trusted Boot functions + * Trusted Board Boot functions ******************************************************************************/ -int plat_match_rotpk(const unsigned char *, unsigned int); +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags); #endif /* __PLATFORM_H__ */ diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c index c6ad68a..103aafb 100644 --- a/plat/arm/board/common/board_arm_trusted_boot.c +++ b/plat/arm/board/common/board_arm_trusted_boot.c @@ -28,15 +28,123 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include +#include +#include +#include + /* Weak definition may be overridden in specific platform */ #pragma weak plat_match_rotpk + +/* SHA256 algorithm */ +#define SHA256_BYTES 32 + +/* ROTPK locations */ +#define ARM_ROTPK_REGS_ID 1 +#define ARM_ROTPK_DEVEL_RSA_ID 2 + +#if !ARM_ROTPK_LOCATION_ID + #error "ARM_ROTPK_LOCATION_ID not defined" +#endif + +static const unsigned char rotpk_hash_hdr[] = \ + "\x30\x31\x30\x0D\x06\x09\x60\x86\x48" \ + "\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"; +static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1; +static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES]; + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) +static const unsigned char arm_devel_rotpk_hash[] = \ + "\xB0\xF3\x82\x09\x12\x97\xD8\x3A" \ + "\x37\x7A\x72\x47\x1B\xEC\x32\x73" \ + "\xE9\x92\x32\xE2\x49\x59\xF6\x5E" \ + "\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA"; +#endif + /* - * Check the validity of the key + * Return the ROTPK hash in the following ASN.1 structure in DER format: * - * 0 = success, Otherwise = error + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } */ -int plat_match_rotpk(const unsigned char *key_buf, unsigned int key_len) +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) { - /* TODO: check against the ROT key stored in the platform */ + uint8_t *dst; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + /* Copy the DER header */ + memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len); + dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len]; + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) + memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES); +#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + uint32_t *src, tmp; + unsigned int words, i; + + /* + * Append the hash from Trusted Root-Key Storage registers. The hash has + * not been written linearly into the registers, so we have to do a bit + * of byte swapping: + * + * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C + * +---------------------------------------------------------------+ + * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 | + * +---------------------------------------------------------------+ + * | ... ... | | ... ... | + * | +--------------------+ | +-------+ + * | | | | + * +----------------------------+ +----------------------------+ + * | | | | + * +-------+ | +--------------------+ | + * | | | | + * v v v v + * +---------------------------------------------------------------+ + * | | | + * +---------------------------------------------------------------+ + * 0 15 16 31 + * + * Additionally, we have to access the registers in 32-bit words + */ + words = SHA256_BYTES >> 3; + + /* Swap bytes 0-15 (first four registers) */ + src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + /* Words are read in little endian */ + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } + + /* Swap bytes 16-31 (last four registers) */ + src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2); + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } +#endif /* (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) */ + + *key_ptr = (void *)rotpk_hash_der; + *key_len = (unsigned int)sizeof(rotpk_hash_der); + *flags = ROTPK_IS_HASH; return 0; } + diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk new file mode 100644 index 0000000..bec49ed --- /dev/null +++ b/plat/arm/board/common/board_common.mk @@ -0,0 +1,55 @@ +# +# 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. +# + +PLAT_INCLUDES += -Iinclude/plat/arm/board/common/ + +PLAT_BL_COMMON_SOURCES += drivers/arm/pl011/pl011_console.S \ + plat/arm/board/common/aarch64/board_arm_helpers.S + +#BL1_SOURCES += + +#BL2_SOURCES += + +#BL31_SOURCES += + +ifneq (${TRUSTED_BOARD_BOOT},0) + # ROTPK hash location + ifeq (${ARM_ROTPK_LOCATION}, regs) + ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID + else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa) + ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID + else + $(error "Unsupported ARM_ROTPK_LOCATION value") + endif + $(eval $(call add_define,ARM_ROTPK_LOCATION_ID)) + + BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c + BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c +endif diff --git a/plat/arm/board/common/board_css.mk b/plat/arm/board/common/board_css.mk index 691999b..67e794e 100644 --- a/plat/arm/board/common/board_css.mk +++ b/plat/arm/board/common/board_css.mk @@ -28,20 +28,6 @@ # POSSIBILITY OF SUCH DAMAGE. # -PLAT_INCLUDES += -Iinclude/plat/arm/board/common/ +PLAT_BL_COMMON_SOURCES += plat/arm/board/common/board_css_common.c -PLAT_BL_COMMON_SOURCES += drivers/arm/pl011/pl011_console.S \ - plat/arm/board/common/aarch64/board_arm_helpers.S \ - plat/arm/board/common/board_css_common.c - - -#BL1_SOURCES += - -#BL2_SOURCES += - -#BL31_SOURCES += - -ifneq (${TRUSTED_BOARD_BOOT},0) - BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c - BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c -endif +include plat/arm/board/common/board_common.mk diff --git a/plat/arm/board/common/rotpk/arm_rotpk_rsa.der b/plat/arm/board/common/rotpk/arm_rotpk_rsa.der new file mode 100644 index 0000000..661f899 --- /dev/null +++ b/plat/arm/board/common/rotpk/arm_rotpk_rsa.der Binary files differ diff --git a/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin b/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin new file mode 100644 index 0000000..7653f7e --- /dev/null +++ b/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin @@ -0,0 +1 @@ +�� ��:7zrG�2s�2�IY�^�JJF�"�� \ No newline at end of file diff --git a/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem b/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem new file mode 100644 index 0000000..71410ec --- /dev/null +++ b/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLLGDVjWPUB3l+ +xxaWvU0kTqyG5rdx48VUC+cUHL0pGsE/erYCqqs2xNk2aWziZcObsb89qFYmy/0E +AbqsPlQyynleu7IF6gZY8nS64fSHwBkKH2YHd4SDoRzv/yhZ58NofSYgQ+tWY/M5 +MdgrUam8T9D23pXcX1vB7ZBv7CiRfhfteJD0YKfEx09Q7V0TOiErcMVhewghZTrN +glaMekesieilSEgx2R1G5YWGmKDlwKZqvQfkkldhB499Wk3Krja5VgQQ8my+9jts +gD6+DqNNx9R+p0nU8tK8zzCo53SPZN+8XEdozEBM+IPMy0A1BGDKs6QXnwPKHVr6 +0a8hVxDTAgMBAAECggEAfwsc8ewbhDW4TwIGqfNtDUr0rtYN13VpqohW0ki2L8G/ +HQaKUViO/wxQFqoNn/OqQO0AfHmKhXAAokTCiXngBHJ/OjF7vB7+IRhazZEE6u2/ +uoivr/OYNQbFpXyTqsQ1eFzpPju6KKcPK7BzT4Mc89ek/vloFAi8w6LdMl8lbvOg +LBWqX+5A+UQoenPUTvYM4U22YNcEAWubkpsYAmViiWiac+a+uPRk39aKyfOedDNu ++ty9MtCwekivoUTfP/1+O+jFlDnPMJUOEkBmcBqxseYYAHu7blBpdHxYpAItC2pv +YwJJSvsE+HLBLPk177Jahg7sOUqcP0F/X+T65yuvIQKBgQDxdjXdJT5K8j7rG2fv +2bvF2H1GPaHaTYRk0EGI2Ql6Nn+ddfeCE6gaT7aPPgg87wAhNu93coFuYHw0p/sc +ZkXMJ+BmlstPV555cWXmwcxZLsni0fOXrt4YxwWkZwmh74m0NVM/cSFw56PU0oj1 +yDNeq3fgmsJocmuNTe1eG9qA7QKBgQDXaAGrNA5Xel5mqqMYTHHQWI6l2uzdNtt7 +eDn3K9+Eh3ywTqrwP845MAjKDU2Lq61I6t2H89dEifHq823VIcLCHd9BF04MrAH7 +qDPzrmPP2iB9g+YFmGBKe+K0HFE1t1KrTlo9VV6ZAC6RJNLAgwD4kvfIVYNkCGwe ++hoZBdhgvwKBgBrOsPQ4ak4PzwRzKnrqhXpVqrLdrNZ7vLMkm+IBlpfG7SwiKLR8 +UjF5oB8PGAML1cvaOYPdZplGhQOjkrF4eU9NLhC1tSS96Y46FMIlyfYsx6UzAgRZ +GbdOgUXbWqpr2bH0KaXlfXz3eqzqIuKGs41TJB//jo3iBibN/AhytzORAoGAeGov +5KDpE4XYl9Pz8HVremjG9Xh4yQENmOwQm1fvT4rd7UFM1ZkVk2qCv1DIdLe32vdQ +d9ucDzh+ADWsxGRnF1TTpPN+Mh9FzISu5h4qtdreJsxBHgecbIbsqHrb+wdMM29N +itPaWfV8Eq9fETcqp8qgsWD8XkNHDdoKFMrrtskCgYAoSt/Je1D3ZE/3HEjez7bq +fenS3J6KG2SEn2PNFn+R0R5vBo4DaV/cQysKh44GD2+sh0QDyh6nuWJufyhPzROP +DU6DCLbwNePj/yaGuzi36oLt6bBgfPWCiJY7jIdK8DmTLW25m7fRtCC5pxZlSzgl +KBf7R6cbaTvaFe05Y2FJXA== +-----END PRIVATE KEY----- diff --git a/plat/arm/board/fvp/aarch64/fvp_common.c b/plat/arm/board/fvp/aarch64/fvp_common.c index a876313..c46bdb6 100644 --- a/plat/arm/board/fvp/aarch64/fvp_common.c +++ b/plat/arm/board/fvp/aarch64/fvp_common.c @@ -55,6 +55,11 @@ DEVICE1_SIZE, \ MT_DEVICE | MT_RW | MT_SECURE) +#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ + DEVICE2_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE) + + /* * Table of regions for various BL stages to map using the MMU. * This doesn't include TZRAM as the 'mem_layout' argument passed to @@ -67,6 +72,7 @@ V2M_MAP_IOFPGA, MAP_DEVICE0, MAP_DEVICE1, + MAP_DEVICE2, {0} }; #endif @@ -77,6 +83,7 @@ V2M_MAP_IOFPGA, MAP_DEVICE0, MAP_DEVICE1, + MAP_DEVICE2, ARM_MAP_NS_DRAM1, ARM_MAP_TSP_SEC_MEM, {0} diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h index 68ef297..842a287 100644 --- a/plat/arm/board/fvp/fvp_def.h +++ b/plat/arm/board/fvp/fvp_def.h @@ -58,13 +58,25 @@ #define DEVICE1_BASE 0x2f000000 #define DEVICE1_SIZE 0x200000 +/* Devices in the second GB */ +#define DEVICE2_BASE 0x7fe00000 +#define DEVICE2_SIZE 0x00200000 + #define NSRAM_BASE 0x2e000000 #define NSRAM_SIZE 0x10000 #define PCIE_EXP_BASE 0x40000000 #define TZRNG_BASE 0x7fe60000 #define TZNVCTR_BASE 0x7fe70000 -#define TZROOTKEY_BASE 0x7fe80000 + +/* Keys */ +#define SOC_KEYS_BASE 0x7fe80000 +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000) +#define TZ_PUB_KEY_HASH_SIZE 32 +#define HU_KEY_BASE (SOC_KEYS_BASE + 0x0020) +#define HU_KEY_SIZE 16 +#define END_KEY_BASE (SOC_KEYS_BASE + 0x0044) +#define END_KEY_SIZE 32 /* Constants to distinguish FVP type */ #define HBI_BASE_FVP 0x020 diff --git a/plat/arm/board/fvp/fvp_io_storage.c b/plat/arm/board/fvp/fvp_io_storage.c index 0284c3d..e9d847f 100644 --- a/plat/arm/board/fvp/fvp_io_storage.c +++ b/plat/arm/board/fvp/fvp_io_storage.c @@ -29,16 +29,88 @@ */ #include +#include #include #include #include #include #include +#include /* For FOPEN_MODE_... */ + +/* Semihosting filenames */ +#define BL2_IMAGE_NAME "bl2.bin" +#define BL31_IMAGE_NAME "bl31.bin" +#define BL32_IMAGE_NAME "bl32.bin" +#define BL33_IMAGE_NAME "bl33.bin" + +#if TRUSTED_BOARD_BOOT +#define BL2_CERT_NAME "bl2.crt" +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define BL31_KEY_CERT_NAME "bl31_key.crt" +#define BL32_KEY_CERT_NAME "bl32_key.crt" +#define BL33_KEY_CERT_NAME "bl33_key.crt" +#define BL31_CERT_NAME "bl31.crt" +#define BL32_CERT_NAME "bl32.crt" +#define BL33_CERT_NAME "bl33.crt" +#endif /* TRUSTED_BOARD_BOOT */ /* IO devices */ static const io_dev_connector_t *sh_dev_con; static uintptr_t sh_dev_handle; +static const io_file_spec_t sh_file_spec[] = { + [BL2_IMAGE_ID] = { + .path = BL2_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL31_IMAGE_ID] = { + .path = BL31_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL32_IMAGE_ID] = { + .path = BL32_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL33_IMAGE_ID] = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, +#if TRUSTED_BOARD_BOOT + [BL2_CERT_ID] = { + .path = BL2_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_KEY_CERT_ID] = { + .path = TRUSTED_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [BL31_KEY_CERT_ID] = { + .path = BL31_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [BL32_KEY_CERT_ID] = { + .path = BL32_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [BL33_KEY_CERT_ID] = { + .path = BL33_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [BL31_CERT_ID] = { + .path = BL31_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [BL32_CERT_ID] = { + .path = BL32_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [BL33_CERT_ID] = { + .path = BL33_CERT_NAME, + .mode = FOPEN_MODE_RB + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + static int open_semihosting(const uintptr_t spec) { @@ -75,13 +147,17 @@ (void)io_result; } -int plat_arm_get_alt_image_source( - const uintptr_t image_spec, - uintptr_t *dev_handle) +/* + * FVP provides semihosting as an alternative to load images + */ +int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) { - int result = open_semihosting(image_spec); - if (result == IO_SUCCESS) + int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]); + if (result == IO_SUCCESS) { *dev_handle = sh_dev_handle; + *image_spec = (uintptr_t)&sh_file_spec[image_id]; + } return result; } diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 949e6ad..a1a0971 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -29,12 +29,10 @@ # -PLAT_INCLUDES := -Iinclude/plat/arm/board/common \ - -Iplat/arm/board/fvp/include +PLAT_INCLUDES := -Iplat/arm/board/fvp/include -PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011_console.S \ - plat/arm/board/fvp/aarch64/fvp_common.c +PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp/aarch64/fvp_common.c BL1_SOURCES += drivers/io/io_semihosting.c \ lib/cpus/aarch64/aem_generic.S \ @@ -65,10 +63,5 @@ plat/arm/board/fvp/aarch64/fvp_helpers.S \ plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c -ifneq (${TRUSTED_BOARD_BOOT},0) - BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c - BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c -endif - - +include plat/arm/board/common/board_common.mk include plat/arm/common/arm_common.mk diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index d8d4f14..98834e7 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -40,7 +40,6 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a57.S - # Enable workarounds for selected Cortex-A57 erratas. ERRATA_A57_806969 := 0 ERRATA_A57_813420 := 1 @@ -53,3 +52,7 @@ include plat/arm/common/arm_common.mk include plat/arm/soc/common/soc_css.mk include plat/arm/css/common/css_common.mk + +ifeq (${KEY_ALG},ecdsa) + $(error "ECDSA key algorithm is not fully supported on Juno.") +endif diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index 3b7c057..bcc3833 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -46,7 +46,8 @@ # Process flags $(eval $(call add_define,ARM_TSP_RAM_LOCATION_ID)) -PLAT_INCLUDES += -Iinclude/plat/arm/common \ +PLAT_INCLUDES += -Iinclude/common/tbbr \ + -Iinclude/plat/arm/common \ -Iinclude/plat/arm/common/aarch64 @@ -83,3 +84,31 @@ plat/arm/common/arm_topology.c \ plat/common/plat_gic.c \ plat/common/aarch64/platform_mp_stack.S + +ifneq (${TRUSTED_BOARD_BOOT},0) + + # By default, ARM platforms use RSA keys + KEY_ALG := rsa + + # Include common TBB sources + AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot.c \ + + BL1_SOURCES += ${AUTH_SOURCES} + BL2_SOURCES += ${AUTH_SOURCES} + + MBEDTLS_KEY_ALG := ${KEY_ALG} + + # We expect to locate the *.mk files under the directories specified below + CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk + IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk + + $(info Including ${CRYPTO_LIB_MK}) + include ${CRYPTO_LIB_MK} + + $(info Including ${IMG_PARSER_LIB_MK}) + include ${IMG_PARSER_LIB_MK} + +endif diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c index ea29313..8488f12 100644 --- a/plat/arm/common/arm_io_storage.c +++ b/plat/arm/common/arm_io_storage.c @@ -28,13 +28,14 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include +#include /* For ARRAY_SIZE */ #include +#include #include #include #include #include #include -#include /* For FOPEN_MODE_... */ #include /* IO devices */ @@ -48,179 +49,162 @@ .length = PLAT_ARM_FIP_MAX_SIZE }; -static const io_file_spec_t bl2_file_spec = { - .path = BL2_IMAGE_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, }; -static const io_file_spec_t bl30_file_spec = { - .path = BL30_IMAGE_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl30_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_BL30, }; -static const io_file_spec_t bl31_file_spec = { - .path = BL31_IMAGE_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, }; -static const io_file_spec_t bl32_file_spec = { - .path = BL32_IMAGE_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, }; -static const io_file_spec_t bl33_file_spec = { - .path = BL33_IMAGE_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, }; #if TRUSTED_BOARD_BOOT -static const io_file_spec_t bl2_cert_file_spec = { - .path = BL2_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl2_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT, }; -static const io_file_spec_t trusted_key_cert_file_spec = { - .path = TRUSTED_KEY_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, }; -static const io_file_spec_t bl30_key_cert_file_spec = { - .path = BL30_KEY_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl30_key_cert_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_BL30_KEY_CERT, }; -static const io_file_spec_t bl31_key_cert_file_spec = { - .path = BL31_KEY_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl31_key_cert_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT, }; -static const io_file_spec_t bl32_key_cert_file_spec = { - .path = BL32_KEY_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl32_key_cert_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_KEY_CERT, }; -static const io_file_spec_t bl33_key_cert_file_spec = { - .path = BL33_KEY_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl33_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT, }; -static const io_file_spec_t bl30_cert_file_spec = { - .path = BL30_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl30_cert_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_BL30_CERT, }; -static const io_file_spec_t bl31_cert_file_spec = { - .path = BL31_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl31_cert_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT, }; -static const io_file_spec_t bl32_cert_file_spec = { - .path = BL32_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl32_cert_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_CERT, }; -static const io_file_spec_t bl33_cert_file_spec = { - .path = BL33_CERT_NAME, - .mode = FOPEN_MODE_RB +static const io_uuid_spec_t bl33_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_CERT, }; #endif /* TRUSTED_BOARD_BOOT */ + static int open_fip(const uintptr_t spec); static int open_memmap(const uintptr_t spec); struct plat_io_policy { - const char *image_name; uintptr_t *dev_handle; uintptr_t image_spec; int (*check)(const uintptr_t spec); }; +/* By default, ARM platforms load images from the FIP */ static const struct plat_io_policy policies[] = { - { - FIP_IMAGE_NAME, + [FIP_IMAGE_ID] = { &memmap_dev_handle, (uintptr_t)&fip_block_spec, open_memmap - }, { - BL2_IMAGE_NAME, + }, + [BL2_IMAGE_ID] = { &fip_dev_handle, - (uintptr_t)&bl2_file_spec, + (uintptr_t)&bl2_uuid_spec, open_fip - }, { - BL30_IMAGE_NAME, + }, + [BL30_IMAGE_ID] = { &fip_dev_handle, - (uintptr_t)&bl30_file_spec, + (uintptr_t)&bl30_uuid_spec, open_fip - }, { - BL31_IMAGE_NAME, + }, + [BL31_IMAGE_ID] = { &fip_dev_handle, - (uintptr_t)&bl31_file_spec, + (uintptr_t)&bl31_uuid_spec, open_fip - }, { - BL32_IMAGE_NAME, + }, + [BL32_IMAGE_ID] = { &fip_dev_handle, - (uintptr_t)&bl32_file_spec, + (uintptr_t)&bl32_uuid_spec, open_fip - }, { - BL33_IMAGE_NAME, + }, + [BL33_IMAGE_ID] = { &fip_dev_handle, - (uintptr_t)&bl33_file_spec, + (uintptr_t)&bl33_uuid_spec, open_fip - }, { + }, #if TRUSTED_BOARD_BOOT - BL2_CERT_NAME, + [BL2_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl2_cert_file_spec, + (uintptr_t)&bl2_cert_uuid_spec, open_fip - }, { - TRUSTED_KEY_CERT_NAME, + }, + [TRUSTED_KEY_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&trusted_key_cert_file_spec, + (uintptr_t)&trusted_key_cert_uuid_spec, open_fip - }, { - BL30_KEY_CERT_NAME, + }, + [BL30_KEY_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl30_key_cert_file_spec, + (uintptr_t)&bl30_key_cert_uuid_spec, open_fip - }, { - BL31_KEY_CERT_NAME, + }, + [BL31_KEY_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl31_key_cert_file_spec, + (uintptr_t)&bl31_key_cert_uuid_spec, open_fip - }, { - BL32_KEY_CERT_NAME, + }, + [BL32_KEY_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl32_key_cert_file_spec, + (uintptr_t)&bl32_key_cert_uuid_spec, open_fip - }, { - BL33_KEY_CERT_NAME, + }, + [BL33_KEY_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl33_key_cert_file_spec, + (uintptr_t)&bl33_key_cert_uuid_spec, open_fip - }, { - BL30_CERT_NAME, + }, + [BL30_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl30_cert_file_spec, + (uintptr_t)&bl30_cert_uuid_spec, open_fip - }, { - BL31_CERT_NAME, + }, + [BL31_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl31_cert_file_spec, + (uintptr_t)&bl31_cert_uuid_spec, open_fip - }, { - BL32_CERT_NAME, + }, + [BL32_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl32_cert_file_spec, + (uintptr_t)&bl32_cert_uuid_spec, open_fip - }, { - BL33_CERT_NAME, + }, + [BL33_CERT_ID] = { &fip_dev_handle, - (uintptr_t)&bl33_cert_file_spec, + (uintptr_t)&bl33_cert_uuid_spec, open_fip - }, { + }, #endif /* TRUSTED_BOARD_BOOT */ - 0, 0, 0 - } }; @@ -235,7 +219,7 @@ uintptr_t local_image_handle; /* See if a Firmware Image Package is available */ - result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_NAME); + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); if (result == IO_SUCCESS) { result = io_open(fip_dev_handle, spec, &local_image_handle); if (result == IO_SUCCESS) { @@ -293,8 +277,9 @@ } int plat_arm_get_alt_image_source( - const uintptr_t image_spec __attribute__((unused)), - uintptr_t *dev_handle __attribute__((unused))) + unsigned int image_id __attribute__((unused)), + uintptr_t *dev_handle __attribute__((unused)), + uintptr_t *image_spec __attribute__((unused))) { /* By default do not try an alternative */ return IO_FAIL; @@ -302,36 +287,24 @@ /* Return an IO device handle and specification which can be used to access * an image. Use this to enforce platform load policy */ -int plat_get_image_source(const char *image_name, uintptr_t *dev_handle, +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, uintptr_t *image_spec) { int result = IO_FAIL; const struct plat_io_policy *policy; - if ((image_name != NULL) && (dev_handle != NULL) && - (image_spec != NULL)) { - policy = policies; - while (policy->image_name != NULL) { - if (strcmp(policy->image_name, image_name) == 0) { - result = policy->check(policy->image_spec); - if (result == IO_SUCCESS) { - *image_spec = policy->image_spec; - *dev_handle = *(policy->dev_handle); - break; - } - VERBOSE("Trying alternative IO\n"); - result = plat_arm_get_alt_image_source( - policy->image_spec, - dev_handle); - if (result == IO_SUCCESS) { - *image_spec = policy->image_spec; - break; - } - } - policy++; - } + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + if (result == IO_SUCCESS) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); } else { - result = IO_FAIL; + VERBOSE("Trying alternative IO\n"); + result = plat_arm_get_alt_image_source(image_id, dev_handle, + image_spec); } + return result; } diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile index eac8cec..a4bd76f 100644 --- a/tools/cert_create/Makefile +++ b/tools/cert_create/Makefile @@ -33,6 +33,7 @@ V := 0 DEBUG := 0 BINARY := ${PROJECT} +OPENSSL_DIR := /usr OBJECTS := src/cert.o \ src/ext.o \ @@ -69,8 +70,8 @@ # 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 d73f573..57bb65f 100644 --- a/tools/cert_create/include/ext.h +++ b/tools/cert_create/include/ext.h @@ -63,7 +63,8 @@ }; 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 8819750..dfb3150 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 @@ 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 31f84a8..21b90db 100644 --- a/tools/cert_create/src/ext.c +++ b/tools/cert_create/src/ext.c @@ -31,13 +31,29 @@ #include #include #include +#include +#include #include #include #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 @@ } /* - * 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 b5737d9..2137bf7 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 @@ /* 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 6df367a..77faf42 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 @@ }; /* Global options */ +static int key_alg; static int new_keys; static int save_keys; static int print_cert; @@ -138,6 +140,11 @@ 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 @@ {"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 @@ printf(" --%s \\\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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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);