Commit 2d017e22 authored by danh-arm's avatar danh-arm
Browse files

Merge pull request #249 from danh-arm/jc/tbb_prototype

Trusted Board Boot Prototype
parents 03b23703 dec840af
...@@ -11,3 +11,5 @@ build/ ...@@ -11,3 +11,5 @@ build/
# Ignore build products from tools # Ignore build products from tools
tools/**/*.o tools/**/*.o
tools/fip_create/fip_create tools/fip_create/fip_create
tools/cert_create/src/*.o
tools/cert_create/cert_create
...@@ -67,6 +67,14 @@ ASM_ASSERTION := ${DEBUG} ...@@ -67,6 +67,14 @@ ASM_ASSERTION := ${DEBUG}
USE_COHERENT_MEM := 1 USE_COHERENT_MEM := 1
# Default FIP file name # Default FIP file name
FIP_NAME := fip.bin FIP_NAME := fip.bin
# By default, use the -pedantic option in the gcc command line
DISABLE_PEDANTIC := 0
# Flags to generate the Chain of Trust
GENERATE_COT := 0
CREATE_KEYS := 1
# Flags to build TF with Trusted Boot support
TRUSTED_BOARD_BOOT := 0
AUTH_MOD := none
# Checkpatch ignores # Checkpatch ignores
CHECK_IGNORE = --ignore COMPLEX_MACRO CHECK_IGNORE = --ignore COMPLEX_MACRO
...@@ -182,7 +190,7 @@ ifneq (${SPD},none) ...@@ -182,7 +190,7 @@ ifneq (${SPD},none)
# fip, then the NEED_BL32 needs to be set and BL3-2 would need to point to the bin. # fip, then the NEED_BL32 needs to be set and BL3-2 would need to point to the bin.
endif endif
.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip .PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip certtool
.SUFFIXES: .SUFFIXES:
INCLUDES += -Iinclude/bl31 \ INCLUDES += -Iinclude/bl31 \
...@@ -236,11 +244,19 @@ $(eval $(call add_define,LOG_LEVEL)) ...@@ -236,11 +244,19 @@ $(eval $(call add_define,LOG_LEVEL))
$(eval $(call assert_boolean,USE_COHERENT_MEM)) $(eval $(call assert_boolean,USE_COHERENT_MEM))
$(eval $(call add_define,USE_COHERENT_MEM)) $(eval $(call add_define,USE_COHERENT_MEM))
# Process Generate CoT flags
$(eval $(call assert_boolean,GENERATE_COT))
$(eval $(call assert_boolean,CREATE_KEYS))
# Process TRUSTED_BOARD_BOOT flag
$(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
$(eval $(call add_define,TRUSTED_BOARD_BOOT))
ASFLAGS += -nostdinc -ffreestanding -Wa,--fatal-warnings \ ASFLAGS += -nostdinc -ffreestanding -Wa,--fatal-warnings \
-Werror -Wmissing-include-dirs \ -Werror -Wmissing-include-dirs \
-mgeneral-regs-only -D__ASSEMBLY__ \ -mgeneral-regs-only -D__ASSEMBLY__ \
${DEFINES} ${INCLUDES} ${DEFINES} ${INCLUDES}
CFLAGS += -nostdinc -pedantic -ffreestanding -Wall \ CFLAGS += -nostdinc -ffreestanding -Wall \
-Werror -Wmissing-include-dirs \ -Werror -Wmissing-include-dirs \
-mgeneral-regs-only -std=c99 -c -Os \ -mgeneral-regs-only -std=c99 -c -Os \
${DEFINES} ${INCLUDES} ${DEFINES} ${INCLUDES}
...@@ -266,6 +282,53 @@ FIPTOOL ?= ${FIPTOOLPATH}/fip_create ...@@ -266,6 +282,53 @@ FIPTOOL ?= ${FIPTOOLPATH}/fip_create
fiptool: ${FIPTOOL} fiptool: ${FIPTOOL}
fip: ${BUILD_PLAT}/${FIP_NAME} fip: ${BUILD_PLAT}/${FIP_NAME}
# Variables for use with Certificate Generation Tool
CRTTOOLPATH ?= tools/cert_create
CRTTOOL ?= ${CRTTOOLPATH}/cert_create
certtool: ${CRTTOOL}
# CoT generation tool default parameters
TRUSTED_KEY_CERT := ${BUILD_PLAT}/trusted_key.crt
# Pass the private keys to the CoT generation tool in the command line
# If CREATE_KEYS is set, the '-n' option will be added, indicating the tool to create new keys
ifneq (${GENERATE_COT},0)
$(eval CERTS := yes)
$(eval FIP_DEPS += certificates)
$(eval FIP_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT})
ifneq (${CREATE_KEYS},0)
$(eval CRT_ARGS += -n)
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
endif
# Check if -pedantic option should be used
ifeq (${DISABLE_PEDANTIC},0)
CFLAGS += -pedantic
endif
locate-checkpatch: locate-checkpatch:
ifndef CHECKPATCH ifndef CHECKPATCH
$(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/script/checkpatch.pl") $(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/script/checkpatch.pl")
...@@ -279,12 +342,14 @@ clean: ...@@ -279,12 +342,14 @@ clean:
@echo " CLEAN" @echo " CLEAN"
${Q}rm -rf ${BUILD_PLAT} ${Q}rm -rf ${BUILD_PLAT}
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
realclean distclean: realclean distclean:
@echo " REALCLEAN" @echo " REALCLEAN"
${Q}rm -rf ${BUILD_BASE} ${Q}rm -rf ${BUILD_BASE}
${Q}rm -f ${CURDIR}/cscope.* ${Q}rm -f ${CURDIR}/cscope.*
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
checkcodebase: locate-checkpatch checkcodebase: locate-checkpatch
@echo " CHECKING STYLE" @echo " CHECKING STYLE"
...@@ -298,6 +363,13 @@ checkpatch: locate-checkpatch ...@@ -298,6 +363,13 @@ checkpatch: locate-checkpatch
@echo " CHECKING STYLE" @echo " CHECKING STYLE"
@git format-patch --stdout ${BASE_COMMIT} | ${CHECKPATCH} ${CHECKPATCH_ARGS} - || true @git format-patch --stdout ${BASE_COMMIT} | ${CHECKPATCH} ${CHECKPATCH_ARGS} - || true
.PHONY: ${CRTTOOL}
${CRTTOOL}:
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH}
@echo
@echo "Built $@ successfully"
@echo
.PHONY: ${FIPTOOL} .PHONY: ${FIPTOOL}
${FIPTOOL}: ${FIPTOOL}:
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH}
...@@ -398,6 +470,39 @@ define SOURCES_TO_OBJS ...@@ -398,6 +470,39 @@ define SOURCES_TO_OBJS
$(notdir $(patsubst %.S,%.o,$(filter %.S,$(1)))) $(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
endef endef
# MAKE_TOOL_ARGS macro defines the command line arguments for the FIP and CRT
# tools at each BL stage. Arguments:
# $(1) = BL stage (2, 30, 31, 32, 33)
# $(2) = Binary file
# $(3) = In FIP (false if empty)
# $(4) = Create certificates (false if empty)
# $(5) = Create key certificate (false if empty)
# $(6) = Private key (optional)
define MAKE_TOOL_ARGS
$(eval FIP_DEPS += $(if $3,$(2),))
$(eval FIP_ARGS += $(if $3,--bl$(1) $(2),))
$(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))
$(eval CRT_ARGS += $(if $4,$(if $5,--bl$(1)-key-cert $(BUILD_PLAT)/bl$(1)_key.crt)))
endef
# MAKE_BL macro defines the targets and options to build each BL image.
# Arguments:
# $(1) = BL stage (2, 30, 31, 32, 33)
# $(2) = In FIP (false if empty)
# $(3) = Create certificates (false if empty)
# $(4) = Create key certificate (false if empty)
# $(5) = Private key (optional)
define MAKE_BL define MAKE_BL
$(eval BUILD_DIR := ${BUILD_PLAT}/bl$(1)) $(eval BUILD_DIR := ${BUILD_PLAT}/bl$(1))
$(eval SOURCES := $(BL$(1)_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES)) $(eval SOURCES := $(BL$(1)_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES))
...@@ -438,8 +543,7 @@ bl$(1) : $(BUILD_DIR) $(BIN) $(DUMP) ...@@ -438,8 +543,7 @@ bl$(1) : $(BUILD_DIR) $(BIN) $(DUMP)
all : bl$(1) all : bl$(1)
$(eval FIP_DEPS += $(if $2,$(BIN),)) $(eval $(call MAKE_TOOL_ARGS,$(1),$(BIN),$(2),$(3),$(4),$(5)))
$(eval FIP_ARGS += $(if $2,--bl$(1) $(BIN),))
endef endef
...@@ -449,23 +553,23 @@ $(eval $(call MAKE_BL,1)) ...@@ -449,23 +553,23 @@ $(eval $(call MAKE_BL,1))
endif endif
ifeq (${NEED_BL2},yes) ifeq (${NEED_BL2},yes)
$(if ${BL2}, $(eval FIP_DEPS += ${BL2}) $(eval FIP_ARGS += --bl2 ${BL2}),\ $(if ${BL2}, $(eval $(call MAKE_TOOL_ARGS,2,${BL2},in_fip,${CERTS})),\
$(eval $(call MAKE_BL,2,in_fip))) $(eval $(call MAKE_BL,2,in_fip,${CERTS})))
endif endif
ifeq (${NEED_BL31},yes) ifeq (${NEED_BL31},yes)
BL31_SOURCES += ${SPD_SOURCES} BL31_SOURCES += ${SPD_SOURCES}
$(if ${BL31}, $(eval FIP_DEPS += ${BL31}) $(eval FIP_ARGS += --bl31 ${BL31}),\ $(if ${BL31}, $(eval $(call MAKE_TOOL_ARGS,31,${BL31},in_fip,${CERTS},${CERTS},${BL31_KEY})),\
$(eval $(call MAKE_BL,31,in_fip))) $(eval $(call MAKE_BL,31,in_fip,${CERTS},${CERTS},${BL31_KEY})))
endif endif
ifeq (${NEED_BL32},yes) ifeq (${NEED_BL32},yes)
$(if ${BL32}, $(eval FIP_DEPS += ${BL32}) $(eval FIP_ARGS += --bl32 ${BL32}),\ $(if ${BL32}, $(eval $(call MAKE_TOOL_ARGS,32,${BL32},in_fip,${CERTS},${CERTS},${BL32_KEY})),\
$(eval $(call MAKE_BL,32,in_fip))) $(eval $(call MAKE_BL,32,in_fip,${CERTS},${CERTS},${BL32_KEY})))
endif endif
ifeq (${NEED_BL30},yes) ifeq (${NEED_BL30},yes)
$(if ${BL30}, $(eval FIP_DEPS += ${BL30}) $(eval FIP_ARGS += --bl30 ${BL30}), ) $(if ${BL30}, $(eval $(call MAKE_TOOL_ARGS,30,${BL30},in_fip,${CERTS},${CERTS},${BL30_KEY})))
# If BL3-0 is needed by the platform then 'BL30' variable must be defined. # If BL3-0 is needed by the platform then 'BL30' variable must be defined.
check_bl30: check_bl30:
...@@ -479,7 +583,7 @@ check_bl30: ...@@ -479,7 +583,7 @@ check_bl30:
endif endif
ifeq (${NEED_BL33},yes) ifeq (${NEED_BL33},yes)
$(if ${BL33}, $(eval FIP_DEPS += ${BL33}) $(eval FIP_ARGS += --bl33 ${BL33}), ) $(if ${BL33}, $(eval $(call MAKE_TOOL_ARGS,33,${BL33},in_fip,${CERTS},${CERTS},${BL33_KEY})))
# If BL3-3 is needed by the platform then 'BL33' variable must be defined. # If BL3-3 is needed by the platform then 'BL33' variable must be defined.
check_bl33: check_bl33:
...@@ -492,6 +596,17 @@ check_bl33: ...@@ -492,6 +596,17 @@ check_bl33:
$(if ${BL33},$(warning "BL3-3 is not supported on platform ${PLAT}, it will just be ignored"),) $(if ${BL33},$(warning "BL3-3 is not supported on platform ${PLAT}, it will just be ignored"),)
endif endif
# Add the dependency on the certificates
ifneq (${GENERATE_COT},0)
all: certificates
endif
certificates: ${CRT_DEPS} ${CRTTOOL} check_bl30 check_bl33
${Q}${CRTTOOL} ${CRT_ARGS}
@echo
@echo "Built $@ successfully"
@echo "Certificates can be found in ${BUILD_PLAT}"
@echo
${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL} check_bl30 check_bl33 ${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL} check_bl30 check_bl33
${Q}${FIPTOOL} --dump \ ${Q}${FIPTOOL} --dump \
...@@ -524,6 +639,7 @@ help: ...@@ -524,6 +639,7 @@ help:
@echo " clean Clean the build for the selected platform" @echo " clean Clean the build for the selected platform"
@echo " cscope Generate cscope index" @echo " cscope Generate cscope index"
@echo " distclean Remove all build artifacts for all platforms" @echo " distclean Remove all build artifacts for all platforms"
@echo " certtool Build the Certificate generation tool"
@echo " fiptool Build the Firmware Image Package(FIP) creation tool" @echo " fiptool Build the Firmware Image Package(FIP) creation tool"
@echo "" @echo ""
@echo "note: most build targets require PLAT to be set to a specific platform." @echo "note: most build targets require PLAT to be set to a specific platform."
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <arch.h> #include <arch.h>
#include <arch_helpers.h> #include <arch_helpers.h>
#include <assert.h> #include <assert.h>
#include <auth.h>
#include <bl_common.h> #include <bl_common.h>
#include <debug.h> #include <debug.h>
#include <platform.h> #include <platform.h>
...@@ -141,6 +142,34 @@ void bl1_main(void) ...@@ -141,6 +142,34 @@ void bl1_main(void)
/* Find out how much free trusted ram remains after BL1 load */ /* Find out how much free trusted ram remains after BL1 load */
bl1_tzram_layout = bl1_plat_sec_mem_layout(); bl1_tzram_layout = bl1_plat_sec_mem_layout();
#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();
}
#endif /* TRUSTED_BOARD_BOOT */
/* Load the BL2 image */ /* Load the BL2 image */
err = load_image(bl1_tzram_layout, err = load_image(bl1_tzram_layout,
BL2_IMAGE_NAME, BL2_IMAGE_NAME,
...@@ -155,6 +184,20 @@ void bl1_main(void) ...@@ -155,6 +184,20 @@ void bl1_main(void)
ERROR("Failed to load BL2 firmware.\n"); ERROR("Failed to load BL2 firmware.\n");
panic(); 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. * Create a new layout of memory for BL2 as seen by BL1 i.e.
* tell it the amount of total and free memory available. * tell it the amount of total and free memory available.
......
...@@ -31,12 +31,149 @@ ...@@ -31,12 +31,149 @@
#include <arch.h> #include <arch.h>
#include <arch_helpers.h> #include <arch_helpers.h>
#include <assert.h> #include <assert.h>
#include <auth.h>
#include <bl_common.h> #include <bl_common.h>
#include <debug.h> #include <debug.h>
#include <platform.h> #include <platform.h>
#include <platform_def.h> #include <platform_def.h>
#include "bl2_private.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. * 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 * If a platform does not want to attempt to load BL3-0 image it must leave
...@@ -69,6 +206,20 @@ static int load_bl30(void) ...@@ -69,6 +206,20 @@ static int load_bl30(void)
NULL); NULL);
if (e == 0) { if (e == 0) {
#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");
panic();
}
/* 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 */ /* The subsequent handling of BL3-0 is platform specific */
bl2_plat_handle_bl30(&bl30_image_info); bl2_plat_handle_bl30(&bl30_image_info);
} }
...@@ -106,9 +257,24 @@ static int load_bl31(bl31_params_t *bl2_to_bl31_params, ...@@ -106,9 +257,24 @@ static int load_bl31(bl31_params_t *bl2_to_bl31_params,
bl2_to_bl31_params->bl31_image_info, bl2_to_bl31_params->bl31_image_info,
bl31_ep_info); bl31_ep_info);
if (e == 0) if (e == 0) {
#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");
panic();
}
/* 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, bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info,
bl31_ep_info); bl31_ep_info);
}
return e; return e;
} }
...@@ -144,6 +310,25 @@ static int load_bl32(bl31_params_t *bl2_to_bl31_params) ...@@ -144,6 +310,25 @@ static int load_bl32(bl31_params_t *bl2_to_bl31_params)
bl2_to_bl31_params->bl32_ep_info); bl2_to_bl31_params->bl32_ep_info);
if (e == 0) { if (e == 0) {
#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");
panic();
}
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");
panic();
}
/* 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_plat_set_bl32_ep_info(
bl2_to_bl31_params->bl32_image_info, bl2_to_bl31_params->bl32_image_info,
bl2_to_bl31_params->bl32_ep_info); bl2_to_bl31_params->bl32_ep_info);
...@@ -176,9 +361,23 @@ static int load_bl33(bl31_params_t *bl2_to_bl31_params) ...@@ -176,9 +361,23 @@ static int load_bl33(bl31_params_t *bl2_to_bl31_params)
bl2_to_bl31_params->bl33_image_info, bl2_to_bl31_params->bl33_image_info,
bl2_to_bl31_params->bl33_ep_info); bl2_to_bl31_params->bl33_ep_info);
if (e == 0) if (e == 0) {
#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");
panic();
}
/* 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_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info,
bl2_to_bl31_params->bl33_ep_info); bl2_to_bl31_params->bl33_ep_info);
}
return e; return e;
} }
...@@ -200,6 +399,18 @@ void bl2_main(void) ...@@ -200,6 +399,18 @@ void bl2_main(void)
/* Perform remaining generic architectural setup in S-EL1 */ /* Perform remaining generic architectural setup in S-EL1 */
bl2_arch_setup(); bl2_arch_setup();
#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();
}
#endif /* TRUSTED_BOARD_BOOT */
/* /*
* Load the subsequent bootloader images * Load the subsequent bootloader images
*/ */
......
/*
* 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.h>
#include <debug.h>
/*
* Initialize the authentication module
*/
void auth_init(void)
{
assert(auth_mod.name);
assert(auth_mod.init);
assert(auth_mod.verify);
INFO("Using authentication module '%s'\n", auth_mod.name);
if (auth_mod.init() != 0)
assert(0);
}
/*
* Authenticate a certificate/image
*
* Return: 0 = success, Otherwise = error
*/
int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len)
{
assert(obj_id < AUTH_NUM_OBJ);
assert(obj_buf != 0);
assert(auth_mod.verify);
return auth_mod.verify(obj_id, obj_buf, len);
}
/*
* 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
};
#
# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# Neither the name of ARM nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# POLARSSL_DIR must be set to the PolarSSL main directory (it must contain
# the 'include' and 'library' subdirectories).
ifeq (${POLARSSL_DIR},)
$(error Error: POLARSSL_DIR not set)
endif
INCLUDES += -I${POLARSSL_DIR}/include \
-Icommon/auth/polarssl
POLARSSL_CONFIG_FILE := "<polarssl_config.h>"
$(eval $(call add_define,POLARSSL_CONFIG_FILE))
POLARSSL_SOURCES := $(addprefix ${POLARSSL_DIR}/library/, \
asn1parse.c \
asn1write.c \
bignum.c \
md.c \
md_wrap.c \
memory_buffer_alloc.c \
oid.c \
pk.c \
pk_wrap.c \
pkparse.c \
pkwrite.c \
platform.c \
rsa.c \
sha1.c \
sha256.c \
x509.c \
x509_crt.c \
)
BL1_SOURCES += ${POLARSSL_SOURCES} \
common/auth/polarssl/polarssl.c
BL2_SOURCES += ${POLARSSL_SOURCES} \
common/auth/polarssl/polarssl.c
DISABLE_PEDANTIC := 1
/*
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __POLARSSL_CONFIG_H__
#define __POLARSSL_CONFIG_H__
/*
* Configuration file to build PolarSSL with the required features for
* Trusted Boot
*/
#define POLARSSL_PLATFORM_MEMORY
#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS
#define POLARSSL_PKCS1_V15
#define POLARSSL_PKCS1_V21
#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
#define POLARSSL_X509_CHECK_KEY_USAGE
#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE
#define POLARSSL_ASN1_PARSE_C
#define POLARSSL_ASN1_WRITE_C
#define POLARSSL_BASE64_C
#define POLARSSL_BIGNUM_C
#define POLARSSL_ERROR_C
#define POLARSSL_MD_C
#define POLARSSL_MEMORY_BUFFER_ALLOC_C
#define POLARSSL_OID_C
#define POLARSSL_PK_C
#define POLARSSL_PK_PARSE_C
#define POLARSSL_PK_WRITE_C
#define POLARSSL_PLATFORM_C
#define POLARSSL_RSA_C
#define POLARSSL_SHA1_C
#define POLARSSL_SHA256_C
#define POLARSSL_VERSION_C
#define POLARSSL_X509_USE_C
#define POLARSSL_X509_CRT_PARSE_C
/* MPI / BIGNUM options */
#define POLARSSL_MPI_WINDOW_SIZE 2
#define POLARSSL_MPI_MAX_SIZE 256
/* Memory buffer allocator options */
#define POLARSSL_MEMORY_ALIGN_MULTIPLE 8
#include "polarssl/check_config.h"
#endif /* __POLARSSL_CONFIG_H__ */
...@@ -275,9 +275,16 @@ int load_image(meminfo_t *mem_layout, ...@@ -275,9 +275,16 @@ int load_image(meminfo_t *mem_layout,
* Update the memory usage info. * Update the memory usage info.
* This is done after the actual loading so that it is not updated when * This is done after the actual loading so that it is not updated when
* the load is unsuccessful. * the load is unsuccessful.
* If the caller does not provide an entry point, bypass the memory
* reservation.
*/ */
reserve_mem(&mem_layout->free_base, &mem_layout->free_size, if (entry_point_info != NULL) {
image_base, image_size); reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
image_base, image_size);
} else {
INFO("Skip reserving memory: 0x%lx - 0x%lx\n",
image_base, image_base + image_size);
}
image_data->image_base = image_base; image_data->image_base = image_base;
image_data->image_size = image_size; image_data->image_size = image_size;
......
...@@ -392,6 +392,17 @@ The ARM FVP port uses this function to initialize the mailbox memory used for ...@@ -392,6 +392,17 @@ The ARM FVP port uses this function to initialize the mailbox memory used for
providing the warm-boot entry-point addresses. providing the warm-boot entry-point addresses.
### Function: plat_match_rotpk()
Argument : const unsigned char *, 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.
2.3 Common optional modifications 2.3 Common optional modifications
--------------------------------- ---------------------------------
......
...@@ -76,6 +76,23 @@ static const plat_fip_name_uuid_t name_uuid[] = { ...@@ -76,6 +76,23 @@ static const plat_fip_name_uuid_t name_uuid[] = {
{BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32}, {BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32},
#endif /* BL32_IMAGE_NAME */ #endif /* BL32_IMAGE_NAME */
{BL33_IMAGE_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33}, {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 const uuid_t uuid_null = {0};
......
/*
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AUTH_H_
#define AUTH_H_
#include <stddef.h>
#include <stdint.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.
*/
/* Objects (images and certificates) involved in the TBB process */
enum {
AUTH_BL2_IMG_CERT,
AUTH_BL2_IMG,
AUTH_TRUSTED_KEY_CERT,
AUTH_BL30_KEY_CERT,
AUTH_BL30_IMG_CERT,
AUTH_BL30_IMG,
AUTH_BL31_KEY_CERT,
AUTH_BL31_IMG_CERT,
AUTH_BL31_IMG,
AUTH_BL32_KEY_CERT,
AUTH_BL32_IMG_CERT,
AUTH_BL32_IMG,
AUTH_BL33_KEY_CERT,
AUTH_BL33_IMG_CERT,
AUTH_BL33_IMG,
AUTH_NUM_OBJ
};
/* Authentication module structure */
typedef struct auth_mod_s {
/* [mandatory] Module name. Printed to the log during initialization */
const char *name;
/* [mandatory] Initialize the authentication module */
int (*init)(void);
/* [mandatory] This function will be called to authenticate a new
* object loaded into memory. The obj_id corresponds to one of the
* values in the enumeration above */
int (*verify)(unsigned int obj_id, uintptr_t obj_buf, size_t len);
} auth_mod_t;
/* This variable must be instantiated by the authentication module */
extern const auth_mod_t auth_mod;
/* Public functions */
void auth_init(void);
int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len);
#endif /* AUTH_H_ */
...@@ -49,6 +49,32 @@ ...@@ -49,6 +49,32 @@
{0x89e1d005, 0xdc53, 0x4713, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} } {0x89e1d005, 0xdc53, 0x4713, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} }
#define UUID_NON_TRUSTED_FIRMWARE_BL33 \ #define UUID_NON_TRUSTED_FIRMWARE_BL33 \
{0xa7eed0d6, 0xeafc, 0x4bd5, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} } {0xa7eed0d6, 0xeafc, 0x4bd5, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} }
/* Key certificates */
#define UUID_ROT_KEY_CERT \
{0x721d2d86, 0x60f8, 0x11e4, 0x92, 0x0b, {0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24} }
#define UUID_TRUSTED_KEY_CERT \
{0x90e87e82, 0x60f8, 0x11e4, 0xa1, 0xb4, {0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c} }
#define UUID_NON_TRUSTED_WORLD_KEY_CERT \
{0x3d87671c, 0x635f, 0x11e4, 0x97, 0x8d, {0x27, 0xc0, 0xc7, 0x14, 0x8a, 0xbd} }
#define UUID_SCP_FIRMWARE_BL30_KEY_CERT \
{0xa1214202, 0x60f8, 0x11e4, 0x8d, 0x9b, {0xf3, 0x3c, 0x0e, 0x15, 0xa0, 0x14} }
#define UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT \
{0xccbeb88a, 0x60f9, 0x11e4, 0x9a, 0xd0, {0xeb, 0x48, 0x22, 0xd8, 0xdc, 0xf8} }
#define UUID_SECURE_PAYLOAD_BL32_KEY_CERT \
{0x03d67794, 0x60fb, 0x11e4, 0x85, 0xdd, {0xb7, 0x10, 0x5b, 0x8c, 0xee, 0x04} }
#define UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT \
{0x2a83d58a, 0x60fb, 0x11e4, 0x8a, 0xaf, {0xdf, 0x30, 0xbb, 0xc4, 0x98, 0x59} }
/* Content certificates */
#define UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT \
{0xea69e2d6, 0x635d, 0x11e4, 0x8d, 0x8c, {0x9f, 0xba, 0xbe, 0x99, 0x56, 0xa5} }
#define UUID_SCP_FIRMWARE_BL30_CERT \
{0x046fbe44, 0x635e, 0x11e4, 0xb2, 0x8b, {0x73, 0xd8, 0xea, 0xae, 0x96, 0x56} }
#define UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT \
{0x200cb2e2, 0x635e, 0x11e4, 0x9c, 0xe8, {0xab, 0xcc, 0xf9, 0x2b, 0xb6, 0x66} }
#define UUID_SECURE_PAYLOAD_BL32_CERT \
{0x11449fa4, 0x635e, 0x11e4, 0x87, 0x28, {0x3f, 0x05, 0x72, 0x2a, 0xf3, 0x3d} }
#define UUID_NON_TRUSTED_FIRMWARE_BL33_CERT \
{0xf3c1c48e, 0x635d, 0x11e4, 0xa7, 0xa9, {0x87, 0xee, 0x40, 0xb2, 0x3f, 0xa7} }
typedef struct fip_toc_header { typedef struct fip_toc_header {
uint32_t name; uint32_t name;
......
...@@ -191,4 +191,9 @@ void bl31_plat_enable_mmu(uint32_t flags); ...@@ -191,4 +191,9 @@ void bl31_plat_enable_mmu(uint32_t flags);
******************************************************************************/ ******************************************************************************/
void bl32_plat_enable_mmu(uint32_t flags); void bl32_plat_enable_mmu(uint32_t flags);
/*******************************************************************************
* Trusted Boot functions
******************************************************************************/
int plat_match_rotpk(const unsigned char *, unsigned int);
#endif /* __PLATFORM_H__ */ #endif /* __PLATFORM_H__ */
/*-
* Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#ifndef _INTTYPES_H_
#define _INTTYPES_H_
#include <machine/_inttypes.h>
#include <sys/stdint.h>
typedef struct {
intmax_t quot; /* Quotient. */
intmax_t rem; /* Remainder. */
} imaxdiv_t;
__BEGIN_DECLS
#ifdef _XLOCALE_H_
#include <xlocale/_inttypes.h>
#endif
intmax_t imaxabs(intmax_t) __pure2;
imaxdiv_t imaxdiv(intmax_t, intmax_t) __pure2;
intmax_t strtoimax(const char *__restrict, char **__restrict, int);
uintmax_t strtoumax(const char *__restrict, char **__restrict, int);
__END_DECLS
#endif /* !_INTTYPES_H_ */
/*
* 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 _MACHINE_INTTYPES_H_
#define _MACHINE_INTTYPES_H_
/*
* Trusted Firmware does not depend on any definitions in this file. Content
* will be added as needed.
*/
#endif /* !_MACHINE_INTTYPES_H_ */
...@@ -65,6 +65,8 @@ int sprintf(char * __restrict, const char * __restrict, ...); ...@@ -65,6 +65,8 @@ int sprintf(char * __restrict, const char * __restrict, ...);
int vsprintf(char * __restrict, const char * __restrict, int vsprintf(char * __restrict, const char * __restrict,
__va_list); __va_list);
int sscanf(const char *__restrict, char const *__restrict, ...);
#if __ISO_C_VISIBLE >= 1999 #if __ISO_C_VISIBLE >= 1999
int snprintf(char * __restrict, size_t, const char * __restrict, int snprintf(char * __restrict, size_t, const char * __restrict,
...) __printflike(3, 4); ...) __printflike(3, 4);
......
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)stdlib.h 8.5 (Berkeley) 5/19/95
* $FreeBSD$
*/
#ifndef _STDLIB_H_
#define _STDLIB_H_
#include <sys/cdefs.h>
#include <sys/_null.h>
#include <sys/_types.h>
#if __BSD_VISIBLE
#ifndef _RUNE_T_DECLARED
typedef __rune_t rune_t;
#define _RUNE_T_DECLARED
#endif
#endif
#ifndef _SIZE_T_DECLARED
typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
typedef struct {
int quot; /* quotient */
int rem; /* remainder */
} div_t;
typedef struct {
long quot;
long rem;
} ldiv_t;
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#define RAND_MAX 0x7ffffffd
__BEGIN_DECLS
#ifdef _XLOCALE_H_
#include <xlocale/_stdlib.h>
#endif
extern int __mb_cur_max;
extern int ___mb_cur_max(void);
#define MB_CUR_MAX (___mb_cur_max())
_Noreturn void abort(void);
int abs(int) __pure2;
int atexit(void (*)(void));
double atof(const char *);
int atoi(const char *);
long atol(const char *);
void *bsearch(const void *, const void *, size_t,
size_t, int (*)(const void *, const void *));
void *calloc(size_t, size_t) __malloc_like;
div_t div(int, int) __pure2;
_Noreturn void exit(int);
void free(void *);
char *getenv(const char *);
long labs(long) __pure2;
ldiv_t ldiv(long, long) __pure2;
void *malloc(size_t) __malloc_like;
int mblen(const char *, size_t);
void qsort(void *, size_t, size_t,
int (*)(const void *, const void *));
int rand(void);
void *realloc(void *, size_t);
void srand(unsigned);
double strtod(const char *__restrict, char **__restrict);
float strtof(const char *__restrict, char **__restrict);
long strtol(const char *__restrict, char **__restrict, int);
long double
strtold(const char *__restrict, char **__restrict);
unsigned long
strtoul(const char *__restrict, char **__restrict, int);
int system(const char *);
/*
* Functions added in C99 which we make conditionally available in the
* BSD^C89 namespace if the compiler supports `long long'.
* The #if test is more complicated than it ought to be because
* __BSD_VISIBLE implies __ISO_C_VISIBLE == 1999 *even if* `long long'
* is not supported in the compilation environment (which therefore means
* that it can't really be ISO C99).
*
* (The only other extension made by C99 in thie header is _Exit().)
*/
#if __ISO_C_VISIBLE >= 1999
#ifdef __LONG_LONG_SUPPORTED
/* LONGLONG */
typedef struct {
long long quot;
long long rem;
} lldiv_t;
/* LONGLONG */
long long
atoll(const char *);
/* LONGLONG */
long long
llabs(long long) __pure2;
/* LONGLONG */
lldiv_t lldiv(long long, long long) __pure2;
/* LONGLONG */
long long
strtoll(const char *__restrict, char **__restrict, int);
/* LONGLONG */
unsigned long long
strtoull(const char *__restrict, char **__restrict, int);
#endif /* __LONG_LONG_SUPPORTED */
_Noreturn void _Exit(int);
#endif /* __ISO_C_VISIBLE >= 1999 */
/*
* If we're in a mode greater than C99, expose C11 functions.
*/
#if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L
void *aligned_alloc(size_t, size_t) __malloc_like;
int at_quick_exit(void (*)(void));
_Noreturn void
quick_exit(int);
#endif /* __ISO_C_VISIBLE >= 2011 */
/*
* Extensions made by POSIX relative to C.
*/
#if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE
char *realpath(const char *__restrict, char *__restrict);
#endif
#if __POSIX_VISIBLE >= 199506
int rand_r(unsigned *); /* (TSF) */
#endif
#if __POSIX_VISIBLE >= 200112
int posix_memalign(void **, size_t, size_t); /* (ADV) */
int setenv(const char *, const char *, int);
int unsetenv(const char *);
#endif
#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE
int getsubopt(char **, char *const *, char **);
#ifndef _MKDTEMP_DECLARED
char *mkdtemp(char *);
#define _MKDTEMP_DECLARED
#endif
#ifndef _MKSTEMP_DECLARED
int mkstemp(char *);
#define _MKSTEMP_DECLARED
#endif
#endif /* __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE */
/*
* The only changes to the XSI namespace in revision 6 were the deletion
* of the ttyslot() and valloc() functions, which FreeBSD never declared
* in this header. For revision 7, ecvt(), fcvt(), and gcvt(), which
* FreeBSD also does not have, and mktemp(), are to be deleted.
*/
#if __XSI_VISIBLE
/* XXX XSI requires pollution from <sys/wait.h> here. We'd rather not. */
long a64l(const char *);
double drand48(void);
/* char *ecvt(double, int, int * __restrict, int * __restrict); */
double erand48(unsigned short[3]);
/* char *fcvt(double, int, int * __restrict, int * __restrict); */
/* char *gcvt(double, int, int * __restrict, int * __restrict); */
int grantpt(int);
char *initstate(unsigned long /* XSI requires u_int */, char *, long);
long jrand48(unsigned short[3]);
char *l64a(long);
void lcong48(unsigned short[7]);
long lrand48(void);
#if !defined(_MKTEMP_DECLARED) && (__BSD_VISIBLE || __XSI_VISIBLE <= 600)
char *mktemp(char *);
#define _MKTEMP_DECLARED
#endif
long mrand48(void);
long nrand48(unsigned short[3]);
int posix_openpt(int);
char *ptsname(int);
int putenv(char *);
long random(void);
unsigned short
*seed48(unsigned short[3]);
#ifndef _SETKEY_DECLARED
int setkey(const char *);
#define _SETKEY_DECLARED
#endif
char *setstate(/* const */ char *);
void srand48(long);
void srandom(unsigned long);
int unlockpt(int);
#endif /* __XSI_VISIBLE */
#if __BSD_VISIBLE
extern const char *malloc_conf;
extern void (*malloc_message)(void *, const char *);
/*
* The alloca() function can't be implemented in C, and on some
* platforms it can't be implemented at all as a callable function.
* The GNU C compiler provides a built-in alloca() which we can use;
* in all other cases, provide a prototype, mainly to pacify various
* incarnations of lint. On platforms where alloca() is not in libc,
* programs which use it will fail to link when compiled with non-GNU
* compilers.
*/
#if __GNUC__ >= 2 || defined(__INTEL_COMPILER)
#undef alloca /* some GNU bits try to get cute and define this on their own */
#define alloca(sz) __builtin_alloca(sz)
#elif defined(lint)
void *alloca(size_t);
#endif
void abort2(const char *, int, void **) __dead2;
__uint32_t
arc4random(void);
void arc4random_addrandom(unsigned char *, int);
void arc4random_buf(void *, size_t);
void arc4random_stir(void);
__uint32_t
arc4random_uniform(__uint32_t);
#ifdef __BLOCKS__
int atexit_b(void (^)(void));
void *bsearch_b(const void *, const void *, size_t,
size_t, int (^)(const void *, const void *));
#endif
char *getbsize(int *, long *);
/* getcap(3) functions */
char *cgetcap(char *, const char *, int);
int cgetclose(void);
int cgetent(char **, char **, const char *);
int cgetfirst(char **, char **);
int cgetmatch(const char *, const char *);
int cgetnext(char **, char **);
int cgetnum(char *, const char *, long *);
int cgetset(const char *);
int cgetstr(char *, const char *, char **);
int cgetustr(char *, const char *, char **);
int daemon(int, int);
char *devname(__dev_t, __mode_t);
char *devname_r(__dev_t, __mode_t, char *, int);
char *fdevname(int);
char *fdevname_r(int, char *, int);
int getloadavg(double [], int);
const char *
getprogname(void);
int heapsort(void *, size_t, size_t, int (*)(const void *, const void *));
#ifdef __BLOCKS__
int heapsort_b(void *, size_t, size_t, int (^)(const void *, const void *));
void qsort_b(void *, size_t, size_t,
int (^)(const void *, const void *));
#endif
int l64a_r(long, char *, int);
int mergesort(void *, size_t, size_t, int (*)(const void *, const void *));
#ifdef __BLOCKS__
int mergesort_b(void *, size_t, size_t, int (^)(const void *, const void *));
#endif
int mkostemp(char *, int);
int mkostemps(char *, int, int);
void qsort_r(void *, size_t, size_t, void *,
int (*)(void *, const void *, const void *));
int radixsort(const unsigned char **, int, const unsigned char *,
unsigned);
void *reallocf(void *, size_t);
int rpmatch(const char *);
void setprogname(const char *);
int sradixsort(const unsigned char **, int, const unsigned char *,
unsigned);
void sranddev(void);
void srandomdev(void);
long long
strtonum(const char *, long long, long long, const char **);
/* Deprecated interfaces, to be removed in FreeBSD 6.0. */
__int64_t
strtoq(const char *, char **, int);
__uint64_t
strtouq(const char *, char **, int);
extern char *suboptarg; /* getsubopt(3) external variable */
#endif /* __BSD_VISIBLE */
__END_DECLS
#endif /* !_STDLIB_H_ */
...@@ -59,6 +59,7 @@ char *strchr(const char *, int) __pure; ...@@ -59,6 +59,7 @@ char *strchr(const char *, int) __pure;
int strcmp(const char *, const char *) __pure; int strcmp(const char *, const char *) __pure;
size_t strlen(const char *) __pure; size_t strlen(const char *) __pure;
int strncmp(const char *, const char *, size_t) __pure; int strncmp(const char *, const char *, size_t) __pure;
int strcasecmp(const char *, const char *);
__END_DECLS __END_DECLS
......
/*-
* Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#ifndef _STRINGS_H_
#define _STRINGS_H_
#include <sys/cdefs.h>
#include <sys/_types.h>
#ifndef _SIZE_T_DECLARED
typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
__BEGIN_DECLS
#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112
int bcmp(const void *, const void *, size_t) __pure; /* LEGACY */
void bcopy(const void *, void *, size_t); /* LEGACY */
void bzero(void *, size_t); /* LEGACY */
#endif
#if __BSD_VISIBLE
void explicit_bzero(void *, size_t);
#endif
#if __XSI_VISIBLE
int ffs(int) __pure2;
#endif
#if __BSD_VISIBLE
int ffsl(long) __pure2;
int ffsll(long long) __pure2;
int fls(int) __pure2;
int flsl(long) __pure2;
int flsll(long long) __pure2;
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112
char *index(const char *, int) __pure; /* LEGACY */
char *rindex(const char *, int) __pure; /* LEGACY */
#endif
int strcasecmp(const char *, const char *) __pure;
int strncasecmp(const char *, const char *, size_t) __pure;
#if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_)
#include <xlocale/_strings.h>
#endif
__END_DECLS
#endif /* _STRINGS_H_ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment