Merge "Necessary fix in drivers to upgrade to mbedtls-2.18.0" into integration
diff --git a/Makefile b/Makefile
index f3cb9be..3d5b395 100644
--- a/Makefile
+++ b/Makefile
@@ -159,6 +159,14 @@
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 @@
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 @@
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 @@
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_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,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_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 @@
# 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 @@
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 @@
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 @@
$(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 @@
${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 @@
@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 @@
@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"
diff --git a/bl1/aarch32/bl1_exceptions.S b/bl1/aarch32/bl1_exceptions.S
index f2af9ab..493d2ca 100644
--- a/bl1/aarch32/bl1_exceptions.S
+++ b/bl1/aarch32/bl1_exceptions.S
@@ -80,7 +80,7 @@
add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
ldm r8, {r0, r1, r2, r3}
- eret
+ exception_return
endfunc bl1_aarch32_smc_handler
/* -----------------------------------------------------
diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S
index 9b4da6b..2e851e6 100644
--- a/bl2/aarch32/bl2_el3_entrypoint.S
+++ b/bl2/aarch32/bl2_el3_entrypoint.S
@@ -87,5 +87,5 @@
add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
ldm r8, {r0, r1, r2, r3}
- eret
+ exception_return
endfunc bl2_run_next_image
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
index e1d961c..9da2f9a 100644
--- a/bl32/tsp/tsp_main.c
+++ b/bl32/tsp/tsp_main.c
@@ -273,11 +273,11 @@
spin_lock(&console_lock);
INFO("TSP: cpu 0x%lx resumed. maximum off power level %lld\n",
read_mpidr(), max_off_pwrlvl);
- INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
+ INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n",
read_mpidr(),
tsp_stats[linear_id].smc_count,
tsp_stats[linear_id].eret_count,
- tsp_stats[linear_id].cpu_suspend_count);
+ tsp_stats[linear_id].cpu_resume_count);
spin_unlock(&console_lock);
#endif
/* Indicate to the SPD that we have completed this request */
diff --git a/docs/change-log-upcoming.rst b/docs/change-log-upcoming.rst
index c4e8bb0..15f39de 100644
--- a/docs/change-log-upcoming.rst
+++ b/docs/change-log-upcoming.rst
@@ -46,6 +46,7 @@
- Security
- Example: "UBSAN support and handlers"
+ - Add support for optional firmware encryption feature (experimental).
- Tools
- Example: "fiptool: Add support to build fiptool on Windows."
diff --git a/docs/design/auth-framework.rst b/docs/design/auth-framework.rst
index ae77391..1a53e22 100644
--- a/docs/design/auth-framework.rst
+++ b/docs/design/auth-framework.rst
@@ -934,7 +934,7 @@
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 @@
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 @@
- ``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
diff --git a/docs/design/trusted-board-boot.rst b/docs/design/trusted-board-boot.rst
index 49e8adb..4802c97 100644
--- a/docs/design/trusted-board-boot.rst
+++ b/docs/design/trusted-board-boot.rst
@@ -229,6 +229,34 @@
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.*
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index da5dcbf..f138feb 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -160,6 +160,12 @@
- ``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 @@
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 @@
- ``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
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index e8357b3..d634d2e 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -872,6 +872,35 @@
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
-----------------------------
diff --git a/docs/getting_started/tools-build.rst b/docs/getting_started/tools-build.rst
index bb707cb..c050f58 100644
--- a/docs/getting_started/tools-build.rst
+++ b/docs/getting_started/tools-build.rst
@@ -135,6 +135,33 @@
./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.*
diff --git a/docs/plat/qemu.rst b/docs/plat/qemu.rst
index 88196bc..afa32c1 100644
--- a/docs/plat/qemu.rst
+++ b/docs/plat/qemu.rst
@@ -21,11 +21,13 @@
- 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 @@
-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
diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c
index 110c504..c63ff08 100644
--- a/drivers/auth/crypto_mod.c
+++ b/drivers/auth/crypto_mod.c
@@ -124,3 +124,35 @@
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);
+}
diff --git a/drivers/auth/cryptocell/712/cryptocell_crypto.c b/drivers/auth/cryptocell/712/cryptocell_crypto.c
index 9112c92..c7ee36f 100644
--- a/drivers/auth/cryptocell/712/cryptocell_crypto.c
+++ b/drivers/auth/cryptocell/712/cryptocell_crypto.c
@@ -302,5 +302,5 @@
/*
* 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);
diff --git a/drivers/auth/dualroot/cot.c b/drivers/auth/dualroot/cot.c
new file mode 100644
index 0000000..eb0b020
--- /dev/null
+++ b/drivers/auth/dualroot/cot.c
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <platform_def.h>
+
+#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include <drivers/auth/auth_mod.h>
+#include <tools_share/dualroot_oid.h>
+
+/*
+ * TODO: Remove dependency on mbedTLS. The chain of trust should be agnostic of
+ * the specific cryptographic library in use.
+*/
+/*
+ * Maximum key and hash sizes (in DER format).
+ *
+ * Both RSA and ECDSA keys may be used at the same time. In this case, the key
+ * buffers must be big enough to hold either. As RSA keys are bigger than ECDSA
+ * ones for all key sizes we support, they impose the minimum size of these
+ * buffers.
+ */
+#if TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE == 1024
+#define PK_DER_LEN 162
+#elif TF_MBEDTLS_KEY_SIZE == 2048
+#define PK_DER_LEN 294
+#elif TF_MBEDTLS_KEY_SIZE == 3072
+#define PK_DER_LEN 422
+#elif TF_MBEDTLS_KEY_SIZE == 4096
+#define PK_DER_LEN 550
+#else
+#error "Invalid value for TF_MBEDTLS_KEY_SIZE"
+#endif
+#else /* Only using ECDSA keys. */
+#define PK_DER_LEN 91
+#endif
+
+#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256
+#define HASH_DER_LEN 51
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384
+#define HASH_DER_LEN 67
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512
+#define HASH_DER_LEN 83
+#else
+#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID"
+#endif
+
+/*
+ * Allocate static buffers to store the authentication parameters extracted from
+ * the certificates.
+ */
+static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char hw_config_hash_buf[HASH_DER_LEN];
+static unsigned char scp_fw_hash_buf[HASH_DER_LEN];
+static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
+
+#ifdef IMAGE_BL2
+static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN];
+static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
+
+static unsigned char trusted_world_pk_buf[PK_DER_LEN];
+static unsigned char content_pk_buf[PK_DER_LEN];
+#endif
+
+/*
+ * Parameter type descriptors.
+ */
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_RAW_DATA, 0);
+
+static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
+static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
+#ifdef IMAGE_BL1
+static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, FWU_HASH_OID);
+#endif /* IMAGE_BL1 */
+
+#ifdef IMAGE_BL2
+static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
+
+static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
+static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, PROT_PK_OID);
+
+static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SCP_FW_HASH_OID);
+static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
+static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
+static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID);
+static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID);
+static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
+static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
+#endif /* IMAGE_BL2 */
+
+
+/* BL2 */
+static const auth_img_desc_t trusted_boot_fw_cert = {
+ .img_id = TRUSTED_BOOT_FW_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tb_fw_hash,
+ .data = {
+ .ptr = (void *)tb_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &tb_fw_config_hash,
+ .data = {
+ .ptr = (void *)tb_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &hw_config_hash,
+ .data = {
+ .ptr = (void *)hw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+#ifdef IMAGE_BL1
+static const auth_img_desc_t bl2_image = {
+ .img_id = BL2_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_boot_fw_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tb_fw_hash
+ }
+ }
+ }
+};
+#endif /* IMAGE_BL1 */
+
+/* HW Config */
+static const auth_img_desc_t hw_config = {
+ .img_id = HW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_boot_fw_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &hw_config_hash
+ }
+ }
+ }
+};
+
+/* TB FW Config */
+#ifdef IMAGE_BL1
+static const auth_img_desc_t tb_fw_config = {
+ .img_id = TB_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_boot_fw_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tb_fw_config_hash
+ }
+ }
+ }
+};
+#endif /* IMAGE_BL1 */
+
+#ifdef IMAGE_BL2
+/* Trusted key certificate */
+static const auth_img_desc_t trusted_key_cert = {
+ .img_id = TRUSTED_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &trusted_world_pk,
+ .data = {
+ .ptr = (void *)trusted_world_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ },
+ }
+};
+
+/* SCP Firmware */
+static const auth_img_desc_t scp_fw_key_cert = {
+ .img_id = SCP_FW_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &scp_fw_content_pk,
+ .data = {
+ .ptr = (void *)content_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t scp_fw_content_cert = {
+ .img_id = SCP_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &scp_fw_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &scp_fw_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &scp_fw_hash,
+ .data = {
+ .ptr = (void *)scp_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t scp_bl2_image = {
+ .img_id = SCP_BL2_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &scp_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &scp_fw_hash
+ }
+ }
+ }
+};
+
+/* SoC Firmware */
+static const auth_img_desc_t soc_fw_key_cert = {
+ .img_id = SOC_FW_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &soc_fw_content_pk,
+ .data = {
+ .ptr = (void *)content_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t soc_fw_content_cert = {
+ .img_id = SOC_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &soc_fw_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &soc_fw_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &soc_fw_hash,
+ .data = {
+ .ptr = (void *)soc_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &soc_fw_config_hash,
+ .data = {
+ .ptr = (void *)soc_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl31_image = {
+ .img_id = BL31_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &soc_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &soc_fw_hash
+ }
+ }
+ }
+};
+
+/* SOC FW Config */
+static const auth_img_desc_t soc_fw_config = {
+ .img_id = SOC_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &soc_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &soc_fw_config_hash
+ }
+ }
+ }
+};
+
+/* Trusted OS Firmware */
+static const auth_img_desc_t trusted_os_fw_key_cert = {
+ .img_id = TRUSTED_OS_FW_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tos_fw_content_pk,
+ .data = {
+ .ptr = (void *)content_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t trusted_os_fw_content_cert = {
+ .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_os_fw_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &tos_fw_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tos_fw_hash,
+ .data = {
+ .ptr = (void *)tos_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &tos_fw_extra1_hash,
+ .data = {
+ .ptr = (void *)tos_fw_extra1_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &tos_fw_extra2_hash,
+ .data = {
+ .ptr = (void *)tos_fw_extra2_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [3] = {
+ .type_desc = &tos_fw_config_hash,
+ .data = {
+ .ptr = (void *)tos_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl32_image = {
+ .img_id = BL32_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_os_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tos_fw_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl32_extra1_image = {
+ .img_id = BL32_EXTRA1_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_os_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tos_fw_extra1_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl32_extra2_image = {
+ .img_id = BL32_EXTRA2_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_os_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tos_fw_extra2_hash
+ }
+ }
+ }
+};
+
+/* TOS FW Config */
+static const auth_img_desc_t tos_fw_config = {
+ .img_id = TOS_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_os_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tos_fw_config_hash
+ }
+ }
+ }
+};
+
+/* Non-Trusted Firmware */
+static const auth_img_desc_t non_trusted_fw_content_cert = {
+ .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL, /* Root certificate. */
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &prot_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &non_trusted_nv_ctr,
+ .plat_nv_ctr = &non_trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &nt_world_bl_hash,
+ .data = {
+ .ptr = (void *)nt_world_bl_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &nt_fw_config_hash,
+ .data = {
+ .ptr = (void *)nt_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl33_image = {
+ .img_id = BL33_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &non_trusted_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &nt_world_bl_hash
+ }
+ }
+ }
+};
+
+/* NT FW Config */
+static const auth_img_desc_t nt_fw_config = {
+ .img_id = NT_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &non_trusted_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &nt_fw_config_hash
+ }
+ }
+ }
+};
+
+#else /* IMAGE_BL2 */
+
+/* FWU auth descriptor */
+static const auth_img_desc_t fwu_cert = {
+ .img_id = FWU_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &scp_bl2u_hash,
+ .data = {
+ .ptr = (void *)scp_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &bl2u_hash,
+ .data = {
+ .ptr = (void *)tb_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &ns_bl2u_hash,
+ .data = {
+ .ptr = (void *)nt_world_bl_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+/* SCP_BL2U */
+static const auth_img_desc_t scp_bl2u_image = {
+ .img_id = SCP_BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &scp_bl2u_hash
+ }
+ }
+ }
+};
+
+/* BL2U */
+static const auth_img_desc_t bl2u_image = {
+ .img_id = BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl2u_hash
+ }
+ }
+ }
+};
+
+/* NS_BL2U */
+static const auth_img_desc_t ns_bl2u_image = {
+ .img_id = NS_BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ns_bl2u_hash
+ }
+ }
+ }
+};
+#endif /* IMAGE_BL2 */
+
+/*
+ * Chain of trust definition
+ */
+#ifdef IMAGE_BL1
+static const auth_img_desc_t * const cot_desc[] = {
+ [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
+ [BL2_IMAGE_ID] = &bl2_image,
+ [HW_CONFIG_ID] = &hw_config,
+ [TB_FW_CONFIG_ID] = &tb_fw_config,
+ [FWU_CERT_ID] = &fwu_cert,
+ [SCP_BL2U_IMAGE_ID] = &scp_bl2u_image,
+ [BL2U_IMAGE_ID] = &bl2u_image,
+ [NS_BL2U_IMAGE_ID] = &ns_bl2u_image
+};
+#else /* IMAGE_BL2 */
+static const auth_img_desc_t * const cot_desc[] = {
+ [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
+ [HW_CONFIG_ID] = &hw_config,
+ [TRUSTED_KEY_CERT_ID] = &trusted_key_cert,
+ [SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert,
+ [SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert,
+ [SCP_BL2_IMAGE_ID] = &scp_bl2_image,
+ [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert,
+ [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert,
+ [BL31_IMAGE_ID] = &bl31_image,
+ [SOC_FW_CONFIG_ID] = &soc_fw_config,
+ [TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert,
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
+ [BL32_IMAGE_ID] = &bl32_image,
+ [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image,
+ [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image,
+ [TOS_FW_CONFIG_ID] = &tos_fw_config,
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
+ [BL33_IMAGE_ID] = &bl33_image,
+ [NT_FW_CONFIG_ID] = &nt_fw_config,
+};
+#endif
+
+/* Register the CoT in the authentication module */
+REGISTER_COT(cot_desc);
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 4b83015..044b368 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -23,13 +23,17 @@
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 @@
$(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))
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c
index 4c6dc0f..6d6efb5 100644
--- a/drivers/auth/mbedtls/mbedtls_crypto.c
+++ b/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>
@@ -18,6 +20,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"
@@ -227,11 +230,121 @@
}
#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 */
diff --git a/drivers/io/io_encrypted.c b/drivers/io/io_encrypted.c
new file mode 100644
index 0000000..744ca83
--- /dev/null
+++ b/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;
+}
diff --git a/fdts/a5ds.dts b/fdts/a5ds.dts
index 31d635a..7334c45 100644
--- a/fdts/a5ds.dts
+++ b/fdts/a5ds.dts
@@ -136,4 +136,23 @@
reg = <0x1a050000 0x1000>;
};
};
+ v2m_fixed_3v3: fixed-regulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ethernet@4020000 {
+ compatible = "smsc,lan9220", "smsc,lan9115";
+ reg = <0x40200000 0x10000>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 43 0xf04>;
+ reg-io-width = <4>;
+ phy-mode = "mii";
+ smsc,irq-active-high;
+ vdd33a-supply = <&v2m_fixed_3v3>;
+ vddvario-supply = <&v2m_fixed_3v3>;
+ };
};
diff --git a/include/arch/aarch32/asm_macros.S b/include/arch/aarch32/asm_macros.S
index 8cfa212..ea1636e 100644
--- a/include/arch/aarch32/asm_macros.S
+++ b/include/arch/aarch32/asm_macros.S
@@ -95,11 +95,24 @@
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
/*
+ * Macro for mitigating against speculative execution.
* ARMv7 cores without Virtualization extension do not support the
* eret instruction.
*/
- .macro eret
+ .macro exception_return
movs pc, lr
+ dsb nsh
+ isb
+ .endm
+
+#else
+ /*
+ * Macro for mitigating against speculative execution beyond ERET.
+ */
+ .macro exception_return
+ eret
+ dsb nsh
+ isb
.endm
#endif
diff --git a/include/arch/aarch32/smccc_macros.S b/include/arch/aarch32/smccc_macros.S
index 4ec2292..ea7835a 100644
--- a/include/arch/aarch32/smccc_macros.S
+++ b/include/arch/aarch32/smccc_macros.S
@@ -235,7 +235,7 @@
/* Restore the rest of the general purpose registers */
ldm r0, {r0-r12}
- eret
+ exception_return
.endm
#endif /* SMCCC_MACROS_S */
diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h
index f211035..71cf673 100644
--- a/include/drivers/auth/crypto_mod.h
+++ b/include/drivers/auth/crypto_mod.h
@@ -13,9 +13,18 @@
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 @@
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 @@
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 @@
/* 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 */
diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h
index 6e179bb..dc00da7 100644
--- a/include/drivers/auth/mbedtls/mbedtls_config.h
+++ b/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
diff --git a/include/drivers/io/io_encrypted.h b/include/drivers/io/io_encrypted.h
new file mode 100644
index 0000000..9dcf061
--- /dev/null
+++ b/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 */
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
index a301ad5..f2d641c 100644
--- a/include/drivers/io/io_storage.h
+++ b/include/drivers/io/io_storage.h
@@ -25,6 +25,7 @@
IO_TYPE_MTD,
IO_TYPE_MMC,
IO_TYPE_STM32IMAGE,
+ IO_TYPE_ENCRYPTED,
IO_TYPE_MAX
} io_type_t;
diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h
index 3602554..89dbc58 100644
--- a/include/export/common/tbbr/tbbr_img_def_exp.h
+++ b/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 */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index f5bd298..5b5ebb9 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -27,6 +27,7 @@
struct mmap_region;
struct spm_mm_boot_info;
struct sp_res_desc;
+enum fw_enc_status_t;
/*******************************************************************************
* plat_get_rotpk_info() flags
@@ -37,6 +38,15 @@
#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_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
diff --git a/include/tools_share/dualroot_oid.h b/include/tools_share/dualroot_oid.h
new file mode 100644
index 0000000..3e88a6d
--- /dev/null
+++ b/include/tools_share/dualroot_oid.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DUALROOT_OID_H
+#define DUALROOT_OID_H
+
+/* Reuse the Object IDs defined by TBBR for certificate extensions. */
+#include "tbbr_oid.h"
+
+/*
+ * Platform root-of-trust public key.
+ * Arbitrary value that does not conflict with any of the TBBR reserved OIDs.
+ */
+#define PROT_PK_OID "1.3.6.1.4.1.4128.2100.1102"
+
+#endif /* DUALROOT_OID_H */
diff --git a/include/tools_share/firmware_encrypted.h b/include/tools_share/firmware_encrypted.h
new file mode 100644
index 0000000..7ca634f
--- /dev/null
+++ b/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 */
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index c377b28..e260f8d 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -156,12 +156,12 @@
* ----------------------------------------------------
*/
func denver_enable_dco
- mov x3, x30
+ mov x18, x30
bl plat_my_core_pos
mov x1, #1
lsl x1, x1, x0
msr s3_0_c15_c0_2, x1
- mov x30, x3
+ mov x30, x18
ret
endfunc denver_enable_dco
@@ -171,7 +171,7 @@
*/
func denver_disable_dco
- mov x3, x30
+ mov x18, x30
/* turn off background work */
bl plat_my_core_pos
@@ -188,7 +188,7 @@
and x2, x2, x1
cbnz x2, 1b
- mov x30, x3
+ mov x30, x18
ret
endfunc denver_disable_dco
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 032e42c..20a36fe 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -109,6 +109,22 @@
${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 @@
# $(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 @@
# $(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 @@
$(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 @@
# $(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 @@
$(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 @@
# $(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 @@
$(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 @@
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
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 9273469..03322db 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -65,6 +65,9 @@
# Debug build
DEBUG := 0
+# By default disable authenticated decryption support.
+DECRYPTION_SUPPORT := none
+
# Build platform
DEFAULT_PLAT := fvp
@@ -106,6 +109,18 @@
# 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 @@
# 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
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index 9c47cc7..f0adfe1 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -23,6 +23,7 @@
# KEY_ALG
# KEY_SIZE
# ROT_KEY
+# PROT_KEY
# TRUSTED_WORLD_KEY
# NON_TRUSTED_WORLD_KEY
# SCP_BL2_KEY
@@ -57,6 +58,7 @@
$(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg)))
$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key)))
$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,FWU_)))
+$(if ${PROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${PROT_KEY},--prot-key)))
$(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key)))
$(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key)))
@@ -93,5 +95,7 @@
ifneq (${BL33},)
$(if ${BL33_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL33_KEY},--nt-fw-key)))
$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_content.crt,--nt-fw-cert))
+ifneq (${COT},dualroot)
$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_key.crt,--nt-fw-key-cert))
endif
+endif
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index 6070db2..de6c1d1 100644
--- a/plat/common/plat_bl_common.c
+++ b/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)
{
@@ -53,6 +55,31 @@
}
/*
+ * 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
* as an array specifying the generic memory regions which can be;
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index 13ca6aa..7cba3a4 100644
--- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,21 +19,16 @@
/*******************************************************************************
* Implementation defined ACTLR_EL3 bit definitions
******************************************************************************/
-#define ACTLR_EL3_L2ACTLR_BIT (U(1) << 6)
-#define ACTLR_EL3_L2ECTLR_BIT (U(1) << 5)
-#define ACTLR_EL3_L2CTLR_BIT (U(1) << 4)
-#define ACTLR_EL3_CPUECTLR_BIT (U(1) << 1)
-#define ACTLR_EL3_CPUACTLR_BIT (U(1) << 0)
-#define ACTLR_EL3_ENABLE_ALL_MASK (ACTLR_EL3_L2ACTLR_BIT | \
- ACTLR_EL3_L2ECTLR_BIT | \
- ACTLR_EL3_L2CTLR_BIT | \
- ACTLR_EL3_CPUECTLR_BIT | \
- ACTLR_EL3_CPUACTLR_BIT)
-#define ACTLR_EL3_ENABLE_ALL_ACCESS (ACTLR_EL3_L2ACTLR_BIT | \
- ACTLR_EL3_L2ECTLR_BIT | \
- ACTLR_EL3_L2CTLR_BIT | \
- ACTLR_EL3_CPUECTLR_BIT | \
- ACTLR_EL3_CPUACTLR_BIT)
+#define ACTLR_ELx_L2ACTLR_BIT (U(1) << 6)
+#define ACTLR_ELx_L2ECTLR_BIT (U(1) << 5)
+#define ACTLR_ELx_L2CTLR_BIT (U(1) << 4)
+#define ACTLR_ELx_CPUECTLR_BIT (U(1) << 1)
+#define ACTLR_ELx_CPUACTLR_BIT (U(1) << 0)
+#define ACTLR_ELx_ENABLE_ALL_ACCESS (ACTLR_ELx_L2ACTLR_BIT | \
+ ACTLR_ELx_L2ECTLR_BIT | \
+ ACTLR_ELx_L2CTLR_BIT | \
+ ACTLR_ELx_CPUECTLR_BIT | \
+ ACTLR_ELx_CPUACTLR_BIT)
/* Global functions */
.globl plat_is_my_cpu_primary
@@ -93,15 +89,11 @@
* -------------------------------------------------------
*/
mrs x0, actlr_el3
- mov x1, #ACTLR_EL3_ENABLE_ALL_MASK
- bic x0, x0, x1
- mov x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
+ mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS
orr x0, x0, x1
msr actlr_el3, x0
mrs x0, actlr_el2
- mov x1, #ACTLR_EL3_ENABLE_ALL_MASK
- bic x0, x0, x1
- mov x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
+ mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS
orr x0, x0, x1
msr actlr_el2, x0
isb
diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
index 8e198ae..dee99fb 100644
--- a/plat/nvidia/tegra/common/tegra_fiq_glue.c
+++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,7 +13,6 @@
#include <common/debug.h>
#include <context.h>
#include <denver.h>
-#include <lib/bakery_lock.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <plat/common/platform.h>
@@ -25,8 +25,6 @@
/* Legacy FIQ used by earlier Tegra platforms */
#define LEGACY_FIQ_PPI_WDT 28U
-static DEFINE_BAKERY_LOCK(tegra_fiq_lock);
-
/*******************************************************************************
* Static variables
******************************************************************************/
@@ -57,8 +55,6 @@
*/
irq = plat_ic_get_pending_interrupt_id();
- bakery_lock_get(&tegra_fiq_lock);
-
/*
* Jump to NS world only if the NS world's FIQ handler has
* been registered
@@ -107,8 +103,6 @@
plat_ic_end_of_interrupt(irq);
}
- bakery_lock_release(&tegra_fiq_lock);
-
return 0;
}
diff --git a/plat/nvidia/tegra/include/drivers/pmc.h b/plat/nvidia/tegra/include/drivers/pmc.h
index 32252a2..8752b84 100644
--- a/plat/nvidia/tegra/include/drivers/pmc.h
+++ b/plat/nvidia/tegra/include/drivers/pmc.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,27 +19,37 @@
#define PMC_DPD_ENABLE_0 U(0x24)
#define PMC_PWRGATE_STATUS U(0x38)
#define PMC_PWRGATE_TOGGLE U(0x30)
-#define PMC_SECURE_SCRATCH0 U(0xb0)
-#define PMC_SECURE_SCRATCH5 U(0xc4)
+#define PMC_SCRATCH1 U(0x54)
#define PMC_CRYPTO_OP_0 U(0xf4)
#define PMC_TOGGLE_START U(0x100)
+#define PMC_SCRATCH31 U(0x118)
+#define PMC_SCRATCH32 U(0x11C)
+#define PMC_SCRATCH33 U(0x120)
#define PMC_SCRATCH39 U(0x138)
+#define PMC_SCRATCH40 U(0x13C)
#define PMC_SCRATCH41 U(0x140)
-#define PMC_SECURE_SCRATCH6 U(0x224)
-#define PMC_SECURE_SCRATCH7 U(0x228)
-#define PMC_SECURE_DISABLE2 U(0x2c4)
+#define PMC_SCRATCH42 U(0x144)
+#define PMC_SCRATCH43 U(0x22C)
+#define PMC_SCRATCH44 U(0x230)
+#define PMC_SCRATCH45 U(0x234)
+#define PMC_SCRATCH46 U(0x238)
+#define PMC_SCRATCH47 U(0x23C)
+#define PMC_SCRATCH48 U(0x240)
+#define PMC_SCRATCH50 U(0x248)
+#define PMC_SCRATCH51 U(0x24C)
+#define PMC_TSC_MULT_0 U(0x2B4)
+#define PMC_STICKY_BIT U(0x2C0)
+#define PMC_SECURE_DISABLE2 U(0x2C4)
#define PMC_SECURE_DISABLE2_WRITE22_ON (U(1) << 28)
-#define PMC_SECURE_SCRATCH8 U(0x300)
-#define PMC_SECURE_SCRATCH79 U(0x41c)
#define PMC_FUSE_CONTROL_0 U(0x450)
-#define PMC_SECURE_SCRATCH22 U(0x338)
-#define PMC_SECURE_DISABLE3 U(0x2d8)
+#define PMC_SECURE_DISABLE3 U(0x2D8)
#define PMC_SECURE_DISABLE3_WRITE34_ON (U(1) << 20)
#define PMC_SECURE_DISABLE3_WRITE35_ON (U(1) << 22)
+#define PMC_SECURE_SCRATCH22 U(0x338)
#define PMC_SECURE_SCRATCH34 U(0x368)
#define PMC_SECURE_SCRATCH35 U(0x36c)
-#define PMC_SECURE_SCRATCH80 U(0xa98)
-#define PMC_SECURE_SCRATCH119 U(0xb34)
+#define PMC_SCRATCH56 U(0x600)
+#define PMC_SCRATCH57 U(0x604)
#define PMC_SCRATCH201 U(0x844)
static inline uint32_t tegra_pmc_read_32(uint32_t off)
diff --git a/plat/nvidia/tegra/include/drivers/security_engine.h b/plat/nvidia/tegra/include/drivers/security_engine.h
index 8a24924..5ae6257 100644
--- a/plat/nvidia/tegra/include/drivers/security_engine.h
+++ b/plat/nvidia/tegra/include/drivers/security_engine.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -55,5 +55,6 @@
int tegra_se_suspend(void);
void tegra_se_resume(void);
int tegra_se_save_tzram(void);
+int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte);
#endif /* SECURITY_ENGINE_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index f2a2334..3d037e1 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -213,6 +213,14 @@
#define RNG_MUTEX_WATCHDOG_NS_LIMIT U(0xFE0)
/*******************************************************************************
+ * Tegra HSP doorbell #0 constants
+ ******************************************************************************/
+#define TEGRA_HSP_DBELL_BASE U(0x03C90000)
+#define HSP_DBELL_1_ENABLE U(0x104)
+#define HSP_DBELL_3_TRIGGER U(0x300)
+#define HSP_DBELL_3_ENABLE U(0x304)
+
+/*******************************************************************************
* Tegra Clock and Reset Controller constants
******************************************************************************/
#define TEGRA_CAR_RESET_BASE U(0x05000000)
@@ -238,6 +246,7 @@
* Tegra scratch registers constants
******************************************************************************/
#define TEGRA_SCRATCH_BASE U(0x0C390000)
+#define SECURE_SCRATCH_RSV0_HI U(0x654)
#define SECURE_SCRATCH_RSV1_LO U(0x658)
#define SECURE_SCRATCH_RSV1_HI U(0x65C)
#define SECURE_SCRATCH_RSV6 U(0x680)
@@ -247,6 +256,15 @@
#define SECURE_SCRATCH_RSV53_HI U(0x7FC)
#define SECURE_SCRATCH_RSV55_LO U(0x808)
#define SECURE_SCRATCH_RSV55_HI U(0x80C)
+#define SECURE_SCRATCH_RSV63_LO U(0x848)
+#define SECURE_SCRATCH_RSV63_HI U(0x84C)
+#define SECURE_SCRATCH_RSV64_LO U(0x850)
+#define SECURE_SCRATCH_RSV64_HI U(0x854)
+#define SECURE_SCRATCH_RSV65_LO U(0x858)
+#define SECURE_SCRATCH_RSV65_HI U(0x85c)
+#define SECURE_SCRATCH_RSV66_LO U(0x860)
+#define SECURE_SCRATCH_RSV66_HI U(0x864)
+#define SECURE_SCRATCH_RSV68_LO U(0x870)
#define SCRATCH_RESET_VECTOR_LO SECURE_SCRATCH_RSV1_LO
#define SCRATCH_RESET_VECTOR_HI SECURE_SCRATCH_RSV1_HI
@@ -281,6 +299,13 @@
#define TEGRA_TZRAM_SIZE U(0x40000)
/*******************************************************************************
+ * Tegra CCPLEX-BPMP IPC constants
+ ******************************************************************************/
+#define TEGRA_BPMP_IPC_TX_PHYS_BASE U(0x3004C000)
+#define TEGRA_BPMP_IPC_RX_PHYS_BASE U(0x3004D000)
+#define TEGRA_BPMP_IPC_CH_MAP_SIZE U(0x1000) /* 4KB */
+
+/*******************************************************************************
* Tegra DRAM memory base address
******************************************************************************/
#define TEGRA_DRAM_BASE ULL(0x80000000)
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index 4a39aa1..e8bce5e 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -144,6 +144,9 @@
#define SE_CLK_ENB_BIT (U(1) << 31)
#define TEGRA_CLK_OUT_ENB_W U(0x364)
#define ENTROPY_RESET_BIT (U(1) << 21)
+#define TEGRA_CLK_RST_CTL_CLK_SRC_SE U(0x42C)
+#define SE_CLK_SRC_MASK (U(7) << 29)
+#define SE_CLK_SRC_CLK_M (U(6) << 29)
#define TEGRA_RST_DEV_SET_V U(0x430)
#define SE_RESET_BIT (U(1) << 31)
#define HDA_RESET_BIT (U(1) << 29)
diff --git a/plat/nvidia/tegra/soc/t186/drivers/se/se.c b/plat/nvidia/tegra/soc/t186/drivers/se/se.c
new file mode 100644
index 0000000..dfb9de8
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/se/se.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <string.h>
+
+#include <bpmp_ipc.h>
+#include <pmc.h>
+#include <security_engine.h>
+#include <tegra186_private.h>
+#include <tegra_private.h>
+
+#include "se_private.h"
+
+/*******************************************************************************
+ * Constants and Macros
+ ******************************************************************************/
+#define SE0_MAX_BUSY_TIMEOUT_MS U(100) /* 100ms */
+#define BYTES_IN_WORD U(4)
+#define SHA256_MAX_HASH_RESULT U(7)
+#define SHA256_DST_SIZE U(32)
+#define SHA_FIRST_OP U(1)
+#define MAX_SHA_ENGINE_CHUNK_SIZE U(0xFFFFFF)
+#define SHA256_MSG_LENGTH_ONETIME U(0xffff)
+
+/*
+ * Check that SE operation has completed after kickoff
+ * This function is invoked after an SE operation has been started,
+ * and it checks the following conditions:
+ * 1. SE0_INT_STATUS = SE0_OP_DONE
+ * 2. SE0_STATUS = IDLE
+ * 3. SE0_ERR_STATUS is clean.
+ */
+static int32_t tegra_se_operation_complete(void)
+{
+ uint32_t val = 0U;
+
+ /* Read SE0 interrupt register to ensure H/W operation complete */
+ val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+ if (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
+ ERROR("%s: Engine busy state too many times! val = 0x%x\n",
+ __func__, val);
+ return -ETIMEDOUT;
+ }
+
+ /* Read SE0 status idle to ensure H/W operation complete */
+ val = tegra_se_read_32(SE0_SHA_STATUS_0);
+ if (val != SE0_SHA_STATUS_IDLE) {
+ ERROR("%s: Idle state timeout! val = 0x%x\n", __func__,
+ val);
+ return -ETIMEDOUT;
+ }
+
+ /* Ensure that no errors are thrown during operation */
+ val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
+ if (val != SE0_ERR_STATUS_CLEAR) {
+ ERROR("%s: Error during SE operation! val = 0x%x",
+ __func__, val);
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+/*
+ * Security engine primitive normal operations
+ */
+static int32_t tegra_se_start_normal_operation(uint64_t src_addr,
+ uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes)
+{
+ int32_t ret = 0;
+ uint32_t val = 0U;
+ uint32_t src_in_lo;
+ uint32_t src_in_msb;
+ uint32_t src_in_hi;
+
+ if ((src_addr == 0UL) || (nbytes == 0U))
+ return -EINVAL;
+
+ src_in_lo = (uint32_t)src_addr;
+ src_in_msb = ((uint32_t)(src_addr >> 32U) & 0xffU);
+ src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) |
+ (nbytes & 0xffffffU));
+
+ /* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/
+ tegra_se_write_32(SE0_IN_ADDR, src_in_lo);
+ tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi);
+
+ val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+ if (val > 0U) {
+ tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x00000U);
+ }
+
+ /* Enable SHA interrupt for SE0 Operation */
+ tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU);
+
+ /* flush to DRAM for SE to use the updated contents */
+ flush_dcache_range(src_addr, src_len_inbytes);
+
+ /* Start SHA256 operation */
+ if (last_buf == 1U) {
+ tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START |
+ SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD);
+ } else {
+ tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START);
+ }
+
+ /* Wait for SE-operation to finish */
+ udelay(SE0_MAX_BUSY_TIMEOUT_MS * 100U);
+
+ /* Check SE0 operation status */
+ ret = tegra_se_operation_complete();
+ if (ret != 0) {
+ ERROR("SE operation complete Failed! 0x%x", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr,
+ uint32_t src_len_inbyte)
+{
+ uint32_t val, last_buf, i;
+ int32_t ret = 0;
+ uint32_t operations;
+ uint64_t src_len_inbits;
+ uint32_t len_bits_msb;
+ uint32_t len_bits_lsb;
+ uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes;
+
+ if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) {
+ ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte);
+ return -EINVAL;
+ }
+
+ if (src_addr == 0UL) {
+ return -EINVAL;
+ }
+
+ /* number of bytes per operation */
+ max_bytes = SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME;
+
+ src_len_inbits = src_len_inbyte * 8U;
+ len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
+ len_bits_lsb = (uint32_t)(src_len_inbits & 0xFFFFFFFF);
+
+ /* program SE0_CONFIG for SHA256 operation */
+ val = SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 |
+ SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG;
+ tegra_se_write_32(SE0_SHA_CONFIG, val);
+
+ /* set SE0_SHA_MSG_LENGTH registers */
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb);
+
+ /* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U);
+
+ number_of_operations = src_len_inbyte / max_bytes;
+ remaining_bytes = src_len_inbyte % max_bytes;
+ if (remaining_bytes > 0U) {
+ number_of_operations += 1U;
+ }
+
+ /*
+ * 1. Operations == 1: program SE0_SHA_TASK register to initiate SHA256
+ * hash generation by setting
+ * 1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK
+ * and start SHA256-normal operation.
+ * 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to
+ * 0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load
+ * intermediate SHA256 digest result from
+ * HASH_RESULT register to continue SHA256
+ * generation and start SHA256-normal operation.
+ * 3. Operations == number_of_operations: continue with step 2 and set
+ * max_bytes to bytes_left to process final
+ * hash-result generation and
+ * start SHA256-normal operation.
+ */
+ bytes_left = src_len_inbyte;
+ for (operations = 1U; operations <= number_of_operations;
+ operations++) {
+ if (operations == SHA_FIRST_OP) {
+ val = SE0_SHA_CONFIG_HW_INIT_HASH;
+ } else {
+ /* Load intermediate SHA digest result to
+ * SHA:HASH_RESULT(0..7) to continue the SHA
+ * calculation and tell the SHA engine to use it.
+ */
+ for (i = 0U; (i / BYTES_IN_WORD) <=
+ SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) {
+ val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 +
+ i);
+ tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i,
+ val);
+ }
+ val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE;
+ if (len_bits_lsb <= (max_bytes * 8U)) {
+ len_bits_lsb = (remaining_bytes * 8U);
+ } else {
+ len_bits_lsb -= (max_bytes * 8U);
+ }
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+ }
+ tegra_se_write_32(SE0_SHA_TASK_CONFIG, val);
+
+ max_bytes = (SHA256_HASH_SIZE_BYTES *
+ SHA256_MSG_LENGTH_ONETIME);
+ if (bytes_left < max_bytes) {
+ max_bytes = bytes_left;
+ last_buf = 1U;
+ } else {
+ bytes_left = bytes_left - max_bytes;
+ last_buf = 0U;
+ }
+ /* start operation */
+ ret = tegra_se_start_normal_operation(src_addr, max_bytes,
+ last_buf, src_len_inbyte);
+ if (ret != 0) {
+ ERROR("Error during SE operation! 0x%x", ret);
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Handler to generate SHA256 and save SHA256 hash to PMC-Scratch register.
+ */
+int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte)
+{
+ int32_t ret = 0;
+ uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U, security;
+
+ /*
+ * Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE
+ * registers.
+ */
+ security = tegra_se_read_32(SE0_SECURITY);
+ tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING);
+
+ ret = tegra_se_calculate_sha256_hash(bl31_base, src_len_inbyte);
+ if (ret != 0L) {
+ ERROR("%s: SHA256 generation failed\n", __func__);
+ return ret;
+ }
+
+ /*
+ * Reset SE_SECURE to previous value.
+ */
+ tegra_se_write_32(SE0_SECURITY, security);
+
+ /* read SHA256_HASH_RESULT and save to PMC Scratch registers */
+ scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
+ while (scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END) {
+
+ val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
+ mmio_write_32(TEGRA_SCRATCH_BASE + scratch_offset, val);
+
+ hash_offset += BYTES_IN_WORD;
+ scratch_offset += BYTES_IN_WORD;
+ }
+
+ return ret;
+}
+
diff --git a/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h
new file mode 100644
index 0000000..7aa0dd6
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SE_PRIVATE_H
+#define SE_PRIVATE_H
+
+#include <lib/utils_def.h>
+
+/* SE0 security register */
+#define SE0_SECURITY U(0x18)
+#define SE0_SECURITY_SE_SOFT_SETTING (((uint32_t)1) << 16U)
+
+/* SE0 config register */
+#define SE0_SHA_CONFIG U(0x104)
+#define SE0_SHA_TASK_CONFIG U(0x108)
+#define SE0_SHA_CONFIG_HW_INIT_HASH ((1U) << 0U)
+#define SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE U(0)
+
+#define SE0_CONFIG_ENC_ALG_SHIFT U(12)
+#define SE0_CONFIG_ENC_ALG_SHA \
+ (((uint32_t)3) << SE0_CONFIG_ENC_ALG_SHIFT)
+#define SE0_CONFIG_DEC_ALG_SHIFT U(8)
+#define SE0_CONFIG_DEC_ALG_NOP \
+ (((uint32_t)0) << SE0_CONFIG_DEC_ALG_SHIFT)
+#define SE0_CONFIG_DST_SHIFT U(2)
+#define SE0_CONFIG_DST_HASHREG \
+ (((uint32_t)1) << SE0_CONFIG_DST_SHIFT)
+#define SHA256_HASH_SIZE_BYTES U(256)
+
+#define SE0_CONFIG_ENC_MODE_SHIFT U(24)
+#define SE0_CONFIG_ENC_MODE_SHA256 \
+ (((uint32_t)5) << SE0_CONFIG_ENC_MODE_SHIFT)
+
+/* SHA input message length */
+#define SE0_SHA_MSG_LENGTH_0 U(0x11c)
+#define SE0_SHA_MSG_LENGTH_1 U(0x120)
+#define SE0_SHA_MSG_LENGTH_2 U(0x124)
+#define SE0_SHA_MSG_LENGTH_3 U(0x128)
+
+/* SHA input message left */
+#define SE0_SHA_MSG_LEFT_0 U(0x12c)
+#define SE0_SHA_MSG_LEFT_1 U(0x130)
+#define SE0_SHA_MSG_LEFT_2 U(0x134)
+#define SE0_SHA_MSG_LEFT_3 U(0x138)
+
+/* SE Hash Result */
+#define SE0_SHA_HASH_RESULT_0 U(0x13c)
+
+/* SE OPERATION */
+#define SE0_OPERATION_REG_OFFSET U(0x17c)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT U(16)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD \
+ (((uint32_t)0x1) << SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT)
+#define SE0_OPERATION_SHIFT U(0)
+#define SE0_OP_START \
+ (((uint32_t)0x1) << SE0_OPERATION_SHIFT)
+
+/* SE Interrupt */
+#define SE0_SHA_INT_ENABLE U(0x180)
+
+#define SE0_INT_STATUS_REG_OFFSET U(0x184)
+#define SE0_INT_OP_DONE_SHIFT U(4)
+#define SE0_INT_OP_DONE_CLEAR \
+ (((uint32_t)0) << SE0_INT_OP_DONE_SHIFT)
+#define SE0_INT_OP_DONE(x) \
+ ((x) & (((uint32_t)0x1) << SE0_INT_OP_DONE_SHIFT))
+
+/* SE SHA status */
+#define SE0_SHA_STATUS_0 U(0x188)
+#define SE0_SHA_STATUS_IDLE U(0)
+
+/* SE error status */
+#define SE0_ERR_STATUS_REG_OFFSET U(0x18c)
+#define SE0_ERR_STATUS_CLEAR U(0)
+#define SE0_IN_ADDR U(0x10c)
+#define SE0_IN_HI_ADDR_HI U(0x110)
+#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT U(24)
+
+/* SE error status */
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START SECURE_SCRATCH_RSV63_LO
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END SECURE_SCRATCH_RSV66_HI
+
+/*******************************************************************************
+ * Inline functions definition
+ ******************************************************************************/
+
+static inline uint32_t tegra_se_read_32(uint32_t offset)
+{
+ return mmio_read_32((uint32_t)(TEGRA_SE0_BASE + offset));
+}
+
+static inline void tegra_se_write_32(uint32_t offset, uint32_t val)
+{
+ mmio_write_32(((uint32_t)(TEGRA_SE0_BASE + offset)), val);
+}
+
+#endif /* SE_PRIVATE_H */
diff --git a/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
index 4ca5e77..a97496b 100644
--- a/plat/nvidia/tegra/soc/t186/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,7 +11,11 @@
#include <mce.h>
#include <memctrl_v2.h>
#include <tegra_mc_def.h>
+#include <tegra186_private.h>
#include <tegra_platform.h>
+#include <tegra_private.h>
+
+extern uint64_t tegra_bl31_phys_base;
/*******************************************************************************
* Array to hold stream_id override config register offsets
@@ -540,6 +545,13 @@
void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes)
{
uint32_t val;
+ uint64_t src_base_tzdram;
+ const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ uint64_t src_len_in_bytes = BL31_END - BL31_START;
+
+ /* base address of BL3-1 source in TZDRAM */
+ src_base_tzdram = params_from_bl2->tzdram_base +
+ tegra186_get_cpu_reset_handler_size();
/*
* Setup the Memory controller to allow only secure accesses to
@@ -569,6 +581,15 @@
mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_TZDRAM_ADDR_HI, val);
/*
+ * save tzdram_addr_lo and ATF-size, this would be used in SC7-RF to
+ * generate SHA256.
+ */
+ mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV68_LO,
+ (uint32_t)src_base_tzdram);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV0_HI,
+ (uint32_t)src_len_in_bytes);
+
+ /*
* MCE propagates the security configuration values across the
* CCPLEX.
*/
diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
index 2000e53..a0879cc 100644
--- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -6,6 +6,7 @@
*/
#include <assert.h>
+#include <stdbool.h>
#include <string.h>
#include <arch.h>
@@ -19,9 +20,10 @@
#include <lib/psci/psci.h>
#include <plat/common/platform.h>
+#include <bpmp_ipc.h>
#include <mce.h>
+#include <security_engine.h>
#include <smmu.h>
-#include <stdbool.h>
#include <t18x_ari.h>
#include <tegra186_private.h>
#include <tegra_private.h>
@@ -280,8 +282,33 @@
uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
TEGRA186_STATE_ID_MASK;
uint64_t val;
+ uint64_t src_len_in_bytes = (uint64_t)(((uintptr_t)(&__BL31_END__) -
+ (uintptr_t)BL31_BASE));
+ int32_t ret;
if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+ val = params_from_bl2->tzdram_base +
+ tegra186_get_cpu_reset_handler_size();
+
+ /* Initialise communication channel with BPMP */
+ assert(tegra_bpmp_ipc_init() == 0);
+
+ /* Enable SE clock */
+ ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE);
+ if (ret != 0) {
+ ERROR("Failed to enable clock\n");
+ return ret;
+ }
+
+ /*
+ * Generate/save SHA256 of ATF during SC7 entry
+ */
+ if (tegra_se_save_sha256_hash(BL31_BASE,
+ (uint32_t)src_len_in_bytes) != 0) {
+ ERROR("Hash calculation failed. Reboot\n");
+ (void)tegra_soc_prepare_system_reset();
+ }
+
/*
* The TZRAM loses power when we enter system suspend. To
* allow graceful exit from system suspend, we need to copy
@@ -291,6 +318,12 @@
tegra186_get_cpu_reset_handler_size();
memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
(uintptr_t)BL31_END - (uintptr_t)BL31_BASE);
+
+ ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE);
+ if (ret != 0) {
+ ERROR("Failed to disable clock\n");
+ return ret;
+ }
}
return PSCI_E_SUCCESS;
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index 7028bfc..e5d0d01 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -106,6 +106,12 @@
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x1000000U, /* 64KB */
MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_HSP_DBELL_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_BPMP_IPC_TX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_BPMP_IPC_RX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
{0}
};
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
index 197e4c6..d79155f 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -30,10 +30,10 @@
PLATFORM_MAX_CPUS_PER_CLUSTER := 4
$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
-MAX_XLAT_TABLES := 24
+MAX_XLAT_TABLES := 25
$(eval $(call add_define,MAX_XLAT_TABLES))
-MAX_MMAP_REGIONS := 25
+MAX_MMAP_REGIONS := 27
$(eval $(call add_define,MAX_MMAP_REGIONS))
# platform files
@@ -42,6 +42,8 @@
BL31_SOURCES += drivers/ti/uart/aarch64/16550_console.S \
lib/cpus/aarch64/denver.S \
lib/cpus/aarch64/cortex_a57.S \
+ ${COMMON_DIR}/drivers/bpmp_ipc/intf.c \
+ ${COMMON_DIR}/drivers/bpmp_ipc/ivc.c \
${COMMON_DIR}/drivers/gpcdma/gpcdma.c \
${COMMON_DIR}/drivers/memctrl/memctrl_v2.c \
${COMMON_DIR}/drivers/smmu/smmu.c \
@@ -49,6 +51,7 @@
${SOC_DIR}/drivers/mce/ari.c \
${SOC_DIR}/drivers/mce/nvg.c \
${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \
+ $(SOC_DIR)/drivers/se/se.c \
${SOC_DIR}/plat_memctrl.c \
${SOC_DIR}/plat_psci_handlers.c \
${SOC_DIR}/plat_setup.c \
diff --git a/plat/nvidia/tegra/soc/t194/plat_memctrl.c b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
index 2208b85..d5f72b6 100644
--- a/plat/nvidia/tegra/soc/t194/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
@@ -138,7 +138,11 @@
MC_STREAMID_OVERRIDE_CFG_MIU2R,
MC_STREAMID_OVERRIDE_CFG_MIU2W,
MC_STREAMID_OVERRIDE_CFG_MIU3R,
- MC_STREAMID_OVERRIDE_CFG_MIU3W
+ MC_STREAMID_OVERRIDE_CFG_MIU3W,
+ MC_STREAMID_OVERRIDE_CFG_MIU4R,
+ MC_STREAMID_OVERRIDE_CFG_MIU4W,
+ MC_STREAMID_OVERRIDE_CFG_MIU5R,
+ MC_STREAMID_OVERRIDE_CFG_MIU5W
};
/*******************************************************************************
@@ -268,416 +272,13 @@
mc_make_sec_cfg(MIU2R, NON_SECURE, OVERRIDE, DISABLE),
mc_make_sec_cfg(MIU2W, NON_SECURE, OVERRIDE, DISABLE),
mc_make_sec_cfg(MIU3R, NON_SECURE, OVERRIDE, DISABLE),
- mc_make_sec_cfg(MIU3W, NON_SECURE, OVERRIDE, DISABLE)
+ mc_make_sec_cfg(MIU3W, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(MIU4R, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(MIU4W, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(MIU5R, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(MIU5W, NON_SECURE, OVERRIDE, DISABLE)
};
-/* To be called by common memctrl_v2.c */
-static void tegra194_memctrl_reconfig_mss_clients(void)
-{
- uint32_t reg_val, wdata_0, wdata_1, wdata_2;
-
- wdata_0 = MC_CLIENT_HOTRESET_CTRL0_HC_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL0_VIC_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL0_TSEC_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL0_SDMMC3A_FLUSH_ENB;
- if (tegra_platform_is_silicon()) {
- wdata_0 |= MC_CLIENT_HOTRESET_CTRL0_SDMMC1A_FLUSH_ENB;
- }
-
- tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0);
-
- /* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
- do {
- reg_val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS0);
- } while ((reg_val & wdata_0) != wdata_0);
-
- wdata_1 = MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_TSECB_FLUSH_ENB|
- MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_NVDISPLAY_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_VIFAL_FLUSH_ENB;
- if (tegra_platform_is_silicon()) {
- wdata_1 |= MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL1_RCE_FLUSH_ENB;
- }
- tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1);
- /* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
- do {
- reg_val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS1);
- } while ((reg_val & wdata_1) != wdata_1);
-
- wdata_2 = MC_CLIENT_HOTRESET_CTRL2_PCIE_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_AONDMA_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_BPMPDMA_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_SCEDMA_FLUSH_ENB;
- if (tegra_platform_is_silicon()) {
- wdata_2 |= MC_CLIENT_HOTRESET_CTRL2_RCEDMA_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_PCIE_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_PCIE5A_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_PCIE3A_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_PCIE3_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_PCIE0A_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_PCIE0A2_FLUSH_ENB |
- MC_CLIENT_HOTRESET_CTRL2_PCIE4A_FLUSH_ENB;
- }
- tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL2, wdata_2);
- /* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
- do {
- reg_val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS2);
- } while ((reg_val & wdata_2) != wdata_2);
-
- /*
- * Change MEMTYPE_OVERRIDE from SO_DEV -> PASSTHRU for boot and
- * strongly ordered MSS clients.
- *
- * MC clients with default SO_DEV override still enabled at TSA:
- * EQOSW, SATAW, XUSB_DEVW, XUSB_HOSTW, PCIe0w, PCIe1w, PCIe2w,
- * PCIe3w, PCIe4w and PCIe5w.
- */
- mc_set_tsa_w_passthrough(AONDMAW);
- mc_set_tsa_w_passthrough(AONW);
- mc_set_tsa_w_passthrough(APEDMAW);
- mc_set_tsa_w_passthrough(APEW);
- mc_set_tsa_w_passthrough(AXISW);
- mc_set_tsa_w_passthrough(BPMPDMAW);
- mc_set_tsa_w_passthrough(BPMPW);
- mc_set_tsa_w_passthrough(EQOSW);
- mc_set_tsa_w_passthrough(ETRW);
- mc_set_tsa_w_passthrough(RCEDMAW);
- mc_set_tsa_w_passthrough(RCEW);
- mc_set_tsa_w_passthrough(SCEDMAW);
- mc_set_tsa_w_passthrough(SCEW);
- mc_set_tsa_w_passthrough(SDMMCW);
- mc_set_tsa_w_passthrough(SDMMCWA);
- mc_set_tsa_w_passthrough(SDMMCWAB);
- mc_set_tsa_w_passthrough(SESWR);
- mc_set_tsa_w_passthrough(TSECSWR);
- mc_set_tsa_w_passthrough(TSECSWRB);
- mc_set_tsa_w_passthrough(UFSHCW);
- mc_set_tsa_w_passthrough(VICSWR);
- mc_set_tsa_w_passthrough(VIFALW);
- /*
- * set HUB2 as SO_DEV_HUBID
- */
- reg_val = tsa_read_32(PCIE0W);
- mc_set_tsa_hub2(reg_val, PCIE0W);
- reg_val = tsa_read_32(PCIE1W);
- mc_set_tsa_hub2(reg_val, PCIE1W);
- reg_val = tsa_read_32(PCIE2AW);
- mc_set_tsa_hub2(reg_val, PCIE2AW);
- reg_val = tsa_read_32(PCIE3W);
- mc_set_tsa_hub2(reg_val, PCIE3W);
- reg_val = tsa_read_32(PCIE4W);
- mc_set_tsa_hub2(reg_val, PCIE4W);
- reg_val = tsa_read_32(SATAW);
- mc_set_tsa_hub2(reg_val, SATAW);
- reg_val = tsa_read_32(XUSB_DEVW);
- mc_set_tsa_hub2(reg_val, XUSB_DEVW);
- reg_val = tsa_read_32(XUSB_HOSTW);
- mc_set_tsa_hub2(reg_val, XUSB_HOSTW);
-
- /*
- * Hw Bug: 200385660, 200394107
- * PCIE datapath hangs when there are more than 28 outstanding
- * requests on data backbone for x1 controller. This is seen
- * on third party PCIE IP, C1 - PCIE1W, C2 - PCIE2AW and C3 - PCIE3W.
- *
- * Setting Reorder depth limit, 16 which is < 28.
- */
- mc_set_tsa_depth_limit(REORDER_DEPTH_LIMIT, PCIE1W);
- mc_set_tsa_depth_limit(REORDER_DEPTH_LIMIT, PCIE2AW);
- mc_set_tsa_depth_limit(REORDER_DEPTH_LIMIT, PCIE3W);
-
- /* Ordered MC Clients on Xavier are EQOS, SATA, XUSB, PCIe1 and PCIe3
- * ISO clients(DISP, VI, EQOS) should never snoop caches and
- * don't need ROC/PCFIFO ordering.
- * ISO clients(EQOS) that need ordering should use PCFIFO ordering
- * and bypass ROC ordering by using FORCE_NON_COHERENT path.
- * FORCE_NON_COHERENT/FORCE_COHERENT config take precedence
- * over SMMU attributes.
- * Force all Normal memory transactions from ISO and non-ISO to be
- * non-coherent(bypass ROC, avoid cache snoop to avoid perf hit).
- * Force the SO_DEV transactions from ordered ISO clients(EQOS) to
- * non-coherent path and enable MC PCFIFO interlock for ordering.
- * Force the SO_DEV transactions from ordered non-ISO clients (PCIe,
- * XUSB, SATA) to coherent so that the transactions are
- * ordered by ROC.
- * PCFIFO ensure write ordering.
- * Read after Write ordering is maintained/enforced by MC clients.
- * Clients that need PCIe type write ordering must
- * go through ROC ordering.
- * Ordering enable for Read clients is not necessary.
- * R5's and A9 would get necessary ordering from AXI and
- * don't need ROC ordering enable:
- * - MMIO ordering is through dev mapping and MMIO
- * accesses bypass SMMU.
- * - Normal memory is accessed through SMMU and ordering is
- * ensured by client and AXI.
- * - Ack point for Normal memory is WCAM in MC.
- * - MMIO's can be early acked and AXI ensures dev memory ordering,
- * Client ensures read/write direction change ordering.
- * - See Bug 200312466 for more details.
- */
- mc_set_txn_override(AONDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(AONDMAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(AONR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(AONW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(APEDMAR, CGID_TAG_ADR, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(APEDMAW, CGID_TAG_ADR, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(APER, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(APEW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(AXISR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(AXISW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(BPMPDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(BPMPDMAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(BPMPR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(BPMPW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(EQOSR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(EQOSW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(ETRR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(ETRW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(HOST1XDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(MPCORER, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MPCOREW, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(NVDISPLAYR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(NVDISPLAYR1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(PCIE0R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE0R1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE0W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE1R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE1W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- if (tegra_platform_is_silicon()) {
- mc_set_txn_override(PCIE2AR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE2AW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE3R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE3W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE4R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE4W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE5R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE5W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(PCIE5R1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- }
- mc_set_txn_override(PTCR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(RCEDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(RCEDMAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(RCER, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(RCEW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SATAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(SATAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(SCEDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SCEDMAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SCER, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SCEW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SDMMCR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SDMMCRAB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SDMMCRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SDMMCW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SDMMCWA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(SDMMCWAB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- /*
- * TO DO: make SESRD/WR FORCE_COHERENT once SE+TZ with SMMU is enabled.
- */
- mc_set_txn_override(SESRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(SESWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(TSECSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(TSECSRDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(TSECSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(TSECSWRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(UFSHCR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(UFSHCW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(VICSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(VICSRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(VICSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(VIFALR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(VIFALW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(XUSB_DEVR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(XUSB_DEVW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(XUSB_HOSTR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(XUSB_HOSTW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
- mc_set_txn_override(AXIAPR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(AXIAPW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA0FALRDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA0FALWRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA0RDA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA0RDA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA0WRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA1FALRDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA1FALWRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA1RDA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA1RDA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(DLA1WRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(HDAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(HDAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
- mc_set_txn_override(ISPFALR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(ISPFALW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(ISPRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(ISPRA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(ISPWA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(ISPWB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVDEC1SRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVDEC1SRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVDEC1SWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVDECSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVDECSRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVDECSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVENC1SRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVENC1SRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVENC1SWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVENCSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVENCSRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVENCSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVJPGSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(NVJPGSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA0RDA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA0RDA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA0RDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA0RDB1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA0RDC, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA0WRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA0WRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA0WRC, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA1RDA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA1RDA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA1RDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA1RDB1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA1RDC, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA1WRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA1WRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(PVA1WRC, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
- mc_set_txn_override(VIW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-
- if (tegra_platform_is_silicon()) {
- mc_set_txn_override(MIU0R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU0W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU1R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU1W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU2R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU2W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU3R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU3W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU4R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU4W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU5R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU5W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU6R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU6W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU7R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- mc_set_txn_override(MIU7W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
- }
-
- /*
- * At this point, ordering can occur at SCF. So, remove PCFIFO's
- * control over ordering requests.
- *
- * Change PCFIFO_*_ORDERED_CLIENT from ORDERED -> UNORDERED for
- * boot and strongly ordered MSS clients
- */
- reg_val = MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL &
- mc_set_pcfifo_unordered_boot_so_mss(2, XUSB_HOSTW) &
- mc_set_pcfifo_unordered_boot_so_mss(2, TSECSWR);
- tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG2, reg_val);
-
- reg_val = MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL &
- mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCWA) &
- mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCW) &
- mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCWAB) &
- mc_set_pcfifo_unordered_boot_so_mss(3, VICSWR) &
- mc_set_pcfifo_unordered_boot_so_mss(3, APEW);
- tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG3, reg_val);
-
- reg_val = MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL &
- mc_set_pcfifo_unordered_boot_so_mss(4, SESWR) &
- mc_set_pcfifo_unordered_boot_so_mss(4, ETRW) &
- mc_set_pcfifo_unordered_boot_so_mss(4, TSECSWRB) &
- mc_set_pcfifo_unordered_boot_so_mss(4, AXISW) &
- mc_set_pcfifo_unordered_boot_so_mss(4, UFSHCW) &
- mc_set_pcfifo_unordered_boot_so_mss(4, BPMPW) &
- mc_set_pcfifo_unordered_boot_so_mss(4, BPMPDMAW) &
- mc_set_pcfifo_unordered_boot_so_mss(4, AONW) &
- mc_set_pcfifo_unordered_boot_so_mss(4, AONDMAW) &
- mc_set_pcfifo_unordered_boot_so_mss(4, SCEW) &
- mc_set_pcfifo_unordered_boot_so_mss(4, SCEDMAW);
- /* EQOSW has PCFIFO order enabled. */
- reg_val |= mc_set_pcfifo_unordered_boot_so_mss(4, EQOSW);
- tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG4, reg_val);
-
- reg_val = MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL &
- mc_set_pcfifo_unordered_boot_so_mss(5, APEDMAW) &
- mc_set_pcfifo_unordered_boot_so_mss(5, VIFALW);
- tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG5, reg_val);
-
- reg_val = MC_PCFIFO_CLIENT_CONFIG6_RESET_VAL &
- mc_set_pcfifo_unordered_boot_so_mss(6, RCEW) &
- mc_set_pcfifo_unordered_boot_so_mss(6, RCEDMAW) &
- mc_set_pcfifo_unordered_boot_so_mss(6, PCIE0W);
- tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG6, reg_val);
-
- reg_val = MC_PCFIFO_CLIENT_CONFIG7_RESET_VAL &
- mc_set_pcfifo_unordered_boot_so_mss(7, PCIE4W) &
- mc_set_pcfifo_unordered_boot_so_mss(7, PCIE5W);
- tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG7, reg_val);
-
- /* Set Order Id only for the clients having non zero order id */
- reg_val = mc_client_order_id(MC_CLIENT_ORDER_ID_9_RESET_VAL, 9, XUSB_HOSTW);
- tegra_mc_write_32(MC_CLIENT_ORDER_ID_9, reg_val);
-
- reg_val = mc_client_order_id(MC_CLIENT_ORDER_ID_27_RESET_VAL, 27, PCIE0W);
- tegra_mc_write_32(MC_CLIENT_ORDER_ID_27, reg_val);
-
- reg_val = mc_client_order_id(MC_CLIENT_ORDER_ID_28_RESET_VAL, 28, PCIE4W);
- reg_val = mc_client_order_id(reg_val, 28, PCIE5W);
- tegra_mc_write_32(MC_CLIENT_ORDER_ID_28, reg_val);
-
- /*
- * Set VC Id only for the clients having different reset values like
- * SDMMCRAB, SDMMCWAB, SESRD, SESWR, TSECSRD,TSECSRDB, TSECSWR and
- * TSECSWRB clients
- */
- reg_val = mc_hub_vc_id(MC_HUB_PC_VC_ID_0_RESET_VAL, 0, APB);
- tegra_mc_write_32(MC_HUB_PC_VC_ID_0, reg_val);
-
- /* SDMMCRAB and SDMMCWAB clients */
- reg_val = mc_hub_vc_id(MC_HUB_PC_VC_ID_2_RESET_VAL, 2, SD);
- tegra_mc_write_32(MC_HUB_PC_VC_ID_2, reg_val);
-
- reg_val = mc_hub_vc_id(MC_HUB_PC_VC_ID_4_RESET_VAL, 4, NIC);
- tegra_mc_write_32(MC_HUB_PC_VC_ID_4, reg_val);
-
- reg_val = mc_hub_vc_id(MC_HUB_PC_VC_ID_12_RESET_VAL, 12, UFSHCPC2);
- tegra_mc_write_32(MC_HUB_PC_VC_ID_12, reg_val);
-
- wdata_0 = MC_CLIENT_HOTRESET_CTRL0_RESET_VAL;
- tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0);
-
- wdata_1 = MC_CLIENT_HOTRESET_CTRL1_RESET_VAL;
- tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1);
-
- wdata_2 = MC_CLIENT_HOTRESET_CTRL2_RESET_VAL;
- tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL2, wdata_2);
-
- reg_val = MC_COALESCE_CTRL_COALESCER_ENABLE;
- tegra_mc_write_32(MC_COALESCE_CTRL, reg_val);
-
- /*
- * WAR to hardware bug 1953865: Coalescer must be disabled
- * for PVA0RDC and PVA1RDC interfaces.
- */
- reg_val = tegra_mc_read_32(MC_COALESCE_CONFIG_6_0);
- reg_val &= ~(MC_COALESCE_CONFIG_6_0_PVA0RDC_COALESCER_ENABLED |
- MC_COALESCE_CONFIG_6_0_PVA1RDC_COALESCER_ENABLED);
- tegra_mc_write_32(MC_COALESCE_CONFIG_6_0, reg_val);
-}
-
/*******************************************************************************
* Struct to hold the memory controller settings
******************************************************************************/
@@ -685,8 +286,7 @@
.streamid_override_cfg = tegra194_streamid_override_regs,
.num_streamid_override_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_override_regs),
.streamid_security_cfg = tegra194_streamid_sec_cfgs,
- .num_streamid_security_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_sec_cfgs),
- .reconfig_mss_clients = tegra194_memctrl_reconfig_mss_clients
+ .num_streamid_security_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_sec_cfgs)
};
/*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
index 352107d..c44b0fc 100644
--- a/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
+++ b/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,6 +15,9 @@
* PMC registers
*/
+/* SC7 context save scratch register for T210 */
+#define PMC_SCRATCH43_REG_OFFSET U(0x22C)
+
/* Secure scratch registers */
#define PMC_SECURE_SCRATCH4_OFFSET 0xC0U
#define PMC_SECURE_SCRATCH5_OFFSET 0xC4U
@@ -435,6 +438,7 @@
((x) & ((0x1U) << SE_TZRAM_OP_REQ_SHIFT))
/* SE Interrupt */
+#define SE_INT_ENABLE_REG_OFFSET U(0xC)
#define SE_INT_STATUS_REG_OFFSET 0x10U
#define SE_INT_OP_DONE_SHIFT 4
#define SE_INT_OP_DONE_CLEAR \
diff --git a/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c b/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
index d5e0491..635018d 100644
--- a/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
+++ b/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -20,8 +20,8 @@
* Constants and Macros
******************************************************************************/
-#define TIMEOUT_100MS 100U // Timeout in 100ms
-#define RNG_AES_KEY_INDEX 1
+#define TIMEOUT_100MS 100U /* Timeout in 100ms */
+#define RNG_AES_KEY_INDEX 1
/*******************************************************************************
* Data structure and global variables
@@ -68,14 +68,12 @@
* #--------------------------------#
*/
-/* Known pattern data */
-static const uint32_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE_WORDS] = {
+/* Known pattern data for T210 */
+static const uint8_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE] = {
/* 128 bit AES block */
- 0x0C0D0E0F,
- 0x08090A0B,
- 0x04050607,
- 0x00010203,
-};
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
/* SE input and output linked list buffers */
static tegra_se_io_lst_t se1_src_ll_buf;
@@ -85,6 +83,9 @@
static tegra_se_io_lst_t se2_src_ll_buf;
static tegra_se_io_lst_t se2_dst_ll_buf;
+/* SE1 context buffer, 132 blocks */
+static __aligned(64) uint8_t se1_ctx_buf[SE_CTX_DRBG_BUFER_SIZE];
+
/* SE1 security engine device handle */
static tegra_se_dev_t se_dev_1 = {
.se_num = 1,
@@ -97,10 +98,10 @@
/* Setup DST buffers for SE operations */
.dst_ll_buf = &se1_dst_ll_buf,
/* Setup context save destination */
- .ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE),
+ .ctx_save_buf = (uint32_t *)&se1_ctx_buf
};
-/* SE2 security engine device handle */
+/* SE2 security engine device handle (T210B01 only) */
static tegra_se_dev_t se_dev_2 = {
.se_num = 2,
/* Setup base address for se */
@@ -112,7 +113,7 @@
/* Setup DST buffers for SE operations */
.dst_ll_buf = &se2_dst_ll_buf,
/* Setup context save destination */
- .ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE + 0x1000),
+ .ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE + 0x1000)
};
static bool ecid_valid;
@@ -202,18 +203,6 @@
}
/*
- * Returns true if the SE engine is configured to perform SE context save in
- * hardware.
- */
-static inline bool tegra_se_atomic_save_enabled(const tegra_se_dev_t *se_dev)
-{
- uint32_t val;
-
- val = tegra_se_read_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET);
- return (SE_CTX_SAVE_AUTO_ENABLE(val) == SE_CTX_SAVE_AUTO_EN);
-}
-
-/*
* Wait for SE engine to be idle and clear pending interrupts before
* starting the next SE operation.
*/
@@ -223,6 +212,9 @@
uint32_t val = 0;
uint32_t timeout;
+ /* disable SE interrupt to prevent interrupt issued by SE operation */
+ tegra_se_write_32(se_dev, SE_INT_ENABLE_REG_OFFSET, 0U);
+
/* Wait for previous operation to finish */
val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET);
for (timeout = 0; (val != 0U) && (timeout < TIMEOUT_100MS); timeout++) {
@@ -629,19 +621,19 @@
{
uint32_t val = 0;
int ret = 0;
- /* First the modulus and then the exponent must be
+ /* For T210, First the modulus and then exponent must be
* encrypted and saved. This is repeated for SLOT 0
* and SLOT 1. Hence the order:
- * SLOT 0 exponent : RSA_KEY_INDEX : 0
* SLOT 0 modulus : RSA_KEY_INDEX : 1
- * SLOT 1 exponent : RSA_KEY_INDEX : 2
+ * SLOT 0 exponent : RSA_KEY_INDEX : 0
* SLOT 1 modulus : RSA_KEY_INDEX : 3
+ * SLOT 1 exponent : RSA_KEY_INDEX : 2
*/
const unsigned int key_index_mod[TEGRA_SE_RSA_KEYSLOT_COUNT][2] = {
/* RSA key slot 0 */
- {SE_RSA_KEY_INDEX_SLOT0_EXP, SE_RSA_KEY_INDEX_SLOT0_MOD},
+ {SE_RSA_KEY_INDEX_SLOT0_MOD, SE_RSA_KEY_INDEX_SLOT0_EXP},
/* RSA key slot 1 */
- {SE_RSA_KEY_INDEX_SLOT1_EXP, SE_RSA_KEY_INDEX_SLOT1_MOD},
+ {SE_RSA_KEY_INDEX_SLOT1_MOD, SE_RSA_KEY_INDEX_SLOT1_EXP},
};
se_dev->dst_ll_buf->last_buff_num = 0;
@@ -876,8 +868,8 @@
/* Write lp context buffer address into PMC scratch register */
if (se_dev->se_num == 1) {
- /* SE context address */
- mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SECURE_SCRATCH117_OFFSET,
+ /* SE context address, support T210 only */
+ mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SCRATCH43_REG_OFFSET,
((uint64_t)(se_dev->ctx_save_buf)));
} else if (se_dev->se_num == 2) {
/* SE2 & PKA1 context address */
@@ -909,7 +901,10 @@
/* Generate random SRK to initialize DRBG */
tegra_se_generate_srk(&se_dev_1);
- tegra_se_generate_srk(&se_dev_2);
+
+ if (tegra_chipid_is_t210_b01()) {
+ tegra_se_generate_srk(&se_dev_2);
+ }
/* determine if ECID is valid */
val = mmio_read_32(TEGRA_FUSE_BASE + FUSE_JTAG_SECUREID_VALID);
@@ -932,6 +927,18 @@
val &= ~ENTROPY_RESET_BIT;
mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_W, val);
+ if (!tegra_chipid_is_t210_b01()) {
+
+ /*
+ * T210 SE clock source is turned off in kernel, to simplify
+ * SE clock source setting, we switch SE clock source to
+ * CLK_M, SE_CLK_DIVISOR = 0. T210 B01 SE clock source is
+ * always on, so don't need this setting.
+ */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_RST_CTL_CLK_SRC_SE,
+ SE_CLK_SRC_CLK_M);
+ }
+
/* Enable SE clock */
val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V);
val |= SE_CLK_ENB_BIT;
@@ -975,43 +982,25 @@
tegra_se_enable_clocks();
- if (tegra_se_atomic_save_enabled(&se_dev_2) &&
- tegra_se_atomic_save_enabled(&se_dev_1)) {
- /* Atomic context save se2 and pka1 */
+ if (tegra_chipid_is_t210_b01()) {
+ /* It is T210 B01, Atomic context save se2 and pka1 */
INFO("%s: SE2/PKA1 atomic context save\n", __func__);
- if (ret == 0) {
- ret = tegra_se_context_save_atomic(&se_dev_2);
- }
-
- /* Atomic context save se */
- if (ret == 0) {
- INFO("%s: SE1 atomic context save\n", __func__);
- ret = tegra_se_context_save_atomic(&se_dev_1);
+ ret = tegra_se_context_save_atomic(&se_dev_2);
+ if (ret != 0) {
+ ERROR("%s: SE2 ctx save failed (%d)\n", __func__, ret);
}
- if (ret == 0) {
- INFO("%s: SE atomic context save done\n", __func__);
- }
- } else if (!tegra_se_atomic_save_enabled(&se_dev_2) &&
- !tegra_se_atomic_save_enabled(&se_dev_1)) {
- /* SW context save se2 and pka1 */
- INFO("%s: SE2/PKA1 legacy(SW) context save\n", __func__);
- if (ret == 0) {
- ret = tegra_se_context_save_sw(&se_dev_2);
- }
-
- /* SW context save se */
- if (ret == 0) {
- INFO("%s: SE1 legacy(SW) context save\n", __func__);
- ret = tegra_se_context_save_sw(&se_dev_1);
- }
-
- if (ret == 0) {
- INFO("%s: SE SW context save done\n", __func__);
+ ret = tegra_se_context_save_atomic(&se_dev_1);
+ if (ret != 0) {
+ ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret);
}
} else {
- ERROR("%s: One SE set for atomic CTX save, the other is not\n",
- __func__);
+ /* It is T210, SW context save se */
+ INFO("%s: SE1 legacy(SW) context save\n", __func__);
+ ret = tegra_se_context_save_sw(&se_dev_1);
+ if (ret != 0) {
+ ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret);
+ }
}
tegra_se_disable_clocks();
@@ -1080,5 +1069,8 @@
void tegra_se_resume(void)
{
tegra_se_warm_boot_resume(&se_dev_1);
- tegra_se_warm_boot_resume(&se_dev_2);
+
+ if (tegra_chipid_is_t210_b01()) {
+ tegra_se_warm_boot_resume(&se_dev_2);
+ }
}
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 832b8d6..f29e624 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -210,12 +210,9 @@
assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) ||
(stateid_afflvl1 == PSTATE_ID_SOC_POWERDN));
- if (tegra_chipid_is_t210_b01()) {
-
- /* Suspend se/se2 and pka1 */
- if (tegra_se_suspend() != 0) {
- ret = PSCI_E_INTERN_FAIL;
- }
+ /* Suspend se/se2 and pka1 for T210 B01 and se for T210 */
+ if (tegra_se_suspend() != 0) {
+ ret = PSCI_E_INTERN_FAIL;
}
} else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index 7afbe0d..933e925 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -174,9 +174,7 @@
}
/* Initialize security engine driver */
- if (tegra_chipid_is_t210_b01()) {
- tegra_se_init();
- }
+ tegra_se_init();
}
/* Secure IRQs for Tegra186 */
diff --git a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
index 7e0f5c1..7d26fe7 100644
--- a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -50,24 +51,32 @@
if (!ns)
SMC_RET1(handle, SMC_UNK);
- switch (smc_fid) {
- case TEGRA_SIP_PMC_COMMANDS:
-
+ if (smc_fid == TEGRA_SIP_PMC_COMMANDS) {
/* check the address is within PMC range and is 4byte aligned */
if ((x2 >= TEGRA_PMC_SIZE) || (x2 & 0x3))
return -EINVAL;
- /* pmc_secure_scratch registers are not accessible */
- if (((x2 >= PMC_SECURE_SCRATCH0) && (x2 <= PMC_SECURE_SCRATCH5)) ||
- ((x2 >= PMC_SECURE_SCRATCH6) && (x2 <= PMC_SECURE_SCRATCH7)) ||
- ((x2 >= PMC_SECURE_SCRATCH8) && (x2 <= PMC_SECURE_SCRATCH79)) ||
- ((x2 >= PMC_SECURE_SCRATCH80) && (x2 <= PMC_SECURE_SCRATCH119)))
- return -EFAULT;
-
+ switch (x2) {
+ /* Black listed PMC registers */
+ case PMC_SCRATCH1:
+ case PMC_SCRATCH31 ... PMC_SCRATCH33:
+ case PMC_SCRATCH40:
+ case PMC_SCRATCH42:
+ case PMC_SCRATCH43 ... PMC_SCRATCH48:
+ case PMC_SCRATCH50 ... PMC_SCRATCH51:
+ case PMC_SCRATCH56 ... PMC_SCRATCH57:
/* PMC secure-only registers are not accessible */
- if ((x2 == PMC_DPD_ENABLE_0) || (x2 == PMC_FUSE_CONTROL_0) ||
- (x2 == PMC_CRYPTO_OP_0))
+ case PMC_DPD_ENABLE_0:
+ case PMC_FUSE_CONTROL_0:
+ case PMC_CRYPTO_OP_0:
+ case PMC_TSC_MULT_0:
+ case PMC_STICKY_BIT:
+ ERROR("%s: error offset=0x%llx\n", __func__, x2);
return -EFAULT;
+ default:
+ /* Valid register */
+ break;
+ }
/* Perform PMC read/write */
if (x1 == PMC_READ) {
@@ -78,13 +87,9 @@
} else {
return -EINVAL;
}
-
- break;
-
- default:
+ } else {
ERROR("%s: unsupported function ID\n", __func__);
return -ENOTSUP;
}
-
return 0;
}
diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk
index 0d27bcd..ba827a0 100644
--- a/plat/nvidia/tegra/soc/t210/platform_t210.mk
+++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk
@@ -46,7 +46,6 @@
ERRATA_A57_826974 := 1
ERRATA_A57_826977 := 1
ERRATA_A57_828024 := 1
-ERRATA_A57_829520 := 1
ERRATA_A57_833471 := 1
# Enable workarounds for selected Cortex-A53 erratas.
diff --git a/plat/qemu/common/qemu_io_storage.c b/plat/qemu/common/qemu_io_storage.c
index 0e81cd1..1107e44 100644
--- a/plat/qemu/common/qemu_io_storage.c
+++ b/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 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 @@
#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 @@
(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 @@
(uintptr_t)&bl32_extra2_uuid_spec,
open_fip
},
+#endif
[BL33_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl33_uuid_spec,
@@ -271,7 +308,7 @@
/* 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 @@
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 @@
&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);
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index cce992f..ed4b748 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/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
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index bc10569..928d69a 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -128,6 +128,11 @@
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 @@
# 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
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index e89c835..77d1eaf 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -21,7 +21,7 @@
#include "uniphier.h"
#define UNIPHIER_ROM_REGION_BASE 0x00000000ULL
-#define UNIPHIER_ROM_REGION_SIZE 0x10000000ULL
+#define UNIPHIER_ROM_REGION_SIZE 0x04000000ULL
#define UNIPHIER_OCM_REGION_SIZE 0x00040000ULL
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index eff929e..19f736f 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -27,6 +27,8 @@
# Chain of trust.
ifeq (${COT},tbbr)
include src/tbbr/tbbr.mk
+else ifeq (${COT},dualroot)
+ include src/dualroot/cot.mk
else
$(error Unknown chain of trust ${COT})
endif
diff --git a/tools/cert_create/include/dualroot/cot.h b/tools/cert_create/include/dualroot/cot.h
new file mode 100644
index 0000000..5701206
--- /dev/null
+++ b/tools/cert_create/include/dualroot/cot.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DUALROOT_COT_H
+#define DUALROOT_COT_H
+
+/* Certificates. */
+enum {
+ /* Certificates owned by the silicon provider. */
+ TRUSTED_BOOT_FW_CERT,
+ TRUSTED_KEY_CERT,
+ SCP_FW_KEY_CERT,
+ SCP_FW_CONTENT_CERT,
+ SOC_FW_KEY_CERT,
+ SOC_FW_CONTENT_CERT,
+ TRUSTED_OS_FW_KEY_CERT,
+ TRUSTED_OS_FW_CONTENT_CERT,
+ FWU_CERT,
+
+ /* Certificates owned by the platform owner. */
+ NON_TRUSTED_FW_CONTENT_CERT,
+};
+
+/* Certificate extensions. */
+enum {
+ /* Extensions used in certificates owned by the silicon provider. */
+ TRUSTED_FW_NVCOUNTER_EXT,
+ TRUSTED_BOOT_FW_HASH_EXT,
+ TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
+ HW_CONFIG_HASH_EXT,
+ TRUSTED_WORLD_PK_EXT,
+ SCP_FW_CONTENT_CERT_PK_EXT,
+ SCP_FW_HASH_EXT,
+ SOC_FW_CONTENT_CERT_PK_EXT,
+ SOC_AP_FW_HASH_EXT,
+ SOC_FW_CONFIG_HASH_EXT,
+ TRUSTED_OS_FW_CONTENT_CERT_PK_EXT,
+ TRUSTED_OS_FW_HASH_EXT,
+ TRUSTED_OS_FW_EXTRA1_HASH_EXT,
+ TRUSTED_OS_FW_EXTRA2_HASH_EXT,
+ TRUSTED_OS_FW_CONFIG_HASH_EXT,
+ SCP_FWU_CFG_HASH_EXT,
+ AP_FWU_CFG_HASH_EXT,
+ FWU_HASH_EXT,
+
+ /* Extensions used in certificates owned by the platform owner. */
+ PROT_PK_EXT,
+ NON_TRUSTED_FW_NVCOUNTER_EXT,
+ NON_TRUSTED_FW_CONTENT_CERT_PK_EXT,
+ NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT,
+ NON_TRUSTED_FW_CONFIG_HASH_EXT,
+};
+
+/* Keys. */
+enum {
+ /* Keys owned by the silicon provider. */
+ ROT_KEY,
+ TRUSTED_WORLD_KEY,
+ SCP_FW_CONTENT_CERT_KEY,
+ SOC_FW_CONTENT_CERT_KEY,
+ TRUSTED_OS_FW_CONTENT_CERT_KEY,
+
+ /* Keys owned by the platform owner. */
+ PROT_KEY,
+};
+
+#endif /* DUALROOT_COT_H */
diff --git a/tools/cert_create/src/dualroot/cot.c b/tools/cert_create/src/dualroot/cot.c
new file mode 100644
index 0000000..8117ffc
--- /dev/null
+++ b/tools/cert_create/src/dualroot/cot.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dualroot_oid.h>
+
+#include "cert.h"
+#include "ext.h"
+#include "key.h"
+
+#include "dualroot/cot.h"
+
+/*
+ * Certificates used in the chain of trust.
+ *
+ * All certificates are self-signed so the issuer certificate field points to
+ * itself.
+ */
+static cert_t cot_certs[] = {
+ [TRUSTED_BOOT_FW_CERT] = {
+ .id = TRUSTED_BOOT_FW_CERT,
+ .opt = "tb-fw-cert",
+ .help_msg = "Trusted Boot FW Certificate (output file)",
+ .cn = "Trusted Boot FW Certificate",
+ .key = ROT_KEY,
+ .issuer = TRUSTED_BOOT_FW_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ TRUSTED_BOOT_FW_HASH_EXT,
+ TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
+ HW_CONFIG_HASH_EXT
+ },
+ .num_ext = 4
+ },
+
+ [TRUSTED_KEY_CERT] = {
+ .id = TRUSTED_KEY_CERT,
+ .opt = "trusted-key-cert",
+ .help_msg = "Trusted Key Certificate (output file)",
+ .cn = "Trusted Key Certificate",
+ .key = ROT_KEY,
+ .issuer = TRUSTED_KEY_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ TRUSTED_WORLD_PK_EXT,
+ },
+ .num_ext = 2
+ },
+
+ [SCP_FW_KEY_CERT] = {
+ .id = SCP_FW_KEY_CERT,
+ .opt = "scp-fw-key-cert",
+ .help_msg = "SCP Firmware Key Certificate (output file)",
+ .cn = "SCP Firmware Key Certificate",
+ .key = TRUSTED_WORLD_KEY,
+ .issuer = SCP_FW_KEY_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ SCP_FW_CONTENT_CERT_PK_EXT
+ },
+ .num_ext = 2
+ },
+
+ [SCP_FW_CONTENT_CERT] = {
+ .id = SCP_FW_CONTENT_CERT,
+ .opt = "scp-fw-cert",
+ .help_msg = "SCP Firmware Content Certificate (output file)",
+ .cn = "SCP Firmware Content Certificate",
+ .key = SCP_FW_CONTENT_CERT_KEY,
+ .issuer = SCP_FW_CONTENT_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ SCP_FW_HASH_EXT
+ },
+ .num_ext = 2
+ },
+
+ [SOC_FW_KEY_CERT] = {
+ .id = SOC_FW_KEY_CERT,
+ .opt = "soc-fw-key-cert",
+ .help_msg = "SoC Firmware Key Certificate (output file)",
+ .cn = "SoC Firmware Key Certificate",
+ .key = TRUSTED_WORLD_KEY,
+ .issuer = SOC_FW_KEY_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ SOC_FW_CONTENT_CERT_PK_EXT
+ },
+ .num_ext = 2
+ },
+
+ [SOC_FW_CONTENT_CERT] = {
+ .id = SOC_FW_CONTENT_CERT,
+ .opt = "soc-fw-cert",
+ .help_msg = "SoC Firmware Content Certificate (output file)",
+ .cn = "SoC Firmware Content Certificate",
+ .key = SOC_FW_CONTENT_CERT_KEY,
+ .issuer = SOC_FW_CONTENT_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ SOC_AP_FW_HASH_EXT,
+ SOC_FW_CONFIG_HASH_EXT,
+ },
+ .num_ext = 3
+ },
+
+ [TRUSTED_OS_FW_KEY_CERT] = {
+ .id = TRUSTED_OS_FW_KEY_CERT,
+ .opt = "tos-fw-key-cert",
+ .help_msg = "Trusted OS Firmware Key Certificate (output file)",
+ .cn = "Trusted OS Firmware Key Certificate",
+ .key = TRUSTED_WORLD_KEY,
+ .issuer = TRUSTED_OS_FW_KEY_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ TRUSTED_OS_FW_CONTENT_CERT_PK_EXT
+ },
+ .num_ext = 2
+ },
+
+ [TRUSTED_OS_FW_CONTENT_CERT] = {
+ .id = TRUSTED_OS_FW_CONTENT_CERT,
+ .opt = "tos-fw-cert",
+ .help_msg = "Trusted OS Firmware Content Certificate (output file)",
+ .cn = "Trusted OS Firmware Content Certificate",
+ .key = TRUSTED_OS_FW_CONTENT_CERT_KEY,
+ .issuer = TRUSTED_OS_FW_CONTENT_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ TRUSTED_OS_FW_HASH_EXT,
+ TRUSTED_OS_FW_EXTRA1_HASH_EXT,
+ TRUSTED_OS_FW_EXTRA2_HASH_EXT,
+ TRUSTED_OS_FW_CONFIG_HASH_EXT,
+ },
+ .num_ext = 5
+ },
+
+ [FWU_CERT] = {
+ .id = FWU_CERT,
+ .opt = "fwu-cert",
+ .help_msg = "Firmware Update Certificate (output file)",
+ .cn = "Firmware Update Certificate",
+ .key = ROT_KEY,
+ .issuer = FWU_CERT,
+ .ext = {
+ SCP_FWU_CFG_HASH_EXT,
+ AP_FWU_CFG_HASH_EXT,
+ FWU_HASH_EXT
+ },
+ .num_ext = 3
+ },
+
+ [NON_TRUSTED_FW_CONTENT_CERT] = {
+ .id = NON_TRUSTED_FW_CONTENT_CERT,
+ .opt = "nt-fw-cert",
+ .help_msg = "Non-Trusted Firmware Content Certificate (output file)",
+ .cn = "Non-Trusted Firmware Content Certificate",
+ .key = PROT_KEY,
+ .issuer = NON_TRUSTED_FW_CONTENT_CERT,
+ .ext = {
+ NON_TRUSTED_FW_NVCOUNTER_EXT,
+ NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT,
+ NON_TRUSTED_FW_CONFIG_HASH_EXT,
+ PROT_PK_EXT,
+ },
+ .num_ext = 4
+ },
+};
+
+REGISTER_COT(cot_certs);
+
+
+/* Certificate extensions. */
+static ext_t cot_ext[] = {
+ [TRUSTED_FW_NVCOUNTER_EXT] = {
+ .oid = TRUSTED_FW_NVCOUNTER_OID,
+ .opt = "tfw-nvctr",
+ .help_msg = "Trusted Firmware Non-Volatile counter value",
+ .sn = "TrustedWorldNVCounter",
+ .ln = "Trusted World Non-Volatile counter",
+ .asn1_type = V_ASN1_INTEGER,
+ .type = EXT_TYPE_NVCOUNTER,
+ .attr.nvctr_type = NVCTR_TYPE_TFW
+ },
+
+ [TRUSTED_BOOT_FW_HASH_EXT] = {
+ .oid = TRUSTED_BOOT_FW_HASH_OID,
+ .opt = "tb-fw",
+ .help_msg = "Trusted Boot Firmware image file",
+ .sn = "TrustedBootFirmwareHash",
+ .ln = "Trusted Boot Firmware hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH
+ },
+
+ [TRUSTED_BOOT_FW_CONFIG_HASH_EXT] = {
+ .oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID,
+ .opt = "tb-fw-config",
+ .help_msg = "Trusted Boot Firmware Config file",
+ .sn = "TrustedBootFirmwareConfigHash",
+ .ln = "Trusted Boot Firmware Config hash",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [HW_CONFIG_HASH_EXT] = {
+ .oid = HW_CONFIG_HASH_OID,
+ .opt = "hw-config",
+ .help_msg = "HW Config file",
+ .sn = "HWConfigHash",
+ .ln = "HW Config hash",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [TRUSTED_WORLD_PK_EXT] = {
+ .oid = TRUSTED_WORLD_PK_OID,
+ .sn = "TrustedWorldPublicKey",
+ .ln = "Trusted World Public Key",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_PKEY,
+ .attr.key = TRUSTED_WORLD_KEY
+ },
+
+ [SCP_FW_CONTENT_CERT_PK_EXT] = {
+ .oid = SCP_FW_CONTENT_CERT_PK_OID,
+ .sn = "SCPFirmwareContentCertPK",
+ .ln = "SCP Firmware content certificate public key",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_PKEY,
+ .attr.key = SCP_FW_CONTENT_CERT_KEY
+ },
+
+ [SCP_FW_HASH_EXT] = {
+ .oid = SCP_FW_HASH_OID,
+ .opt = "scp-fw",
+ .help_msg = "SCP Firmware image file",
+ .sn = "SCPFirmwareHash",
+ .ln = "SCP Firmware hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH
+ },
+
+ [SOC_FW_CONTENT_CERT_PK_EXT] = {
+ .oid = SOC_FW_CONTENT_CERT_PK_OID,
+ .sn = "SoCFirmwareContentCertPK",
+ .ln = "SoC Firmware content certificate public key",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_PKEY,
+ .attr.key = SOC_FW_CONTENT_CERT_KEY
+ },
+
+ [SOC_AP_FW_HASH_EXT] = {
+ .oid = SOC_AP_FW_HASH_OID,
+ .opt = "soc-fw",
+ .help_msg = "SoC AP Firmware image file",
+ .sn = "SoCAPFirmwareHash",
+ .ln = "SoC AP Firmware hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH
+ },
+
+ [SOC_FW_CONFIG_HASH_EXT] = {
+ .oid = SOC_FW_CONFIG_HASH_OID,
+ .opt = "soc-fw-config",
+ .help_msg = "SoC Firmware Config file",
+ .sn = "SocFirmwareConfigHash",
+ .ln = "SoC Firmware Config hash",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [TRUSTED_OS_FW_CONTENT_CERT_PK_EXT] = {
+ .oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID,
+ .sn = "TrustedOSFirmwareContentCertPK",
+ .ln = "Trusted OS Firmware content certificate public key",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_PKEY,
+ .attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
+ },
+
+ [TRUSTED_OS_FW_HASH_EXT] = {
+ .oid = TRUSTED_OS_FW_HASH_OID,
+ .opt = "tos-fw",
+ .help_msg = "Trusted OS image file",
+ .sn = "TrustedOSHash",
+ .ln = "Trusted OS hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH
+ },
+
+ [TRUSTED_OS_FW_EXTRA1_HASH_EXT] = {
+ .oid = TRUSTED_OS_FW_EXTRA1_HASH_OID,
+ .opt = "tos-fw-extra1",
+ .help_msg = "Trusted OS Extra1 image file",
+ .sn = "TrustedOSExtra1Hash",
+ .ln = "Trusted OS Extra1 hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [TRUSTED_OS_FW_EXTRA2_HASH_EXT] = {
+ .oid = TRUSTED_OS_FW_EXTRA2_HASH_OID,
+ .opt = "tos-fw-extra2",
+ .help_msg = "Trusted OS Extra2 image file",
+ .sn = "TrustedOSExtra2Hash",
+ .ln = "Trusted OS Extra2 hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [TRUSTED_OS_FW_CONFIG_HASH_EXT] = {
+ .oid = TRUSTED_OS_FW_CONFIG_HASH_OID,
+ .opt = "tos-fw-config",
+ .help_msg = "Trusted OS Firmware Config file",
+ .sn = "TrustedOSFirmwareConfigHash",
+ .ln = "Trusted OS Firmware Config hash",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [SCP_FWU_CFG_HASH_EXT] = {
+ .oid = SCP_FWU_CFG_HASH_OID,
+ .opt = "scp-fwu-cfg",
+ .help_msg = "SCP Firmware Update Config image file",
+ .sn = "SCPFWUpdateConfig",
+ .ln = "SCP Firmware Update Config hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [AP_FWU_CFG_HASH_EXT] = {
+ .oid = AP_FWU_CFG_HASH_OID,
+ .opt = "ap-fwu-cfg",
+ .help_msg = "AP Firmware Update Config image file",
+ .sn = "APFWUpdateConfig",
+ .ln = "AP Firmware Update Config hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [FWU_HASH_EXT] = {
+ .oid = FWU_HASH_OID,
+ .opt = "fwu",
+ .help_msg = "Firmware Updater image file",
+ .sn = "FWUpdaterHash",
+ .ln = "Firmware Updater hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
+ [PROT_PK_EXT] = {
+ .oid = PROT_PK_OID,
+ .sn = "PlatformRoTKey",
+ .ln = "Platform Root of Trust Public Key",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_PKEY,
+ .attr.key = PROT_KEY
+ },
+
+ [NON_TRUSTED_FW_NVCOUNTER_EXT] = {
+ .oid = NON_TRUSTED_FW_NVCOUNTER_OID,
+ .opt = "ntfw-nvctr",
+ .help_msg = "Non-Trusted Firmware Non-Volatile counter value",
+ .sn = "NormalWorldNVCounter",
+ .ln = "Non-Trusted Firmware Non-Volatile counter",
+ .asn1_type = V_ASN1_INTEGER,
+ .type = EXT_TYPE_NVCOUNTER,
+ .attr.nvctr_type = NVCTR_TYPE_NTFW
+ },
+
+ [NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = {
+ .oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID,
+ .opt = "nt-fw",
+ .help_msg = "Non-Trusted World Bootloader image file",
+ .sn = "NonTrustedWorldBootloaderHash",
+ .ln = "Non-Trusted World hash (SHA256)",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH
+ },
+
+ [NON_TRUSTED_FW_CONFIG_HASH_EXT] = {
+ .oid = NON_TRUSTED_FW_CONFIG_HASH_OID,
+ .opt = "nt-fw-config",
+ .help_msg = "Non Trusted OS Firmware Config file",
+ .sn = "NonTrustedOSFirmwareConfigHash",
+ .ln = "Non-Trusted OS Firmware Config hash",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+};
+
+REGISTER_EXTENSIONS(cot_ext);
+
+
+/* Keys used to establish the chain of trust. */
+static key_t cot_keys[] = {
+ [ROT_KEY] = {
+ .id = ROT_KEY,
+ .opt = "rot-key",
+ .help_msg = "Root Of Trust key (input/output file)",
+ .desc = "Root Of Trust key"
+ },
+
+ [TRUSTED_WORLD_KEY] = {
+ .id = TRUSTED_WORLD_KEY,
+ .opt = "trusted-world-key",
+ .help_msg = "Trusted World key (input/output file)",
+ .desc = "Trusted World key"
+ },
+
+ [SCP_FW_CONTENT_CERT_KEY] = {
+ .id = SCP_FW_CONTENT_CERT_KEY,
+ .opt = "scp-fw-key",
+ .help_msg = "SCP Firmware Content Certificate key (input/output file)",
+ .desc = "SCP Firmware Content Certificate key"
+ },
+
+ [SOC_FW_CONTENT_CERT_KEY] = {
+ .id = SOC_FW_CONTENT_CERT_KEY,
+ .opt = "soc-fw-key",
+ .help_msg = "SoC Firmware Content Certificate key (input/output file)",
+ .desc = "SoC Firmware Content Certificate key"
+ },
+
+ [TRUSTED_OS_FW_CONTENT_CERT_KEY] = {
+ .id = TRUSTED_OS_FW_CONTENT_CERT_KEY,
+ .opt = "tos-fw-key",
+ .help_msg = "Trusted OS Firmware Content Certificate key (input/output file)",
+ .desc = "Trusted OS Firmware Content Certificate key"
+ },
+
+ [PROT_KEY] = {
+ .id = PROT_KEY,
+ .opt = "prot-key",
+ .help_msg = "Platform Root of Trust key",
+ .desc = "Platform Root of Trust key"
+ },
+};
+
+REGISTER_KEYS(cot_keys);
diff --git a/tools/cert_create/src/dualroot/cot.mk b/tools/cert_create/src/dualroot/cot.mk
new file mode 100644
index 0000000..a572484
--- /dev/null
+++ b/tools/cert_create/src/dualroot/cot.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_MSG := Dual root of trust
+PLAT_INCLUDE := ../../include/tools_share
+
+OBJECTS += src/dualroot/cot.o
diff --git a/tools/encrypt_fw/Makefile b/tools/encrypt_fw/Makefile
new file mode 100644
index 0000000..cb81d0b
--- /dev/null
+++ b/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})
diff --git a/tools/encrypt_fw/include/cmd_opt.h b/tools/encrypt_fw/include/cmd_opt.h
new file mode 100644
index 0000000..bd7d31f
--- /dev/null
+++ b/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 */
diff --git a/tools/encrypt_fw/include/debug.h b/tools/encrypt_fw/include/debug.h
new file mode 100644
index 0000000..ee8f1f5
--- /dev/null
+++ b/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 */
diff --git a/tools/encrypt_fw/include/encrypt.h b/tools/encrypt_fw/include/encrypt.h
new file mode 100644
index 0000000..25d3011
--- /dev/null
+++ b/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 */
diff --git a/tools/encrypt_fw/src/cmd_opt.c b/tools/encrypt_fw/src/cmd_opt.c
new file mode 100644
index 0000000..64180d1
--- /dev/null
+++ b/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];
+}
diff --git a/tools/encrypt_fw/src/encrypt.c b/tools/encrypt_fw/src/encrypt.c
new file mode 100644
index 0000000..18a514c
--- /dev/null
+++ b/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;
+ }
+}
diff --git a/tools/encrypt_fw/src/main.c b/tools/encrypt_fw/src/main.c
new file mode 100644
index 0000000..39b7af7
--- /dev/null
+++ b/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;
+}