Commit 091576e7 authored by Sandrine Bailleux's avatar Sandrine Bailleux Committed by TrustedFirmware Code Review
Browse files

Merge changes from topic "tbbr/fw_enc" into integration

* changes:
  docs: qemu: Add instructions to boot using FIP image
  docs: Update docs with firmware encryption feature
  qemu: Support optional encryption of BL31 and BL32 images
  qemu: Update flash address map to keep FIP in secure FLASH0
  Makefile: Add support to optionally encrypt BL31 and BL32
  tools: Add firmware authenticated encryption tool
  TBB: Add an IO abstraction layer to load encrypted firmwares
  drivers: crypto: Add authenticated decryption framework
parents a3d0fa31 4ebbea95
......@@ -159,6 +159,14 @@ else
endif
endif
ifneq (${DECRYPTION_SUPPORT},none)
ENC_ARGS += -f ${FW_ENC_STATUS}
ENC_ARGS += -k ${ENC_KEY}
ENC_ARGS += -n ${ENC_NONCE}
FIP_DEPS += enctool
FWU_FIP_DEPS += enctool
endif
################################################################################
# Toolchain
################################################################################
......@@ -623,7 +631,7 @@ endif
ifeq ($(MEASURED_BOOT),1)
ifneq (${TRUSTED_BOARD_BOOT},1)
$(error MEASURED_BOOT requires TRUSTED_BOARD_BOOT=1")
$(error MEASURED_BOOT requires TRUSTED_BOARD_BOOT=1)
else
$(info MEASURED_BOOT is an experimental feature)
endif
......@@ -635,6 +643,14 @@ ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
endif
endif
ifneq (${DECRYPTION_SUPPORT},none)
ifeq (${TRUSTED_BOARD_BOOT}, 0)
$(error TRUSTED_BOARD_BOOT must be enabled for DECRYPTION_SUPPORT to be set)
else
$(info DECRYPTION_SUPPORT is an experimental feature)
endif
endif
################################################################################
# Process platform overrideable behaviour
################################################################################
......@@ -708,6 +724,10 @@ include lib/stack_protector/stack_protector.mk
CRTTOOLPATH ?= tools/cert_create
CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT}
# Variables for use with Firmware Encryption Tool
ENCTOOLPATH ?= tools/encrypt_fw
ENCTOOL ?= ${ENCTOOLPATH}/encrypt_fw${BIN_EXT}
# Variables for use with Firmware Image Package
FIPTOOLPATH ?= tools/fiptool
FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT}
......@@ -814,10 +834,13 @@ $(eval $(call assert_boolean,BL2_AT_EL3))
$(eval $(call assert_boolean,BL2_IN_XIP_MEM))
$(eval $(call assert_boolean,BL2_INV_DCACHE))
$(eval $(call assert_boolean,USE_SPINLOCK_CAS))
$(eval $(call assert_boolean,ENCRYPT_BL31))
$(eval $(call assert_boolean,ENCRYPT_BL32))
$(eval $(call assert_numeric,ARM_ARCH_MAJOR))
$(eval $(call assert_numeric,ARM_ARCH_MINOR))
$(eval $(call assert_numeric,BRANCH_PROTECTION))
$(eval $(call assert_numeric,FW_ENC_STATUS))
ifdef KEY_SIZE
$(eval $(call assert_numeric,KEY_SIZE))
......@@ -843,6 +866,7 @@ $(eval $(call add_define,CTX_INCLUDE_PAUTH_REGS))
$(eval $(call add_define,EL3_EXCEPTION_HANDLING))
$(eval $(call add_define,CTX_INCLUDE_MTE_REGS))
$(eval $(call add_define,CTX_INCLUDE_EL2_REGS))
$(eval $(call add_define,DECRYPTION_SUPPORT_${DECRYPTION_SUPPORT}))
$(eval $(call add_define,ENABLE_AMU))
$(eval $(call add_define,ENABLE_ASSERTIONS))
$(eval $(call add_define,ENABLE_BTI))
......@@ -854,6 +878,8 @@ $(eval $(call add_define,ENABLE_PSCI_STAT))
$(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION))
$(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS))
$(eval $(call add_define,ENABLE_SVE_FOR_NS))
$(eval $(call add_define,ENCRYPT_BL31))
$(eval $(call add_define,ENCRYPT_BL32))
$(eval $(call add_define,ERROR_DEPRECATED))
$(eval $(call add_define,FAULT_INJECTION_SUPPORT))
$(eval $(call add_define,GICV2_G0_FOR_EL3))
......@@ -926,7 +952,7 @@ endif
# Build targets
################################################################################
.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip sp fwu_fip certtool dtbs memmap doc
.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip sp fwu_fip certtool dtbs memmap doc enctool
.SUFFIXES:
all: msg_start
......@@ -974,9 +1000,14 @@ endif
ifeq (${NEED_BL31},yes)
BL31_SOURCES += ${SPD_SOURCES}
ifneq (${DECRYPTION_SUPPORT},none)
$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw,,$(ENCRYPT_BL31))),\
$(eval $(call MAKE_BL,31,soc-fw,,$(ENCRYPT_BL31))))
else
$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw)),\
$(eval $(call MAKE_BL,31,soc-fw)))
endif
endif
# If a BL32 image is needed but neither BL32 nor BL32_SOURCES is defined, the
# build system will call TOOL_ADD_IMG to print a warning message and abort the
......@@ -985,9 +1016,14 @@ ifeq (${NEED_BL32},yes)
BUILD_BL32 := $(if $(BL32),,$(if $(BL32_SOURCES),1))
ifneq (${DECRYPTION_SUPPORT},none)
$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw,,$(ENCRYPT_BL32))),\
$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw,,$(ENCRYPT_BL32))))
else
$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw)),\
$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw)))
endif
endif
# Add the BL33 image if required by the platform
ifeq (${NEED_BL33},yes)
......@@ -1029,6 +1065,7 @@ clean:
$(call SHELL_REMOVE_DIR,${BUILD_PLAT})
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} clean
${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean
realclean distclean:
......@@ -1038,6 +1075,7 @@ realclean distclean:
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
${Q}${MAKE} --no-print-directory -C ${SPTOOLPATH} clean
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} realclean
${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean
checkcodebase: locate-checkpatch
......@@ -1139,6 +1177,15 @@ doc:
@echo " BUILD DOCUMENTATION"
${Q}${MAKE} --no-print-directory -C ${DOCS_PATH} html
enctool: ${ENCTOOL}
.PHONY: ${ENCTOOL}
${ENCTOOL}:
${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 --no-print-directory -C ${ENCTOOLPATH}
@${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
@${ECHO_BLANK_LINE}
cscope:
@echo " CSCOPE"
${Q}find ${CURDIR} -name "*.[chsS]" > cscope.files
......@@ -1175,6 +1222,7 @@ help:
@echo " cscope Generate cscope index"
@echo " distclean Remove all build artifacts for all platforms"
@echo " certtool Build the Certificate generation tool"
@echo " enctool Build the Firmware encryption tool"
@echo " fiptool Build the Firmware Image Package (FIP) creation tool"
@echo " sp Build the Secure Partition Packages"
@echo " sptool Build the Secure Partition Package creation tool"
......
......@@ -46,6 +46,7 @@ New Features
- Security
- Example: "UBSAN support and handlers"
- Add support for optional firmware encryption feature (experimental).
- Tools
- Example: "fiptool: Add support to build fiptool on Windows."
......
......@@ -934,7 +934,7 @@ i.e. verify a hash or a digital signature. Arm platforms will use a library
based on mbed TLS, 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:
four functions:
.. code:: c
......@@ -945,6 +945,11 @@ three functions:
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);
int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
unsigned int key_flags, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len)
The mbedTLS library algorithm support is configured by both the
``TF_MBEDTLS_KEY_ALG`` and ``TF_MBEDTLS_KEY_SIZE`` variables.
......@@ -957,6 +962,9 @@ The mbedTLS library algorithm support is configured by both the
- ``TF_MBEDTLS_KEY_SIZE`` sets the supported RSA key size for TFA. Valid values
include 1024, 2048, 3072 and 4096.
- ``TF_MBEDTLS_USE_AES_GCM`` enables the authenticated decryption support based
on AES-GCM algorithm. Valid values are 0 and 1.
.. note::
If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can
be defined in the platform Makefile. It will make mbed TLS use an
......
......@@ -229,6 +229,34 @@ library that is required is given in the :ref:`Prerequisites` document.
Instructions for building and using the tool can be found at
:ref:`tools_build_cert_create`.
Authenticated Encryption Framework
----------------------------------
The authenticated encryption framework included in TF-A provides support to
implement the optional firmware encryption feature. This feature can be
optionally enabled on platforms to implement the optional requirement:
R060_TBBR_FUNCTION as specified in the `Trusted Board Boot Requirements (TBBR)`_
document.
Note that due to security considerations and complexity of this feature, it is
marked as experimental.
Firmware Encryption Tool
------------------------
The ``encrypt_fw`` tool is built and runs on the host machine as part of the
TF-A build process when ``DECRYPTION_SUPPORT != none``. It takes the plain
firmware image as input and generates the encrypted firmware image which can
then be passed as input to the ``fiptool`` utility for creating the FIP.
The encrypted firmwares are also stored individually in the output build
directory.
The tool resides in the ``tools/encrypt_fw`` directory. It uses OpenSSL SSL
library version 1.0.1 or later to do authenticated encryption operation.
Instructions for building and using the tool can be found in the
:ref:`tools_build_enctool`.
--------------
*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.*
......
......@@ -160,6 +160,12 @@ Common build options
- ``DEBUG``: Chooses between a debug and release build. It can take either 0
(release) or 1 (debug) as values. 0 is the default.
- ``DECRYPTION_SUPPORT``: This build flag enables the user to select the
authenticated decryption algorithm to be used to decrypt firmware/s during
boot. It accepts 2 values: ``aes_gcm`` and ``none``. The default value of
this flag is ``none`` to disable firmware decryption which is an optional
feature as per TBBR. Also, it is an experimental feature.
- ``DISABLE_BIN_GENERATION``: Boolean option to disable the generation
of the binary image. If set to 1, then only the ELF image is built.
0 is the default.
......@@ -257,6 +263,22 @@ Common build options
platform hook needs to be implemented. The value is passed as the last
component of the option ``-fstack-protector-$ENABLE_STACK_PROTECTOR``.
- ``ENCRYPT_BL31``: Binary flag to enable encryption of BL31 firmware. This
flag depends on ``DECRYPTION_SUPPORT`` build flag which is marked as
experimental.
- ``ENCRYPT_BL32``: Binary flag to enable encryption of Secure BL32 payload.
This flag depends on ``DECRYPTION_SUPPORT`` build flag which is marked as
experimental.
- ``ENC_KEY``: A 32-byte (256-bit) symmetric key in hex string format. It could
either be SSK or BSSK depending on ``FW_ENC_STATUS`` flag. This value depends
on ``DECRYPTION_SUPPORT`` build flag which is marked as experimental.
- ``ENC_NONCE``: A 12-byte (96-bit) encryption nonce or Initialization Vector
(IV) in hex string format. This value depends on ``DECRYPTION_SUPPORT``
build flag which is marked as experimental.
- ``ERROR_DEPRECATED``: This option decides whether to treat the usage of
deprecated platform APIs, helper functions or drivers within Trusted
Firmware as error. It can take the value 1 (flag the use of deprecated
......@@ -281,6 +303,18 @@ Common build options
- ``FWU_FIP_NAME``: This is an optional build option which specifies the FWU
FIP filename for the ``fwu_fip`` target. Default is ``fwu_fip.bin``.
- ``FW_ENC_STATUS``: Top level firmware's encryption numeric flag, values:
::
0: Encryption is done with Secret Symmetric Key (SSK) which is common
for a class of devices.
1: Encryption is done with Binding Secret Symmetric Key (BSSK) which is
unique per device.
This flag depends on ``DECRYPTION_SUPPORT`` build flag which is marked as
experimental.
- ``GENERATE_COT``: Boolean flag used to build and execute the ``cert_create``
tool to create certificates as per the Chain of Trust described in
:ref:`Trusted Board Boot`. The build system then calls ``fiptool`` to
......
......@@ -872,6 +872,35 @@ twice.
On success the function should return 0 and a negative error code otherwise.
Function : plat_get_enc_key_info() [when FW_ENC_STATUS == 0 or 1]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
Arguments : enum fw_enc_status_t fw_enc_status, uint8_t *key,
size_t *key_len, unsigned int *flags, const uint8_t *img_id,
size_t img_id_len
Return : int
This function provides a symmetric key (either SSK or BSSK depending on
fw_enc_status) which is invoked during runtime decryption of encrypted
firmware images. `plat/common/plat_bl_common.c` provides a dummy weak
implementation for testing purposes which must be overridden by the platform
trying to implement a real world firmware encryption use-case.
It also allows the platform to pass symmetric key identifier rather than
actual symmetric key which is useful in cases where the crypto backend provides
secure storage for the symmetric key. So in this case ``ENC_KEY_IS_IDENTIFIER``
flag must be set in ``flags``.
In addition to above a platform may also choose to provide an image specific
symmetric key/identifier using img_id.
On success the function should return 0 and a negative error code otherwise.
Note that this API depends on ``DECRYPTION_SUPPORT`` build flag which is
marked as experimental.
Common optional modifications
-----------------------------
......
......@@ -135,6 +135,33 @@ verbose. The following command should be used to obtain help about the tool:
./tools/cert_create/cert_create -h
.. _tools_build_enctool:
Building the Firmware Encryption Tool
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``encrypt_fw`` tool is built as part of the TF-A build process when the
``fip`` make target is specified, DECRYPTION_SUPPORT and TBB are enabled, but
it can also be built separately with the following command:
.. code:: shell
make PLAT=<platform> [DEBUG=1] [V=1] enctool
``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more
verbose. The following command should be used to obtain help about the tool:
.. code:: shell
./tools/encrypt_fw/encrypt_fw -h
Note that the enctool in its current implementation only supports encryption
key to be provided in plain format. A typical implementation can very well
extend this tool to support custom techniques to protect encryption key.
Also, a user may choose to provide encryption key or nonce as an input file
via using ``cat <filename>`` instead of a hex string.
--------------
*Copyright (c) 2019, Arm Limited. All rights reserved.*
......@@ -21,11 +21,13 @@ Current limitations:
- Only cold boot is supported
- No build instructions for QEMU\_EFI.fd and rootfs-arm64.cpio.gz
- No instructions for how to load a BL32 (Secure Payload)
``QEMU_EFI.fd`` can be dowloaded from
http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC5/QEMU_EFI.fd
Booting via semi-hosting option
-------------------------------
Boot binaries, except BL1, are primarily loaded via semi-hosting so all
binaries has to reside in the same directory as QEMU is started from. This
is conveniently achieved with symlinks the local names as:
......@@ -50,3 +52,52 @@ To start (QEMU v4.1.0):
-append "console=ttyAMA0,38400 keep_bootcon root=/dev/vda2" \
-initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios bl1.bin \
-d unimp -semihosting-config enable,target=native
Booting via flash based firmwares
---------------------------------
Boot firmwares are loaded via secure FLASH0 device so ``bl1.bin`` and
``fip.bin`` should be concatenated to create a ``flash.bin`` that is flashed
onto secure FLASH0.
- ``bl32.bin`` -> BL32 (``tee-header_v2.bin``)
- ``bl32_extra1.bin`` -> BL32 Extra1 (``tee-pager_v2.bin``)
- ``bl32_extra2.bin`` -> BL32 Extra2 (``tee-pageable_v2.bin``)
- ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``)
- ``Image`` -> linux/arch/arm64/boot/Image
To build:
.. code:: shell
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \
BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \
BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip
To build with TBBR enabled, BL31 and BL32 encrypted with test key:
.. code:: shell
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \
BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \
BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip \
MBEDTLS_DIR=<path-to-mbedtls-repo> TRUSTED_BOARD_BOOT=1 \
GENERATE_COT=1 DECRYPTION_SUPPORT=aes_gcm FW_ENC_STATUS=0 \
ENCRYPT_BL31=1 ENCRYPT_BL32=1
To build flash.bin:
.. code:: shell
dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc
dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc
To start (QEMU v2.6.0):
.. code:: shell
qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \
-kernel Image -no-acpi \
-append 'console=ttyAMA0,38400 keep_bootcon root=/dev/vda2' \
-initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios flash.bin \
-d unimp
......@@ -124,3 +124,35 @@ int crypto_mod_calc_hash(unsigned int alg, void *data_ptr,
return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output);
}
#endif /* MEASURED_BOOT */
/*
* Authenticated decryption of data
*
* Parameters:
*
* dec_algo: authenticated decryption algorithm
* data_ptr, len: data to be decrypted (inout param)
* key, key_len, key_flags: symmetric decryption key
* iv, iv_len: initialization vector
* tag, tag_len: authentication tag
*/
int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
unsigned int key_flags, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len)
{
assert(crypto_lib_desc.auth_decrypt != NULL);
assert(data_ptr != NULL);
assert(len != 0U);
assert(key != NULL);
assert(key_len != 0U);
assert(iv != NULL);
assert((iv_len != 0U) && (iv_len <= CRYPTO_MAX_IV_SIZE));
assert(tag != NULL);
assert((tag_len != 0U) && (tag_len <= CRYPTO_MAX_TAG_SIZE));
return crypto_lib_desc.auth_decrypt(dec_algo, data_ptr, len, key,
key_len, key_flags, iv, iv_len, tag,
tag_len);
}
......@@ -301,5 +301,5 @@ static int verify_hash(void *data_ptr, unsigned int data_len,
/*
* Register crypto library descriptor
*/
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
......@@ -23,13 +23,17 @@ MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_common.c
LIBMBEDTLS_SRCS := $(addprefix ${MBEDTLS_DIR}/library/, \
aes.c \
asn1parse.c \
asn1write.c \
cipher.c \
cipher_wrap.c \
memory_buffer_alloc.c \
oid.c \
platform.c \
platform_util.c \
bignum.c \
gcm.c \
md.c \
md_wrap.c \
pk.c \
......@@ -87,11 +91,17 @@ else
$(error "TF_MBEDTLS_KEY_ALG=${TF_MBEDTLS_KEY_ALG} not supported on mbed TLS")
endif
ifeq (${DECRYPTION_SUPPORT}, aes_gcm)
TF_MBEDTLS_USE_AES_GCM := 1
else
TF_MBEDTLS_USE_AES_GCM := 0
endif
# Needs to be set to drive mbed TLS configuration correctly
$(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID))
$(eval $(call add_define,TF_MBEDTLS_KEY_SIZE))
$(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID))
$(eval $(call add_define,TF_MBEDTLS_USE_AES_GCM))
$(eval $(call MAKE_LIB,mbedtls))
......
......@@ -4,10 +4,12 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
/* mbed TLS headers */
#include <mbedtls/gcm.h>
#include <mbedtls/md.h>
#include <mbedtls/memory_buffer_alloc.h>
#include <mbedtls/oid.h>
......@@ -17,6 +19,7 @@
#include <drivers/auth/crypto_mod.h>
#include <drivers/auth/mbedtls/mbedtls_common.h>
#include <drivers/auth/mbedtls/mbedtls_config.h>
#include <plat/common/platform.h>
#define LIB_NAME "mbed TLS"
......@@ -226,11 +229,121 @@ int calc_hash(unsigned int alg, void *data_ptr,
}
#endif /* MEASURED_BOOT */
#if TF_MBEDTLS_USE_AES_GCM
/*
* Stack based buffer allocation for decryption operation. It could
* be configured to balance stack usage vs execution speed.
*/
#define DEC_OP_BUF_SIZE 128
static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key,
unsigned int key_len, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len)
{
mbedtls_gcm_context ctx;
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
unsigned char buf[DEC_OP_BUF_SIZE];
unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
unsigned char *pt = data_ptr;
size_t dec_len;
int diff, i, rc;
mbedtls_gcm_init(&ctx);
rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8);
if (rc != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0);
if (rc != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
while (len > 0) {
dec_len = MIN(sizeof(buf), len);
rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf);
if (rc != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
memcpy(pt, buf, dec_len);
pt += dec_len;
len -= dec_len;
}
rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf));
if (rc != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
/* Check tag in "constant-time" */
for (diff = 0, i = 0; i < tag_len; i++)
diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
if (diff != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
/* GCM decryption success */
rc = CRYPTO_SUCCESS;
exit_gcm:
mbedtls_gcm_free(&ctx);
return rc;
}
/*
* Authenticated decryption of an image
*/
static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
unsigned int key_flags, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len)
{
int rc;
assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
switch (dec_algo) {
case CRYPTO_GCM_DECRYPT:
rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
tag, tag_len);
if (rc != 0)
return rc;
break;
default:
return CRYPTO_ERR_DECRYPTION;
}
return CRYPTO_SUCCESS;
}
#endif /* TF_MBEDTLS_USE_AES_GCM */
/*
* Register crypto library descriptor
*/
#if MEASURED_BOOT
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash);
#if TF_MBEDTLS_USE_AES_GCM
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
auth_decrypt);
#else
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
NULL);
#endif
#else /* MEASURED_BOOT */
#if TF_MBEDTLS_USE_AES_GCM
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash,
auth_decrypt);
#else
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
#endif
#endif /* MEASURED_BOOT */
/*
* Copyright (c) 2020, Linaro Limited. All rights reserved.
* Author: Sumit Garg <sumit.garg@linaro.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <platform_def.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>
#include <drivers/io/io_driver.h>
#include <drivers/io/io_encrypted.h>
#include <drivers/io/io_storage.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
#include <tools_share/firmware_encrypted.h>
#include <tools_share/uuid.h>
static uintptr_t backend_dev_handle;
static uintptr_t backend_dev_spec;
static uintptr_t backend_handle;
static uintptr_t backend_image_spec;
static io_dev_info_t enc_dev_info;
/* Encrypted firmware driver functions */
static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity);
static int enc_file_len(io_entity_t *entity, size_t *length);
static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
size_t *length_read);
static int enc_file_close(io_entity_t *entity);
static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
static int enc_dev_close(io_dev_info_t *dev_info);
static inline int is_valid_header(struct fw_enc_hdr *header)
{
if (header->magic == ENC_HEADER_MAGIC)
return 1;
else
return 0;
}
static io_type_t device_type_enc(void)
{
return IO_TYPE_ENCRYPTED;
}
static const io_dev_connector_t enc_dev_connector = {
.dev_open = enc_dev_open
};
static const io_dev_funcs_t enc_dev_funcs = {
.type = device_type_enc,
.open = enc_file_open,
.seek = NULL,
.size = enc_file_len,
.read = enc_file_read,
.write = NULL,
.close = enc_file_close,
.dev_init = enc_dev_init,
.dev_close = enc_dev_close,
};
static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info)
{
assert(dev_info != NULL);
enc_dev_info.funcs = &enc_dev_funcs;
*dev_info = &enc_dev_info;
return 0;
}
static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
{
int result;
unsigned int image_id = (unsigned int)init_params;
/* Obtain a reference to the image by querying the platform layer */
result = plat_get_image_source(image_id, &backend_dev_handle,
&backend_dev_spec);
if (result != 0) {
WARN("Failed to obtain reference to image id=%u (%i)\n",
image_id, result);
return -ENOENT;
}
return result;
}
static int enc_dev_close(io_dev_info_t *dev_info)
{
backend_dev_handle = (uintptr_t)NULL;
backend_dev_spec = (uintptr_t)NULL;
return 0;
}
static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity)
{
int result;
assert(spec != 0);
assert(entity != NULL);
backend_image_spec = spec;
result = io_open(backend_dev_handle, backend_image_spec,
&backend_handle);
if (result != 0) {
WARN("Failed to open backend device (%i)\n", result);
result = -ENOENT;
}
return result;
}
static int enc_file_len(io_entity_t *entity, size_t *length)
{
int result;
assert(entity != NULL);
assert(length != NULL);
result = io_size(backend_handle, length);
if (result != 0) {
WARN("Failed to read blob length (%i)\n", result);
return -ENOENT;
}
/*
* Encryption header is attached at the beginning of the encrypted file
* and is not considered a part of the payload.
*/
if (*length < sizeof(struct fw_enc_hdr))
return -EIO;
*length -= sizeof(struct fw_enc_hdr);
return result;
}
static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
size_t *length_read)
{
int result;
struct fw_enc_hdr header;
enum fw_enc_status_t fw_enc_status;
size_t bytes_read;
uint8_t key[ENC_MAX_KEY_SIZE];
size_t key_len = sizeof(key);
unsigned int key_flags = 0;
const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)backend_image_spec;
assert(entity != NULL);
assert(length_read != NULL);
result = io_read(backend_handle, (uintptr_t)&header, sizeof(header),
&bytes_read);
if (result != 0) {
WARN("Failed to read encryption header (%i)\n", result);
return -ENOENT;
}
if (!is_valid_header(&header)) {
WARN("Encryption header check failed.\n");
return -ENOENT;
}
VERBOSE("Encryption header looks OK.\n");
fw_enc_status = header.flags & FW_ENC_STATUS_FLAG_MASK;
if ((header.iv_len > ENC_MAX_IV_SIZE) ||
(header.tag_len > ENC_MAX_TAG_SIZE)) {
WARN("Incorrect IV or tag length\n");
return -ENOENT;
}
result = io_read(backend_handle, buffer, length, &bytes_read);
if (result != 0) {
WARN("Failed to read encrypted payload (%i)\n", result);
return -ENOENT;
}
*length_read = bytes_read;
result = plat_get_enc_key_info(fw_enc_status, key, &key_len, &key_flags,
(uint8_t *)&uuid_spec->uuid,
sizeof(uuid_t));
if (result != 0) {
WARN("Failed to obtain encryption key (%i)\n", result);
return -ENOENT;
}
result = crypto_mod_auth_decrypt(header.dec_algo,
(void *)buffer, *length_read, key,
key_len, key_flags, header.iv,
header.iv_len, header.tag,
header.tag_len);
memset(key, 0, key_len);
if (result != 0) {
ERROR("File decryption failed (%i)\n", result);
return -ENOENT;
}
return result;
}
static int enc_file_close(io_entity_t *entity)
{
io_close(backend_handle);
backend_image_spec = (uintptr_t)NULL;
entity->info = 0;
return 0;
}
/* Exported functions */
/* Register the Encrypted Firmware driver with the IO abstraction */
int register_io_dev_enc(const io_dev_connector_t **dev_con)
{
int result;
assert(dev_con != NULL);
result = io_register_device(&enc_dev_info);
if (result == 0)
*dev_con = &enc_dev_connector;
return result;
}
......@@ -13,9 +13,18 @@ enum crypto_ret_value {
CRYPTO_ERR_INIT,
CRYPTO_ERR_HASH,
CRYPTO_ERR_SIGNATURE,
CRYPTO_ERR_DECRYPTION,
CRYPTO_ERR_UNKNOWN
};
#define CRYPTO_MAX_IV_SIZE 16U
#define CRYPTO_MAX_TAG_SIZE 16U
/* Decryption algorithm */
enum crypto_dec_algo {
CRYPTO_GCM_DECRYPT = 0
};
/*
* Cryptographic library descriptor
*/
......@@ -44,6 +53,15 @@ typedef struct crypto_lib_desc_s {
unsigned int data_len, unsigned char *output);
#endif /* MEASURED_BOOT */
/*
* Authenticated decryption. Return one of the
* 'enum crypto_ret_value' options.
*/
int (*auth_decrypt)(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
unsigned int key_flags, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len);
} crypto_lib_desc_t;
/* Public functions */
......@@ -54,6 +72,11 @@ int crypto_mod_verify_signature(void *data_ptr, unsigned int data_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);
int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
unsigned int key_flags, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len);
#if MEASURED_BOOT
int crypto_mod_calc_hash(unsigned int alg, void *data_ptr,
......@@ -61,21 +84,24 @@ int crypto_mod_calc_hash(unsigned int alg, void *data_ptr,
/* Macro to register a cryptographic library */
#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
_calc_hash) \
_calc_hash, _auth_decrypt) \
const crypto_lib_desc_t crypto_lib_desc = { \
.name = _name, \
.init = _init, \
.verify_signature = _verify_signature, \
.verify_hash = _verify_hash, \
.calc_hash = _calc_hash \
.calc_hash = _calc_hash, \
.auth_decrypt = _auth_decrypt \
}
#else
#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash) \
#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
_auth_decrypt) \
const crypto_lib_desc_t crypto_lib_desc = { \
.name = _name, \
.init = _init, \
.verify_signature = _verify_signature, \
.verify_hash = _verify_hash \
.verify_hash = _verify_hash, \
.auth_decrypt = _auth_decrypt \
}
#endif /* MEASURED_BOOT */
......
......@@ -79,6 +79,12 @@
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#if TF_MBEDTLS_USE_AES_GCM
#define MBEDTLS_AES_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_GCM_C
#endif
/* MPI / BIGNUM options */
#define MBEDTLS_MPI_WINDOW_SIZE 2
......
/*
* Copyright (c) 2020, Linaro Limited. All rights reserved.
* Author: Sumit Garg <sumit.garg@linaro.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IO_ENCRYPTED_H
#define IO_ENCRYPTED_H
struct io_dev_connector;
int register_io_dev_enc(const struct io_dev_connector **dev_con);
#endif /* IO_ENCRYPTED_H */
......@@ -25,6 +25,7 @@ typedef enum {
IO_TYPE_MTD,
IO_TYPE_MMC,
IO_TYPE_STM32IMAGE,
IO_TYPE_ENCRYPTED,
IO_TYPE_MAX
} io_type_t;
......
......@@ -85,12 +85,15 @@
/* Binary with STM32 header */
#define STM32_IMAGE_ID U(29)
/* Encrypted image identifier */
#define ENC_IMAGE_ID U(30)
/* Define size of the array */
#if defined(SPD_spmd)
#define MAX_SP_IDS U(8)
#define MAX_NUMBER_IDS MAX_SP_IDS + U(30)
#define MAX_NUMBER_IDS MAX_SP_IDS + U(31)
#else
#define MAX_NUMBER_IDS U(30)
#define MAX_NUMBER_IDS U(31)
#endif
#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */
......@@ -27,6 +27,7 @@ struct bl_params;
struct mmap_region;
struct spm_mm_boot_info;
struct sp_res_desc;
enum fw_enc_status_t;
/*******************************************************************************
* plat_get_rotpk_info() flags
......@@ -36,6 +37,15 @@ struct sp_res_desc;
ROTPK is not deployed */
#define ROTPK_NOT_DEPLOYED (1 << 1)
/*******************************************************************************
* plat_get_enc_key_info() flags
******************************************************************************/
/*
* Flag used to notify caller that information provided in key buffer is an
* identifier rather than an actual key.
*/
#define ENC_KEY_IS_IDENTIFIER (1 << 0)
/*******************************************************************************
* Function declarations
******************************************************************************/
......@@ -265,6 +275,9 @@ int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr);
int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc,
unsigned int nv_ctr);
int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size);
int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
size_t *key_len, unsigned int *flags,
const uint8_t *img_id, size_t img_id_len);
/*******************************************************************************
* Secure Partitions functions
......
/*
* Copyright (c) 2020, Linaro Limited. All rights reserved.
* Author: Sumit Garg <sumit.garg@linaro.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FIRMWARE_ENCRYPTED_H
#define FIRMWARE_ENCRYPTED_H
#include <stdint.h>
/* This is used as a signature to validate the encryption header */
#define ENC_HEADER_MAGIC 0xAA640001U
/* Firmware encryption status flag mask */
#define FW_ENC_STATUS_FLAG_MASK 0x1
/*
* SSK: Secret Symmetric Key
* BSSK: Binding Secret Symmetric Key
*/
enum fw_enc_status_t {
FW_ENC_WITH_SSK = 0,
FW_ENC_WITH_BSSK = 1,
};
#define ENC_MAX_IV_SIZE 16U
#define ENC_MAX_TAG_SIZE 16U
#define ENC_MAX_KEY_SIZE 32U
struct fw_enc_hdr {
uint32_t magic;
uint16_t dec_algo;
uint16_t flags;
uint16_t iv_len;
uint16_t tag_len;
uint8_t iv[ENC_MAX_IV_SIZE];
uint8_t tag[ENC_MAX_TAG_SIZE];
};
#endif /* FIRMWARE_ENCRYPTED_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