Browse Source

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
pull/1938/head
Sandrine Bailleux 5 years ago
committed by TrustedFirmware Code Review
parent
commit
091576e7f1
  1. 52
      Makefile
  2. 1
      docs/change-log-upcoming.rst
  3. 10
      docs/design/auth-framework.rst
  4. 28
      docs/design/trusted-board-boot.rst
  5. 34
      docs/getting_started/build-options.rst
  6. 29
      docs/getting_started/porting-guide.rst
  7. 27
      docs/getting_started/tools-build.rst
  8. 53
      docs/plat/qemu.rst
  9. 32
      drivers/auth/crypto_mod.c
  10. 2
      drivers/auth/cryptocell/712/cryptocell_crypto.c
  11. 12
      drivers/auth/mbedtls/mbedtls_common.mk
  12. 117
      drivers/auth/mbedtls/mbedtls_crypto.c
  13. 244
      drivers/io/io_encrypted.c
  14. 34
      include/drivers/auth/crypto_mod.h
  15. 6
      include/drivers/auth/mbedtls/mbedtls_config.h
  16. 15
      include/drivers/io/io_encrypted.h
  17. 1
      include/drivers/io/io_storage.h
  18. 7
      include/export/common/tbbr/tbbr_img_def_exp.h
  19. 13
      include/plat/common/platform.h
  20. 42
      include/tools_share/firmware_encrypted.h
  21. 45
      make_helpers/build_macros.mk
  22. 18
      make_helpers/defaults.mk
  23. 27
      plat/common/plat_bl_common.c
  24. 71
      plat/qemu/common/qemu_io_storage.c
  25. 6
      plat/qemu/qemu/include/platform_def.h
  26. 13
      plat/qemu/qemu/platform.mk
  27. 65
      tools/encrypt_fw/Makefile
  28. 32
      tools/encrypt_fw/include/cmd_opt.h
  29. 59
      tools/encrypt_fw/include/debug.h
  30. 19
      tools/encrypt_fw/include/encrypt.h
  31. 59
      tools/encrypt_fw/src/cmd_opt.c
  32. 167
      tools/encrypt_fw/src/encrypt.c
  33. 224
      tools/encrypt_fw/src/main.c

52
Makefile

@ -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"

1
docs/change-log-upcoming.rst

@ -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."

10
docs/design/auth-framework.rst

@ -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

28
docs/design/trusted-board-boot.rst

@ -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.*

34
docs/getting_started/build-options.rst

@ -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

29
docs/getting_started/porting-guide.rst

@ -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
-----------------------------

27
docs/getting_started/tools-build.rst

@ -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.*

53
docs/plat/qemu.rst

@ -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

32
drivers/auth/crypto_mod.c

@ -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);
}

2
drivers/auth/cryptocell/712/cryptocell_crypto.c

@ -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);

12
drivers/auth/mbedtls/mbedtls_common.mk

@ -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))

117
drivers/auth/mbedtls/mbedtls_crypto.c

@ -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 */

244
drivers/io/io_encrypted.c

@ -0,0 +1,244 @@
/*
* 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;
}

34
include/drivers/auth/crypto_mod.h

@ -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 */

6
include/drivers/auth/mbedtls/mbedtls_config.h

@ -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

15
include/drivers/io/io_encrypted.h

@ -0,0 +1,15 @@
/*
* 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 */

1
include/drivers/io/io_storage.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;

7
include/export/common/tbbr/tbbr_img_def_exp.h

@ -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 */

13
include/plat/common/platform.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

42
include/tools_share/firmware_encrypted.h

@ -0,0 +1,42 @@
/*
* 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 */

45
make_helpers/build_macros.mk

@ -109,6 +109,22 @@ define IMG_BIN
${BUILD_PLAT}/bl$(1).bin
endef
# IMG_ENC_BIN defines the default encrypted image file corresponding to a
# BL stage
# $(1) = BL stage (2, 30, 31, 32, 33)
define IMG_ENC_BIN
${BUILD_PLAT}/bl$(1)_enc.bin
endef
# ENCRYPT_FW invokes enctool to encrypt firmware binary
# $(1) = input firmware binary
# $(2) = output encrypted firmware binary
define ENCRYPT_FW
$(2): $(1) enctool
$$(ECHO) " ENC $$<"
$$(Q)$$(ENCTOOL) $$(ENC_ARGS) -i $$< -o $$@
endef
# TOOL_ADD_PAYLOAD appends the command line arguments required by fiptool to
# package a new payload and/or by cert_create to generate certificate.
# Optionally, it adds the dependency on this payload
@ -116,11 +132,17 @@ endef
# $(2) = command line option for the specified payload (i.e. --soc-fw)
# $(3) = tool target dependency (optional) (ex. build/fvp/release/bl31.bin)
# $(4) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
# $(5) = encrypted payload (optional) (ex. build/fvp/release/bl31_enc.bin)
define TOOL_ADD_PAYLOAD
ifneq ($(5),)
$(4)FIP_ARGS += $(2) $(5)
$(if $(3),$(4)CRT_DEPS += $(1))
else
$(4)FIP_ARGS += $(2) $(1)
$(if $(3),$(4)CRT_DEPS += $(3))
endif
$(if $(3),$(4)FIP_DEPS += $(3))
$(4)CRT_ARGS += $(2) $(1)
$(if $(3),$(4)CRT_DEPS += $(3))
endef
# TOOL_ADD_IMG_PAYLOAD works like TOOL_ADD_PAYLOAD, but applies image filters
@ -130,6 +152,7 @@ endef
# $(3) = command line option for the specified payload (ex. --soc-fw)
# $(4) = tool target dependency (optional) (ex. build/fvp/release/bl31.bin)
# $(5) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
# $(6) = encrypted payload (optional) (ex. build/fvp/release/bl31_enc.bin)
define TOOL_ADD_IMG_PAYLOAD
@ -143,10 +166,10 @@ $(call $(PRE_TOOL_FILTER)_RULE,$(PROCESSED_PATH),$(2))
$(PROCESSED_PATH): $(4)
$(call TOOL_ADD_PAYLOAD,$(PROCESSED_PATH),$(3),$(PROCESSED_PATH),$(5))
$(call TOOL_ADD_PAYLOAD,$(PROCESSED_PATH),$(3),$(PROCESSED_PATH),$(5),$(6))
else
$(call TOOL_ADD_PAYLOAD,$(2),$(3),$(4),$(5))
$(call TOOL_ADD_PAYLOAD,$(2),$(3),$(4),$(5),$(6))
endif
endef
@ -164,6 +187,7 @@ endef
# $(1) = image_type (scp_bl2, bl33, etc.)
# $(2) = command line option for fiptool (--scp-fw, --nt-fw, etc)
# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
# $(4) = Image encryption flag (optional) (0, 1)
# Example:
# $(eval $(call TOOL_ADD_IMG,bl33,--nt-fw))
define TOOL_ADD_IMG
@ -173,7 +197,14 @@ define TOOL_ADD_IMG
$(3)CRT_DEPS += check_$(1)
$(3)FIP_DEPS += check_$(1)
ifeq ($(4),1)
$(eval ENC_BIN := ${BUILD_PLAT}/$(1)_enc.bin)
$(call ENCRYPT_FW,$(value $(_V)),$(ENC_BIN))
$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(value $(_V)),$(2),$(ENC_BIN),$(3), \
$(ENC_BIN))
else
$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(value $(_V)),$(2),,$(3))
endif
.PHONY: check_$(1)
check_$(1):
@ -390,6 +421,7 @@ endef
# $(1) = BL stage (1, 2, 2u, 31, 32)
# $(2) = FIP command line option (if empty, image will not be included in the FIP)
# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
# $(4) = BL encryption flag (optional) (0, 1)
define MAKE_BL
$(eval BUILD_DIR := ${BUILD_PLAT}/bl$(1))
$(eval BL_SOURCES := $(BL$(call uppercase,$(1))_SOURCES))
@ -400,6 +432,7 @@ define MAKE_BL
$(eval ELF := $(call IMG_ELF,$(1)))
$(eval DUMP := $(call IMG_DUMP,$(1)))
$(eval BIN := $(call IMG_BIN,$(1)))
$(eval ENC_BIN := $(call IMG_ENC_BIN,$(1)))
$(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE))
$(eval BL_LIBS := $(BL$(call uppercase,$(1))_LIBS))
# We use sort only to get a list of unique object directory names.
@ -480,7 +513,13 @@ endif
all: bl$(1)
ifeq ($(4),1)
$(call ENCRYPT_FW,$(BIN),$(ENC_BIN))
$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \
$(ENC_BIN)))
else
$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(BIN),$(3)))
endif
endef

18
make_helpers/defaults.mk

@ -65,6 +65,9 @@ CTX_INCLUDE_PAUTH_REGS := 0
# Debug build
DEBUG := 0
# By default disable authenticated decryption support.
DECRYPTION_SUPPORT := none
# Build platform
DEFAULT_PLAT := fvp
@ -106,6 +109,18 @@ ENABLE_BTI := 0
# Use BRANCH_PROTECTION to enable PAUTH.
ENABLE_PAUTH := 0
# By default BL31 encryption disabled
ENCRYPT_BL31 := 0
# By default BL32 encryption disabled
ENCRYPT_BL32 := 0
# Default dummy firmware encryption key
ENC_KEY := 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
# Default dummy nonce for firmware encryption
ENC_NONCE := 1234567890abcdef12345678
# Build flag to treat usage of deprecated platform and framework APIs as error.
ERROR_DEPRECATED := 0
@ -121,6 +136,9 @@ FIP_NAME := fip.bin
# Default FWU_FIP file name
FWU_FIP_NAME := fwu_fip.bin
# By default firmware encryption with SSK
FW_ENC_STATUS := 0
# For Chain of Trust
GENERATE_COT := 0

27
plat/common/plat_bl_common.c

@ -11,6 +11,7 @@
#include <common/debug.h>
#include <lib/xlat_tables/xlat_tables_compat.h>
#include <plat/common/platform.h>
#include <tools_share/firmware_encrypted.h>
/*
* The following platform functions are weakly defined. The Platforms
@ -22,6 +23,7 @@
#pragma weak bl2_plat_handle_pre_image_load
#pragma weak bl2_plat_handle_post_image_load
#pragma weak plat_try_next_boot_source
#pragma weak plat_get_enc_key_info
void bl2_el3_plat_prepare_exit(void)
{
@ -52,6 +54,31 @@ int plat_try_next_boot_source(void)
return 0;
}
/*
* Weak implementation to provide dummy decryption key only for test purposes,
* platforms must override this API for any real world firmware encryption
* use-case.
*/
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)
{
#define DUMMY_FIP_ENC_KEY { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }
const uint8_t dummy_key[] = DUMMY_FIP_ENC_KEY;
assert(*key_len >= sizeof(dummy_key));
*key_len = sizeof(dummy_key);
memcpy(key, dummy_key, *key_len);
*flags = 0;
return 0;
}
/*
* Set up the page tables for the generic and platform-specific memory regions.
* The size of the Trusted SRAM seen by the BL image must be specified as well

71
plat/qemu/common/qemu_io_storage.c

@ -12,6 +12,7 @@
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/io/io_driver.h>
#include <drivers/io/io_encrypted.h>
#include <drivers/io/io_fip.h>
#include <drivers/io/io_memmap.h>
#include <drivers/io/io_semihosting.h>
@ -47,6 +48,10 @@ static const io_dev_connector_t *memmap_dev_con;
static uintptr_t memmap_dev_handle;
static const io_dev_connector_t *sh_dev_con;
static uintptr_t sh_dev_handle;
#ifndef DECRYPTION_SUPPORT_none
static const io_dev_connector_t *enc_dev_con;
static uintptr_t enc_dev_handle;
#endif
static const io_block_spec_t fip_block_spec = {
.offset = PLAT_QEMU_FIP_BASE,
@ -172,10 +177,11 @@ static const io_file_spec_t sh_file_spec[] = {
#endif /* TRUSTED_BOARD_BOOT */
};
static int open_fip(const uintptr_t spec);
static int open_memmap(const uintptr_t spec);
#ifndef DECRYPTION_SUPPORT_none
static int open_enc_fip(const uintptr_t spec);
#endif
struct plat_io_policy {
uintptr_t *dev_handle;
@ -190,16 +196,46 @@ static const struct plat_io_policy policies[] = {
(uintptr_t)&fip_block_spec,
open_memmap
},
[ENC_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)NULL,
open_fip
},
[BL2_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl2_uuid_spec,
open_fip
},
#if ENCRYPT_BL31 && !defined(DECRYPTION_SUPPORT_none)
[BL31_IMAGE_ID] = {
&enc_dev_handle,
(uintptr_t)&bl31_uuid_spec,
open_enc_fip
},
#else
[BL31_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl31_uuid_spec,
open_fip
},
#endif
#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none)
[BL32_IMAGE_ID] = {
&enc_dev_handle,
(uintptr_t)&bl32_uuid_spec,
open_enc_fip
},
[BL32_EXTRA1_IMAGE_ID] = {
&enc_dev_handle,
(uintptr_t)&bl32_extra1_uuid_spec,
open_enc_fip
},
[BL32_EXTRA2_IMAGE_ID] = {
&enc_dev_handle,
(uintptr_t)&bl32_extra2_uuid_spec,
open_enc_fip
},
#else
[BL32_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl32_uuid_spec,
@ -215,6 +251,7 @@ static const struct plat_io_policy policies[] = {
(uintptr_t)&bl32_extra2_uuid_spec,
open_fip
},
#endif
[BL33_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl33_uuid_spec,
@ -271,7 +308,7 @@ static int open_fip(const uintptr_t spec)
/* See if a Firmware Image Package is available */
result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
if (result == 0) {
if (result == 0 && spec != (uintptr_t)NULL) {
result = io_open(fip_dev_handle, spec, &local_image_handle);
if (result == 0) {
VERBOSE("Using FIP\n");
@ -281,6 +318,25 @@ static int open_fip(const uintptr_t spec)
return result;
}
#ifndef DECRYPTION_SUPPORT_none
static int open_enc_fip(const uintptr_t spec)
{
int result;
uintptr_t local_image_handle;
/* See if an encrypted FIP is available */
result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID);
if (result == 0) {
result = io_open(enc_dev_handle, spec, &local_image_handle);
if (result == 0) {
VERBOSE("Using encrypted FIP\n");
io_close(local_image_handle);
}
}
return result;
}
#endif
static int open_memmap(const uintptr_t spec)
{
int result;
@ -333,6 +389,15 @@ void plat_qemu_io_setup(void)
&memmap_dev_handle);
assert(io_result == 0);
#ifndef DECRYPTION_SUPPORT_none
io_result = register_io_dev_enc(&enc_dev_con);
assert(io_result == 0);
io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL,
&enc_dev_handle);
assert(io_result == 0);
#endif
/* Register the additional IO devices on this platform */
io_result = register_io_dev_sh(&sh_dev_con);
assert(io_result == 0);

6
plat/qemu/qemu/include/platform_def.h

@ -172,7 +172,7 @@
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
#define MAX_MMAP_REGIONS 11
#define MAX_XLAT_TABLES 6
#define MAX_IO_DEVICES 3
#define MAX_IO_DEVICES 4
#define MAX_IO_HANDLES 4
/*
@ -196,8 +196,8 @@
#define QEMU_FLASH1_BASE 0x04000000
#define QEMU_FLASH1_SIZE 0x04000000
#define PLAT_QEMU_FIP_BASE QEMU_FLASH1_BASE
#define PLAT_QEMU_FIP_MAX_SIZE QEMU_FLASH1_SIZE
#define PLAT_QEMU_FIP_BASE 0x00040000
#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000
#define DEVICE0_BASE 0x08000000
#define DEVICE0_SIZE 0x01000000

13
plat/qemu/qemu/platform.mk

@ -128,6 +128,11 @@ ifeq ($(add-lib-optee),yes)
BL2_SOURCES += lib/optee/optee_utils.c
endif
ifneq (${DECRYPTION_SUPPORT},none)
BL1_SOURCES += drivers/io/io_encrypted.c
BL2_SOURCES += drivers/io/io_encrypted.c
endif
QEMU_GICV2_SOURCES := drivers/arm/gic/v2/gicv2_helpers.c \
drivers/arm/gic/v2/gicv2_main.c \
drivers/arm/gic/common/gic_common.c \
@ -165,11 +170,19 @@ endif
# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
# in the FIP if the platform requires.
ifneq ($(BL32_EXTRA1),)
ifneq (${DECRYPTION_SUPPORT},none)
$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
else
$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
endif
endif
ifneq ($(BL32_EXTRA2),)
ifneq (${DECRYPTION_SUPPORT},none)
$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
else
$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
endif
endif
SEPARATE_CODE_AND_RODATA := 1
ENABLE_STACK_PROTECTOR := 0

65
tools/encrypt_fw/Makefile

@ -0,0 +1,65 @@
#
# Copyright (c) 2019, Linaro Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
PROJECT := encrypt_fw
V ?= 0
BUILD_INFO ?= 1
DEBUG := 0
BINARY := ${PROJECT}${BIN_EXT}
OPENSSL_DIR := /usr
OBJECTS := src/encrypt.o \
src/cmd_opt.o \
src/main.o
HOSTCCFLAGS := -Wall -std=c99
MAKE_HELPERS_DIRECTORY := ../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
include ${MAKE_HELPERS_DIRECTORY}build_env.mk
ifeq (${DEBUG},1)
HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40
else
ifeq (${BUILD_INFO},1)
HOSTCCFLAGS += -O2 -DLOG_LEVEL=20
else
HOSTCCFLAGS += -O2 -DLOG_LEVEL=10
endif
endif
ifeq (${V},0)
Q := @
else
Q :=
endif
# Make soft links and include from local directory otherwise wrong headers
# could get pulled in from firmware tree.
INC_DIR := -I ./include -I ../../include/tools_share -I ${OPENSSL_DIR}/include
LIB_DIR := -L ${OPENSSL_DIR}/lib
LIB := -lssl -lcrypto
HOSTCC ?= gcc
.PHONY: all clean realclean
all: clean ${BINARY}
${BINARY}: ${OBJECTS} Makefile
@echo " HOSTLD $@"
@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__;' | \
${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o
${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
%.o: %.c
@echo " HOSTCC $<"
${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
clean:
$(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS})
realclean: clean
$(call SHELL_DELETE,${BINARY})

32
tools/encrypt_fw/include/cmd_opt.h

@ -0,0 +1,32 @@
/*
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019, Linaro Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CMD_OPT_H
#define CMD_OPT_H
#include <getopt.h>
#define CMD_OPT_MAX_NUM 64
/* Supported long command line option types */
enum {
CMD_OPT_FW
};
/* Structure to define a command line option */
typedef struct cmd_opt_s {
struct option long_opt;
const char *help_msg;
} cmd_opt_t;
/* Exported API*/
void cmd_opt_add(const cmd_opt_t *cmd_opt);
const struct option *cmd_opt_get_array(void);
const char *cmd_opt_get_name(int idx);
const char *cmd_opt_get_help_msg(int idx);
#endif /* CMD_OPT_H */

59
tools/encrypt_fw/include/debug.h

@ -0,0 +1,59 @@
/*
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef DEBUG_H
#define DEBUG_H
#include <stdio.h>
/* The log output macros print output to the console. These macros produce
* compiled log output only if the LOG_LEVEL defined in the makefile (or the
* make command line) is greater or equal than the level required for that
* type of log output.
* The format expected is the same as for printf(). For example:
* INFO("Info %s.\n", "message") -> INFO: Info message.
* WARN("Warning %s.\n", "message") -> WARNING: Warning message.
*/
#define LOG_LEVEL_NONE 0
#define LOG_LEVEL_ERROR 10
#define LOG_LEVEL_NOTICE 20
#define LOG_LEVEL_WARNING 30
#define LOG_LEVEL_INFO 40
#define LOG_LEVEL_VERBOSE 50
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
# define NOTICE(...) printf("NOTICE: " __VA_ARGS__)
#else
# define NOTICE(...)
#endif
#if LOG_LEVEL >= LOG_LEVEL_ERROR
# define ERROR(...) printf("ERROR: " __VA_ARGS__)
#else
# define ERROR(...)
#endif
#if LOG_LEVEL >= LOG_LEVEL_WARNING
# define WARN(...) printf("WARNING: " __VA_ARGS__)
#else
# define WARN(...)
#endif
#if LOG_LEVEL >= LOG_LEVEL_INFO
# define INFO(...) printf("INFO: " __VA_ARGS__)
#else
# define INFO(...)
#endif
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
# define VERBOSE(...) printf("VERBOSE: " __VA_ARGS__)
#else
# define VERBOSE(...)
#endif
#endif /* DEBUG_H */

19
tools/encrypt_fw/include/encrypt.h

@ -0,0 +1,19 @@
/*
* Copyright (c) 2019, Linaro Limited. All rights reserved.
* Author: Sumit Garg <sumit.garg@linaro.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ENCRYPT_H
#define ENCRYPT_H
/* Supported key algorithms */
enum {
KEY_ALG_GCM /* AES-GCM (default) */
};
int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string,
char *nonce_string, const char *ip_name, const char *op_name);
#endif /* ENCRYPT_H */

59
tools/encrypt_fw/src/cmd_opt.c

@ -0,0 +1,59 @@
/*
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <cmd_opt.h>
#include <getopt.h>
#include <stddef.h>
#include <stdlib.h>
#include "debug.h"
/* Command line options */
static struct option long_opt[CMD_OPT_MAX_NUM+1];
static const char *help_msg[CMD_OPT_MAX_NUM+1];
static int num_reg_opt;
void cmd_opt_add(const cmd_opt_t *cmd_opt)
{
assert(cmd_opt != NULL);
if (num_reg_opt >= CMD_OPT_MAX_NUM) {
ERROR("Out of memory. Please increase CMD_OPT_MAX_NUM\n");
exit(1);
}
long_opt[num_reg_opt].name = cmd_opt->long_opt.name;
long_opt[num_reg_opt].has_arg = cmd_opt->long_opt.has_arg;
long_opt[num_reg_opt].flag = 0;
long_opt[num_reg_opt].val = cmd_opt->long_opt.val;
help_msg[num_reg_opt] = cmd_opt->help_msg;
num_reg_opt++;
}
const struct option *cmd_opt_get_array(void)
{
return long_opt;
}
const char *cmd_opt_get_name(int idx)
{
if (idx >= num_reg_opt) {
return NULL;
}
return long_opt[idx].name;
}
const char *cmd_opt_get_help_msg(int idx)
{
if (idx >= num_reg_opt) {
return NULL;
}
return help_msg[idx];
}

167
tools/encrypt_fw/src/encrypt.c

@ -0,0 +1,167 @@
/*
* Copyright (c) 2019, Linaro Limited. All rights reserved.
* Author: Sumit Garg <sumit.garg@linaro.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <firmware_encrypted.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
#include "debug.h"
#include "encrypt.h"
#define BUFFER_SIZE 256
#define IV_SIZE 12
#define IV_STRING_SIZE 24
#define TAG_SIZE 16
#define KEY_SIZE 32
#define KEY_STRING_SIZE 64
static int gcm_encrypt(unsigned short fw_enc_status, char *key_string,
char *nonce_string, const char *ip_name,
const char *op_name)
{
FILE *ip_file;
FILE *op_file;
EVP_CIPHER_CTX *ctx;
unsigned char data[BUFFER_SIZE], enc_data[BUFFER_SIZE];
unsigned char key[KEY_SIZE], iv[IV_SIZE], tag[TAG_SIZE];
int bytes, enc_len = 0, i, j, ret = 0;
struct fw_enc_hdr header;
memset(&header, 0, sizeof(struct fw_enc_hdr));
if (strlen(key_string) != KEY_STRING_SIZE) {
ERROR("Unsupported key size: %lu\n", strlen(key_string));
return -1;
}
for (i = 0, j = 0; i < KEY_SIZE; i++, j += 2) {
if (sscanf(&key_string[j], "%02hhx", &key[i]) != 1) {
ERROR("Incorrect key format\n");
return -1;
}
}
if (strlen(nonce_string) != IV_STRING_SIZE) {
ERROR("Unsupported IV size: %lu\n", strlen(nonce_string));
return -1;
}
for (i = 0, j = 0; i < IV_SIZE; i++, j += 2) {
if (sscanf(&nonce_string[j], "%02hhx", &iv[i]) != 1) {
ERROR("Incorrect IV format\n");
return -1;
}
}
ip_file = fopen(ip_name, "rb");
if (ip_file == NULL) {
ERROR("Cannot read %s\n", ip_name);
return -1;
}
op_file = fopen(op_name, "wb");
if (op_file == NULL) {
ERROR("Cannot write %s\n", op_name);
fclose(ip_file);
return -1;
}
ret = fseek(op_file, sizeof(struct fw_enc_hdr), SEEK_SET);
if (ret) {
ERROR("fseek failed\n");
goto out_file;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
ERROR("EVP_CIPHER_CTX_new failed\n");
ret = -1;
goto out_file;
}
ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
if (ret != 1) {
ERROR("EVP_EncryptInit_ex failed\n");
ret = -1;
goto out;
}
ret = EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv);
if (ret != 1) {
ERROR("EVP_EncryptInit_ex failed\n");
goto out;
}
while ((bytes = fread(data, 1, BUFFER_SIZE, ip_file)) != 0) {
ret = EVP_EncryptUpdate(ctx, enc_data, &enc_len, data, bytes);
if (ret != 1) {
ERROR("EVP_EncryptUpdate failed\n");
ret = -1;
goto out;
}
fwrite(enc_data, 1, enc_len, op_file);
}
ret = EVP_EncryptFinal_ex(ctx, enc_data, &enc_len);
if (ret != 1) {
ERROR("EVP_EncryptFinal_ex failed\n");
ret = -1;
goto out;
}
ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_SIZE, tag);
if (ret != 1) {
ERROR("EVP_CIPHER_CTX_ctrl failed\n");
ret = -1;
goto out;
}
header.magic = ENC_HEADER_MAGIC;
header.flags |= fw_enc_status & FW_ENC_STATUS_FLAG_MASK;
header.dec_algo = KEY_ALG_GCM;
header.iv_len = IV_SIZE;
header.tag_len = TAG_SIZE;
memcpy(header.iv, iv, IV_SIZE);
memcpy(header.tag, tag, TAG_SIZE);
ret = fseek(op_file, 0, SEEK_SET);
if (ret) {
ERROR("fseek failed\n");
goto out;
}
fwrite(&header, 1, sizeof(struct fw_enc_hdr), op_file);
out:
EVP_CIPHER_CTX_free(ctx);
out_file:
fclose(ip_file);
fclose(op_file);
/*
* EVP_* APIs returns 1 as success but enctool considers
* 0 as success.
*/
if (ret == 1)
ret = 0;
return ret;
}
int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string,
char *nonce_string, const char *ip_name, const char *op_name)
{
switch (enc_alg) {
case KEY_ALG_GCM:
return gcm_encrypt(fw_enc_status, key_string, nonce_string,
ip_name, op_name);
default:
return -1;
}
}

