Merge pull request #315 from jcastillo-arm/jc/tbb_tmp9
Authentication Framework
This commit is contained in:
commit
84f95bed54
26
Makefile
26
Makefile
|
@ -73,9 +73,9 @@ DISABLE_PEDANTIC := 0
|
|||
# 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 @@ INCLUDES += -Iinclude/bl31 \
|
|||
-Iinclude/common \
|
||||
-Iinclude/drivers \
|
||||
-Iinclude/drivers/arm \
|
||||
-Iinclude/drivers/auth \
|
||||
-Iinclude/drivers/io \
|
||||
-Iinclude/drivers/ti/uart \
|
||||
-Iinclude/lib \
|
||||
|
@ -270,6 +271,7 @@ $(eval $(call add_define,USE_COHERENT_MEM))
|
|||
# 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 (${GENERATE_COT},0)
|
|||
|
||||
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,--bl$(1)-cert $(BUILD_PLAT)/bl$(1).crt))
|
|||
$(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))
|
||||
|
|
|
@ -51,6 +51,12 @@ SECTIONS
|
|||
*(.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.
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
|
@ -157,40 +157,20 @@ void bl1_main(void)
|
|||
/* 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 @@ void bl1_main(void)
|
|||
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.
|
||||
|
|
|
@ -50,6 +50,13 @@ SECTIONS
|
|||
*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__ = .;
|
||||
/*
|
||||
|
|
284
bl2/bl2_main.c
284
bl2/bl2_main.c
|
@ -31,149 +31,14 @@
|
|||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
#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 @@ static int load_bl30(void)
|
|||
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 @@ static int load_bl31(bl31_params_t *bl2_to_bl31_params,
|
|||
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 @@ static int load_bl32(bl31_params_t *bl2_to_bl31_params)
|
|||
* 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 @@ static int load_bl33(bl31_params_t *bl2_to_bl31_params)
|
|||
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 @@ void bl2_main(void)
|
|||
|
||||
#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 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 <stddef.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <auth.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <platform_oid.h>
|
||||
|
||||
#include <polarssl/memory_buffer_alloc.h>
|
||||
#include <polarssl/oid.h>
|
||||
#include <polarssl/platform.h>
|
||||
#include <polarssl/sha256.h>
|
||||
#include <polarssl/x509_crt.h>
|
||||
|
||||
/*
|
||||
* 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
|
||||
};
|
|
@ -31,6 +31,7 @@
|
|||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <auth_mod.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
@ -156,7 +157,7 @@ static void dump_load_info(unsigned long image_load_addr,
|
|||
}
|
||||
|
||||
/* 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 @@ unsigned long image_size(const char *image_name)
|
|||
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 @@ unsigned long image_size(const char *image_name)
|
|||
* 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 load_image(meminfo_t *mem_layout,
|
|||
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 @@ int load_image(meminfo_t *mem_layout,
|
|||
/* 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 @@ int load_image(meminfo_t *mem_layout,
|
|||
*/
|
||||
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 @@ exit:
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -134,51 +134,6 @@ platform port to define additional platform porting constants in
|
|||
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 @@ platform port to define additional platform porting constants in
|
|||
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 @@ The ARM FVP port uses this function to initialize the mailbox memory used for
|
|||
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 @@ provide at least one driver for a device capable of supporting generic
|
|||
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
|
||||
|
|
|
@ -6,7 +6,7 @@ Contents :
|
|||
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 @@ The mechanism used for generating the FIP and the Authentication module are
|
|||
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 @@ _Copyright (c) 2015, ARM Limited and Contributors. All rights reserved._
|
|||
|
||||
[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
|
||||
|
|
|
@ -265,16 +265,8 @@ performed.
|
|||
* `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/<module name>`
|
||||
directory. The directory must contain a makefile `<module name>.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 @@ performed.
|
|||
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 @@ performed.
|
|||
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 @@ The Trusted Board Boot feature is described in [Trusted Board Boot]. The
|
|||
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=<path of the directory containing PolarSSL sources>`
|
||||
* `AUTH_MOD=polarssl`
|
||||
* `MBEDTLS_DIR=<path of the directory containing mbedTLS sources>`
|
||||
* `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=<path-to-aarch64-gcc>/bin/aarch64-none-elf- \
|
||||
BL33=<path-to>/<bl33_image> \
|
||||
MBEDTLS_DIR=<path of the directory containing mbedTLS sources> \
|
||||
make PLAT=<platform> 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 @@ _Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved._
|
|||
[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
|
||||
|
|
|
@ -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 <assert.h>
|
||||
#include <auth_common.h>
|
||||
#include <auth_mod.h>
|
||||
#include <cot_def.h>
|
||||
#include <crypto_mod.h>
|
||||
#include <debug.h>
|
||||
#include <img_parser_mod.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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 <assert.h>
|
||||
#include <crypto_mod.h>
|
||||
#include <debug.h>
|
||||
|
||||
/* 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);
|
||||
}
|
|
@ -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 <assert.h>
|
||||
#include <auth_common.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <img_parser_mod.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -29,33 +29,37 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <auth.h>
|
||||
#include <debug.h>
|
||||
|
||||
/* mbedTLS headers */
|
||||
#include <polarssl/memory_buffer_alloc.h>
|
||||
|
||||
/*
|
||||
* Initialize the authentication module
|
||||
* mbedTLS heap
|
||||
*/
|
||||
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);
|
||||
}
|
||||
#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];
|
||||
|
||||
/*
|
||||
* Authenticate a certificate/image
|
||||
* mbedTLS initialization function
|
||||
*
|
||||
* Return: 0 = success, Otherwise = error
|
||||
*/
|
||||
int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len)
|
||||
void mbedtls_init(void)
|
||||
{
|
||||
assert(obj_id < AUTH_NUM_OBJ);
|
||||
assert(obj_buf != 0);
|
||||
assert(auth_mod.verify);
|
||||
static int ready;
|
||||
int rc;
|
||||
|
||||
return auth_mod.verify(obj_id, obj_buf, len);
|
||||
if (!ready) {
|
||||
/* Initialize the mbedTLS heap */
|
||||
rc = memory_buffer_alloc_init(heap, MBEDTLS_HEAP_SIZE);
|
||||
if (rc == 0) {
|
||||
ready = 1;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,41 +28,33 @@
|
|||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
# POLARSSL_DIR must be set to the PolarSSL main directory (it must contain
|
||||
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 (${POLARSSL_DIR},)
|
||||
$(error Error: POLARSSL_DIR not set)
|
||||
ifeq (${MBEDTLS_DIR},)
|
||||
$(error Error: MBEDTLS_DIR not set)
|
||||
endif
|
||||
|
||||
INCLUDES += -I${POLARSSL_DIR}/include \
|
||||
-Icommon/auth/polarssl
|
||||
INCLUDES += -I${MBEDTLS_DIR}/include \
|
||||
-Iinclude/drivers/auth/mbedtls
|
||||
|
||||
POLARSSL_CONFIG_FILE := "<polarssl_config.h>"
|
||||
# Specify mbedTLS configuration file
|
||||
POLARSSL_CONFIG_FILE := "<mbedtls_config.h>"
|
||||
$(eval $(call add_define,POLARSSL_CONFIG_FILE))
|
||||
|
||||
POLARSSL_SOURCES := $(addprefix ${POLARSSL_DIR}/library/, \
|
||||
MBEDTLS_COMMON_SOURCES := drivers/auth/mbedtls/mbedtls_common.c \
|
||||
$(addprefix ${MBEDTLS_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
|
||||
|
||||
BL1_SOURCES += ${MBEDTLS_COMMON_SOURCES}
|
||||
BL2_SOURCES += ${MBEDTLS_COMMON_SOURCES}
|
||||
DISABLE_PEDANTIC := 1
|
||||
|
||||
endif
|
|
@ -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 <crypto_mod.h>
|
||||
#include <debug.h>
|
||||
#include <mbedtls_common.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
/* mbedTLS headers */
|
||||
#include <polarssl/md_wrap.h>
|
||||
#include <polarssl/memory_buffer_alloc.h>
|
||||
#include <polarssl/oid.h>
|
||||
#include <polarssl/platform.h>
|
||||
|
||||
#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);
|
|
@ -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}
|
|
@ -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}
|
|
@ -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 <assert.h>
|
||||
#include <img_parser_mod.h>
|
||||
#include <mbedtls_common.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* mbedTLS headers */
|
||||
#include <polarssl/asn1.h>
|
||||
#include <polarssl/oid.h>
|
||||
#include <polarssl/platform.h>
|
||||
|
||||
/* 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);
|
|
@ -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 <auth_mod.h>
|
||||
#include <platform_def.h>
|
||||
#include <platform_oid.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* 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);
|
|
@ -50,11 +50,6 @@
|
|||
x.node[0], x.node[1], x.node[2], x.node[3], \
|
||||
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
|
||||
|
@ -64,37 +59,6 @@ typedef struct {
|
|||
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_init(io_dev_info_t *dev_info, const uintptr_t init_params);
|
|||
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 inline int is_valid_header(fip_toc_header_t *header)
|
|||
}
|
||||
|
||||
|
||||
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_open(const uintptr_t dev_spec __attribute__((unused)),
|
|||
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 @@ static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
|
|||
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 @@ static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
|
|||
{
|
||||
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 @@ static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
|
|||
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 @@ static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
|
|||
&bytes_read);
|
||||
if (result == IO_SUCCESS) {
|
||||
if (compare_uuids(¤t_file.entry.uuid,
|
||||
&file_uuid) == 0) {
|
||||
&uuid_spec->uuid) == 0) {
|
||||
found_file = 1;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -226,12 +226,17 @@ CASSERT(sizeof(unsigned long) ==
|
|||
******************************************************************************/
|
||||
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[];
|
||||
|
||||
|
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -28,61 +28,45 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef AUTH_H_
|
||||
#define AUTH_H_
|
||||
#ifndef __AUTH_MOD_H__
|
||||
#define __AUTH_MOD_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
|
||||
#include <auth_common.h>
|
||||
#include <cot_def.h>
|
||||
#include <img_parser_mod.h>
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Image flags
|
||||
*/
|
||||
#define IMG_FLAG_AUTHENTICATED (1 << 0)
|
||||
|
||||
/* 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;
|
||||
/*
|
||||
* 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_init(void);
|
||||
int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len);
|
||||
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);
|
||||
|
||||
#endif /* AUTH_H_ */
|
||||
/* 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__ */
|
|
@ -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__ */
|
|
@ -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 <auth_common.h>
|
||||
|
||||
/*
|
||||
* 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__ */
|
|
@ -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__ */
|
|
@ -27,9 +27,14 @@
|
|||
* 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__
|
||||
#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
|
||||
|
@ -64,7 +69,14 @@
|
|||
|
||||
#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
|
||||
|
@ -81,4 +93,7 @@
|
|||
|
||||
#include "polarssl/check_config.h"
|
||||
|
||||
#endif /* __POLARSSL_CONFIG_H__ */
|
||||
/* System headers required to build mbedTLS with the current configuration */
|
||||
#include <stdlib.h>
|
||||
|
||||
#endif /* __MBEDTLS_CONFIG_H__ */
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h> /* For ssize_t */
|
||||
#include <uuid.h>
|
||||
|
||||
|
||||
/* Device type which can be used to enable policy decisions about which device
|
||||
|
@ -67,6 +68,11 @@ typedef struct io_file_spec {
|
|||
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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <common_def.h>
|
||||
#include <platform_def.h>
|
||||
#include <tbbr_img_def.h>
|
||||
#include <xlat_tables.h>
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -196,8 +196,9 @@ void plat_arm_pwrc_setup(void);
|
|||
*/
|
||||
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);
|
||||
|
||||
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -43,6 +43,11 @@ struct image_info;
|
|||
struct entry_point_info;
|
||||
struct bl31_params;
|
||||
|
||||
/*******************************************************************************
|
||||
* plat_get_rotpk_info() flags
|
||||
******************************************************************************/
|
||||
#define ROTPK_IS_HASH (1 << 0)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function declarations
|
||||
******************************************************************************/
|
||||
|
@ -50,7 +55,7 @@ struct bl31_params;
|
|||
* 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 bl31_plat_enable_mmu(uint32_t flags);
|
|||
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__ */
|
||||
|
|
|
@ -28,15 +28,123 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <arm_def.h>
|
||||
#include <assert.h>
|
||||
#include <platform.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
Аѓ<EFBFBD> <12>и:7zrGь2sщ<73>2тIYі^<5E>JJFи"<22>к
|
|
@ -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-----
|
|
@ -55,6 +55,11 @@ arm_config_t arm_config;
|
|||
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 @@ const mmap_region_t plat_arm_mmap[] = {
|
|||
V2M_MAP_IOFPGA,
|
||||
MAP_DEVICE0,
|
||||
MAP_DEVICE1,
|
||||
MAP_DEVICE2,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
@ -77,6 +83,7 @@ const mmap_region_t plat_arm_mmap[] = {
|
|||
V2M_MAP_IOFPGA,
|
||||
MAP_DEVICE0,
|
||||
MAP_DEVICE1,
|
||||
MAP_DEVICE2,
|
||||
ARM_MAP_NS_DRAM1,
|
||||
ARM_MAP_TSP_SEC_MEM,
|
||||
{0}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -29,16 +29,88 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common_def.h>
|
||||
#include <debug.h>
|
||||
#include <io_driver.h>
|
||||
#include <io_storage.h>
|
||||
#include <io_semihosting.h>
|
||||
#include <plat_arm.h>
|
||||
#include <semihosting.h> /* 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 plat_arm_io_setup(void)
|
|||
(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;
|
||||
}
|
||||
|
|
|
@ -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 @@ BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
|
|||
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
|
||||
|
|
|
@ -40,7 +40,6 @@ BL2_SOURCES += plat/arm/board/juno/juno_security.c \
|
|||
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/board/common/board_css.mk
|
|||
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
|
||||
|
|
|
@ -46,7 +46,8 @@ endif
|
|||
# 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 @@ BL31_SOURCES += drivers/arm/cci/cci.c \
|
|||
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
|
||||
|
|
|
@ -28,13 +28,14 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <bl_common.h> /* For ARRAY_SIZE */
|
||||
#include <debug.h>
|
||||
#include <firmware_image_package.h>
|
||||
#include <io_driver.h>
|
||||
#include <io_fip.h>
|
||||
#include <io_memmap.h>
|
||||
#include <io_storage.h>
|
||||
#include <platform_def.h>
|
||||
#include <semihosting.h> /* For FOPEN_MODE_... */
|
||||
#include <string.h>
|
||||
|
||||
/* IO devices */
|
||||
|
@ -48,179 +49,162 @@ static const io_block_spec_t fip_block_spec = {
|
|||
.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 @@ static int open_fip(const uintptr_t spec)
|
|||
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 @@ void plat_arm_io_setup(void)
|
|||
}
|
||||
|
||||
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 @@ int plat_arm_get_alt_image_source(
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ PLAT := none
|
|||
V := 0
|
||||
DEBUG := 0
|
||||
BINARY := ${PROJECT}
|
||||
OPENSSL_DIR := /usr
|
||||
|
||||
OBJECTS := src/cert.o \
|
||||
src/ext.o \
|
||||
|
@ -69,8 +70,8 @@ endif
|
|||
|
||||
# Make soft links and include from local directory otherwise wrong headers
|
||||
# could get pulled in from firmware tree.
|
||||
INC_DIR := -I ./include -I ${PLAT_INCLUDE}
|
||||
LIB_DIR :=
|
||||
INC_DIR := -I ./include -I ${PLAT_INCLUDE} -I ${OPENSSL_DIR}/include
|
||||
LIB_DIR := -L ${OPENSSL_DIR}/lib
|
||||
LIB := -lssl -lcrypto
|
||||
|
||||
CC := gcc
|
||||
|
|
|
@ -63,7 +63,8 @@ enum {
|
|||
};
|
||||
|
||||
int ext_init(ext_t *tbb_ext);
|
||||
X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len);
|
||||
X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
|
||||
unsigned char *buf, size_t len);
|
||||
X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value);
|
||||
X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k);
|
||||
|
||||
|
|
|
@ -35,6 +35,21 @@
|
|||
|
||||
#define RSA_KEY_BITS 2048
|
||||
|
||||
/* Error codes */
|
||||
enum {
|
||||
KEY_ERR_NONE,
|
||||
KEY_ERR_MALLOC,
|
||||
KEY_ERR_FILENAME,
|
||||
KEY_ERR_OPEN,
|
||||
KEY_ERR_LOAD
|
||||
};
|
||||
|
||||
/* Supported key algorithms */
|
||||
enum {
|
||||
KEY_ALG_RSA,
|
||||
KEY_ALG_ECDSA
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure contains the relevant information to create the keys
|
||||
* required to sign the certificates.
|
||||
|
@ -50,8 +65,8 @@ typedef struct key_s {
|
|||
EVP_PKEY *key; /* Key container */
|
||||
} key_t;
|
||||
|
||||
int key_new(key_t *key);
|
||||
int key_load(key_t *key);
|
||||
int key_create(key_t *key, int type);
|
||||
int key_load(key_t *key, unsigned int *err_code);
|
||||
int key_store(key_t *key);
|
||||
|
||||
#endif /* KEY_H_ */
|
||||
|
|
|
@ -31,13 +31,29 @@
|
|||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include "ext.h"
|
||||
|
||||
DECLARE_ASN1_ITEM(ASN1_INTEGER)
|
||||
DECLARE_ASN1_ITEM(X509_ALGOR)
|
||||
DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
|
||||
|
||||
typedef struct {
|
||||
X509_ALGOR *hashAlgorithm;
|
||||
ASN1_OCTET_STRING *dataHash;
|
||||
} HASH;
|
||||
|
||||
ASN1_SEQUENCE(HASH) = {
|
||||
ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
|
||||
ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
|
||||
} ASN1_SEQUENCE_END(HASH)
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS(HASH)
|
||||
IMPLEMENT_ASN1_FUNCTIONS(HASH)
|
||||
|
||||
/*
|
||||
* This function adds the TBB extensions to the internal extension list
|
||||
* maintained by OpenSSL so they can be used later.
|
||||
|
@ -123,37 +139,85 @@ X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len)
|
|||
}
|
||||
|
||||
/*
|
||||
* Creates a x509v3 extension containing a hash encapsulated in an ASN1 Octet
|
||||
* String
|
||||
* Creates a x509v3 extension containing a hash
|
||||
*
|
||||
* DigestInfo ::= SEQUENCE {
|
||||
* digestAlgorithm AlgorithmIdentifier,
|
||||
* digest OCTET STRING
|
||||
* }
|
||||
*
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL
|
||||
* }
|
||||
*
|
||||
* Parameters:
|
||||
* pex: OpenSSL extension pointer (output parameter)
|
||||
* nid: extension identifier
|
||||
* crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
|
||||
* md: hash algorithm
|
||||
* buf: pointer to the buffer that contains the hash
|
||||
* len: size of the hash in bytes
|
||||
*
|
||||
* Return: Extension address, NULL if error
|
||||
*/
|
||||
X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len)
|
||||
X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
|
||||
unsigned char *buf, size_t len)
|
||||
{
|
||||
X509_EXTENSION *ex = NULL;
|
||||
ASN1_OCTET_STRING *hash = NULL;
|
||||
ASN1_OCTET_STRING *octet = NULL;
|
||||
HASH *hash = NULL;
|
||||
ASN1_OBJECT *algorithm = NULL;
|
||||
X509_ALGOR *x509_algor = NULL;
|
||||
unsigned char *p = NULL;
|
||||
int sz = -1;
|
||||
|
||||
/* Encode Hash */
|
||||
hash = ASN1_OCTET_STRING_new();
|
||||
ASN1_OCTET_STRING_set(hash, buf, len);
|
||||
sz = i2d_ASN1_OCTET_STRING(hash, NULL);
|
||||
i2d_ASN1_OCTET_STRING(hash, &p);
|
||||
/* OBJECT_IDENTIFIER with hash algorithm */
|
||||
algorithm = OBJ_nid2obj(md->type);
|
||||
if (algorithm == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create X509_ALGOR */
|
||||
x509_algor = X509_ALGOR_new();
|
||||
if (x509_algor == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
x509_algor->algorithm = algorithm;
|
||||
x509_algor->parameter = ASN1_TYPE_new();
|
||||
ASN1_TYPE_set(x509_algor->parameter, V_ASN1_NULL, NULL);
|
||||
|
||||
/* OCTET_STRING with the actual hash */
|
||||
octet = ASN1_OCTET_STRING_new();
|
||||
if (octet == NULL) {
|
||||
X509_ALGOR_free(x509_algor);
|
||||
return NULL;
|
||||
}
|
||||
ASN1_OCTET_STRING_set(octet, buf, len);
|
||||
|
||||
/* HASH structure containing algorithm + hash */
|
||||
hash = HASH_new();
|
||||
if (hash == NULL) {
|
||||
ASN1_OCTET_STRING_free(octet);
|
||||
X509_ALGOR_free(x509_algor);
|
||||
return NULL;
|
||||
}
|
||||
hash->hashAlgorithm = x509_algor;
|
||||
hash->dataHash = octet;
|
||||
|
||||
/* DER encoded HASH */
|
||||
sz = i2d_HASH(hash, &p);
|
||||
if ((sz <= 0) || (p == NULL)) {
|
||||
HASH_free(hash);
|
||||
X509_ALGOR_free(x509_algor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the extension */
|
||||
ex = ext_new(nid, crit, p, sz);
|
||||
|
||||
/* Clean up */
|
||||
OPENSSL_free(p);
|
||||
ASN1_OCTET_STRING_free(hash);
|
||||
HASH_free(hash);
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
|
|
@ -46,41 +46,81 @@
|
|||
#define MAX_FILENAME_LEN 1024
|
||||
|
||||
/*
|
||||
* Create a new key
|
||||
* Create a new key container
|
||||
*/
|
||||
int key_new(key_t *key)
|
||||
static int key_new(key_t *key)
|
||||
{
|
||||
RSA *rsa = NULL;
|
||||
EVP_PKEY *k = NULL;
|
||||
|
||||
/* Create key pair container */
|
||||
k = EVP_PKEY_new();
|
||||
if (k == NULL) {
|
||||
key->key = EVP_PKEY_new();
|
||||
if (key->key == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generate a new RSA key */
|
||||
rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL);
|
||||
if (EVP_PKEY_assign_RSA(k, rsa)) {
|
||||
key->key = k;
|
||||
return 1;
|
||||
} else {
|
||||
printf("Cannot assign RSA key\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int key_create(key_t *key, int type)
|
||||
{
|
||||
RSA *rsa = NULL;
|
||||
EC_KEY *ec = NULL;
|
||||
|
||||
/* Create OpenSSL key container */
|
||||
if (!key_new(key)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (k)
|
||||
EVP_PKEY_free(k);
|
||||
switch (type) {
|
||||
case KEY_ALG_RSA:
|
||||
/* Generate a new RSA key */
|
||||
rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL);
|
||||
if (rsa == NULL) {
|
||||
printf("Cannot create RSA key\n");
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_PKEY_assign_RSA(key->key, rsa)) {
|
||||
printf("Cannot assign RSA key\n");
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case KEY_ALG_ECDSA:
|
||||
/* Generate a new ECDSA key */
|
||||
ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
if (ec == NULL) {
|
||||
printf("Cannot create EC key\n");
|
||||
goto err;
|
||||
}
|
||||
if (!EC_KEY_generate_key(ec)) {
|
||||
printf("Cannot generate EC key\n");
|
||||
goto err;
|
||||
}
|
||||
EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS);
|
||||
EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
|
||||
if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) {
|
||||
printf("Cannot assign EC key\n");
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
RSA_free(rsa);
|
||||
EC_KEY_free(ec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int key_load(key_t *key)
|
||||
int key_load(key_t *key, unsigned int *err_code)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
EVP_PKEY *k = NULL;
|
||||
|
||||
/* Create key pair container */
|
||||
k = EVP_PKEY_new();
|
||||
if (k == NULL) {
|
||||
/* Create OpenSSL key container */
|
||||
if (!key_new(key)) {
|
||||
*err_code = KEY_ERR_MALLOC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -88,24 +128,24 @@ int key_load(key_t *key)
|
|||
/* Load key from file */
|
||||
fp = fopen(key->fn, "r");
|
||||
if (fp) {
|
||||
k = PEM_read_PrivateKey(fp, &k, NULL, NULL);
|
||||
k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL);
|
||||
fclose(fp);
|
||||
if (k) {
|
||||
key->key = k;
|
||||
*err_code = KEY_ERR_NONE;
|
||||
return 1;
|
||||
} else {
|
||||
ERROR("Cannot read key from %s\n", key->fn);
|
||||
ERROR("Cannot load key from %s\n", key->fn);
|
||||
*err_code = KEY_ERR_LOAD;
|
||||
}
|
||||
} else {
|
||||
ERROR("Cannot open file %s\n", key->fn);
|
||||
WARN("Cannot open file %s\n", key->fn);
|
||||
*err_code = KEY_ERR_OPEN;
|
||||
}
|
||||
} else {
|
||||
ERROR("Key filename not specified\n");
|
||||
WARN("Key filename not specified\n");
|
||||
*err_code = KEY_ERR_FILENAME;
|
||||
}
|
||||
|
||||
if (k)
|
||||
EVP_PKEY_free(k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#define VAL_DAYS 7300
|
||||
#define ID_TO_BIT_MASK(id) (1 << id)
|
||||
#define NVCOUNTER_VALUE 0
|
||||
#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0])))
|
||||
|
||||
/* Files */
|
||||
enum {
|
||||
|
@ -112,6 +113,7 @@ enum {
|
|||
};
|
||||
|
||||
/* Global options */
|
||||
static int key_alg;
|
||||
static int new_keys;
|
||||
static int save_keys;
|
||||
static int print_cert;
|
||||
|
@ -138,6 +140,11 @@ static char *strdup(const char *str)
|
|||
return dup;
|
||||
}
|
||||
|
||||
static const char *key_algs_str[] = {
|
||||
[KEY_ALG_RSA] = "rsa",
|
||||
[KEY_ALG_ECDSA] = "ecdsa"
|
||||
};
|
||||
|
||||
/* Command line options */
|
||||
static const struct option long_opt[] = {
|
||||
/* Binary images */
|
||||
|
@ -166,6 +173,7 @@ static const struct option long_opt[] = {
|
|||
{"bl32-key", required_argument, 0, BL32_KEY_ID},
|
||||
{"bl33-key", required_argument, 0, BL33_KEY_ID},
|
||||
/* Common options */
|
||||
{"key-alg", required_argument, 0, 'a'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"save-keys", no_argument, 0, 'k'},
|
||||
{"new-chain", no_argument, 0, 'n'},
|
||||
|
@ -189,6 +197,7 @@ static void print_help(const char *cmd)
|
|||
printf(" --%s <file> \\\n", long_opt[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
printf("-a Key algorithm: rsa (default), ecdsa\n");
|
||||
printf("-h Print help and exit\n");
|
||||
printf("-k Save key pairs into files. Filenames must be provided\n");
|
||||
printf("-n Generate new key pairs if no key files are provided\n");
|
||||
|
@ -198,8 +207,27 @@ static void print_help(const char *cmd)
|
|||
exit(0);
|
||||
}
|
||||
|
||||
static int get_key_alg(const char *key_alg_str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
|
||||
if (0 == strcmp(key_alg_str, key_algs_str[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void check_cmd_params(void)
|
||||
{
|
||||
/* Only save new keys */
|
||||
if (save_keys && !new_keys) {
|
||||
ERROR("Only new keys can be saved to disk\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* BL2, BL31 and BL33 are mandatory */
|
||||
if (certs[BL2_CERT].bin == NULL) {
|
||||
ERROR("BL2 image not specified\n");
|
||||
|
@ -276,14 +304,19 @@ int main(int argc, char *argv[])
|
|||
FILE *file = NULL;
|
||||
int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid;
|
||||
int c, opt_idx = 0;
|
||||
unsigned int err_code;
|
||||
unsigned char md[SHA256_DIGEST_LENGTH];
|
||||
const EVP_MD *md_info;
|
||||
|
||||
NOTICE("CoT Generation Tool: %s\n", build_msg);
|
||||
NOTICE("Target platform: %s\n", platform_msg);
|
||||
|
||||
/* Set default options */
|
||||
key_alg = KEY_ALG_RSA;
|
||||
|
||||
while (1) {
|
||||
/* getopt_long stores the option index here. */
|
||||
c = getopt_long(argc, argv, "hknp", long_opt, &opt_idx);
|
||||
c = getopt_long(argc, argv, "ahknp", long_opt, &opt_idx);
|
||||
|
||||
/* Detect the end of the options. */
|
||||
if (c == -1) {
|
||||
|
@ -291,6 +324,13 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
switch (c) {
|
||||
case 'a':
|
||||
key_alg = get_key_alg(optarg);
|
||||
if (key_alg < 0) {
|
||||
ERROR("Invalid key algorithm '%s'\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
print_help(argv[0]);
|
||||
break;
|
||||
|
@ -389,24 +429,50 @@ int main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/* Indicate SHA256 as image hash algorithm in the certificate
|
||||
* extension */
|
||||
md_info = EVP_sha256();
|
||||
|
||||
/* Get non-volatile counters NIDs */
|
||||
CHECK_OID(tz_nvctr_nid, TZ_FW_NVCOUNTER_OID);
|
||||
CHECK_OID(ntz_nvctr_nid, NTZ_FW_NVCOUNTER_OID);
|
||||
|
||||
/* Load private keys from files (or generate new ones) */
|
||||
if (new_keys) {
|
||||
for (i = 0 ; i < NUM_KEYS ; i++) {
|
||||
if (!key_new(&keys[i])) {
|
||||
ERROR("Error creating %s\n", keys[i].desc);
|
||||
exit(1);
|
||||
}
|
||||
for (i = 0 ; i < NUM_KEYS ; i++) {
|
||||
/* First try to load the key from disk */
|
||||
if (key_load(&keys[i], &err_code)) {
|
||||
/* Key loaded successfully */
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
for (i = 0 ; i < NUM_KEYS ; i++) {
|
||||
if (!key_load(&keys[i])) {
|
||||
ERROR("Error loading %s\n", keys[i].desc);
|
||||
|
||||
/* Key not loaded. Check the error code */
|
||||
if (err_code == KEY_ERR_MALLOC) {
|
||||
/* Cannot allocate memory. Abort. */
|
||||
ERROR("Malloc error while loading '%s'\n", keys[i].fn);
|
||||
exit(1);
|
||||
} else if (err_code == KEY_ERR_LOAD) {
|
||||
/* File exists, but it does not contain a valid private
|
||||
* key. Abort. */
|
||||
ERROR("Error loading '%s'\n", keys[i].fn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* File does not exist, could not be opened or no filename was
|
||||
* given */
|
||||
if (new_keys) {
|
||||
/* Try to create a new key */
|
||||
NOTICE("Creating new key for '%s'\n", keys[i].desc);
|
||||
if (!key_create(&keys[i], key_alg)) {
|
||||
ERROR("Error creating key '%s'\n", keys[i].desc);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if (err_code == KEY_ERR_OPEN) {
|
||||
ERROR("Error opening '%s'\n", keys[i].fn);
|
||||
} else {
|
||||
ERROR("Key '%s' not specified\n", keys[i].desc);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,7 +496,7 @@ int main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
CHECK_OID(hash_nid, BL2_HASH_OID);
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md,
|
||||
SHA256_DIGEST_LENGTH));
|
||||
sk_X509_EXTENSION_push(sk, hash_ext);
|
||||
|
||||
|
@ -509,8 +575,8 @@ int main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
CHECK_OID(hash_nid, BL30_HASH_OID);
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
|
||||
SHA256_DIGEST_LENGTH));
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info,
|
||||
md, SHA256_DIGEST_LENGTH));
|
||||
sk_X509_EXTENSION_push(sk, hash_ext);
|
||||
|
||||
if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) {
|
||||
|
@ -559,7 +625,7 @@ int main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
CHECK_OID(hash_nid, BL31_HASH_OID);
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md,
|
||||
SHA256_DIGEST_LENGTH));
|
||||
sk_X509_EXTENSION_push(sk, hash_ext);
|
||||
|
||||
|
@ -612,8 +678,8 @@ int main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
CHECK_OID(hash_nid, BL32_HASH_OID);
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
|
||||
SHA256_DIGEST_LENGTH));
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info,
|
||||
md, SHA256_DIGEST_LENGTH));
|
||||
sk_X509_EXTENSION_push(sk, hash_ext);
|
||||
|
||||
if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) {
|
||||
|
@ -662,7 +728,7 @@ int main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
CHECK_OID(hash_nid, BL33_HASH_OID);
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
|
||||
CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md,
|
||||
SHA256_DIGEST_LENGTH));
|
||||
sk_X509_EXTENSION_push(sk, hash_ext);
|
||||
|
||||
|
|
Loading…
Reference in New Issue