224
tools/encrypt_fw/src/main.c

@ -0,0 +1,224 @@
/*
* Copyright (c) 2019, Linaro Limited. All rights reserved.
* Author: Sumit Garg <sumit.garg@linaro.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <ctype.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <openssl/conf.h>
#include "cmd_opt.h"
#include "debug.h"
#include "encrypt.h"
#include "firmware_encrypted.h"
#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0])))
#define HELP_OPT_MAX_LEN 128
/* Global options */
/* Info messages created in the Makefile */
extern const char build_msg[];
static char *key_algs_str[] = {
[KEY_ALG_GCM] = "gcm",
};
static void print_help(const char *cmd, const struct option *long_opt)
{
int rem, i = 0;
const struct option *opt;
char line[HELP_OPT_MAX_LEN];
char *p;
assert(cmd != NULL);
assert(long_opt != NULL);
printf("\n\n");
printf("The firmware encryption tool loads the binary image and\n"
"outputs encrypted binary image using an encryption key\n"
"provided as an input hex string.\n");
printf("\n");
printf("Usage:\n");
printf("\t%s [OPTIONS]\n\n", cmd);
printf("Available options:\n");
opt = long_opt;
while (opt->name) {
p = line;
rem = HELP_OPT_MAX_LEN;
if (isalpha(opt->val)) {
/* Short format */
sprintf(p, "-%c,", (char)opt->val);
p += 3;
rem -= 3;
}
snprintf(p, rem, "--%s %s", opt->name,
(opt->has_arg == required_argument) ? "<arg>" : "");
printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
opt++;
i++;
}
printf("\n");
}
static int get_key_alg(const char *key_alg_str)
{
int i;
for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
if (strcmp(key_alg_str, key_algs_str[i]) == 0) {
return i;
}
}
return -1;
}
static void parse_fw_enc_status_flag(const char *arg,
unsigned short *fw_enc_status)
{
unsigned long flag;
char *endptr;
flag = strtoul(arg, &endptr, 16);
if (*endptr != '\0' || flag > FW_ENC_WITH_BSSK) {
ERROR("Invalid fw_enc_status flag '%s'\n", arg);
exit(1);
}
*fw_enc_status = flag & FW_ENC_STATUS_FLAG_MASK;
}
/* Common command line options */
static const cmd_opt_t common_cmd_opt[] = {
{
{ "help", no_argument, NULL, 'h' },
"Print this message and exit"
},
{
{ "fw-enc-status", required_argument, NULL, 'f' },
"Firmware encryption status flag (with SSK=0 or BSSK=1)."
},
{
{ "key-alg", required_argument, NULL, 'a' },
"Encryption key algorithm: 'gcm' (default)"
},
{
{ "key", required_argument, NULL, 'k' },
"Encryption key (for supported algorithm)."
},
{
{ "nonce", required_argument, NULL, 'n' },
"Nonce or Initialization Vector (for supported algorithm)."
},
{
{ "in", required_argument, NULL, 'i' },
"Input filename to be encrypted."
},
{
{ "out", required_argument, NULL, 'o' },
"Encrypted output filename."
},
};
int main(int argc, char *argv[])
{
int i, key_alg, ret;
int c, opt_idx = 0;
const struct option *cmd_opt;
char *key = NULL;
char *nonce = NULL;
char *in_fn = NULL;
char *out_fn = NULL;
unsigned short fw_enc_status = 0;
NOTICE("Firmware Encryption Tool: %s\n", build_msg);
/* Set default options */
key_alg = KEY_ALG_GCM;
/* Add common command line options */
for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
cmd_opt_add(&common_cmd_opt[i]);
}
/* Get the command line options populated during the initialization */
cmd_opt = cmd_opt_get_array();
while (1) {
/* getopt_long stores the option index here. */
c = getopt_long(argc, argv, "a:f:hi:k:n:o:", cmd_opt, &opt_idx);
/* Detect the end of the options. */
if (c == -1) {
break;
}
switch (c) {
case 'a':
key_alg = get_key_alg(optarg);
if (key_alg < 0) {
ERROR("Invalid key algorithm '%s'\n", optarg);
exit(1);
}
break;
case 'f':
parse_fw_enc_status_flag(optarg, &fw_enc_status);
break;
case 'k':
key = optarg;
break;
case 'i':
in_fn = optarg;
break;
case 'o':
out_fn = optarg;
break;
case 'n':
nonce = optarg;
break;
case 'h':
print_help(argv[0], cmd_opt);
exit(0);
case '?':
default:
print_help(argv[0], cmd_opt);
exit(1);
}
}
if (!key) {
ERROR("Key must not be NULL\n");
exit(1);
}
if (!nonce) {
ERROR("Nonce must not be NULL\n");
exit(1);
}
if (!in_fn) {
ERROR("Input filename must not be NULL\n");
exit(1);
}
if (!out_fn) {
ERROR("Output filename must not be NULL\n");
exit(1);
}
ret = encrypt_file(fw_enc_status, key_alg, key, nonce, in_fn, out_fn);
CRYPTO_cleanup_all_ex_data();
return ret;
}
Loading…
Cancel
Save