aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components/service/crypto/client/cpp/component.cmake22
-rw-r--r--components/service/crypto/client/cpp/config_mbed_crypto.h1955
-rw-r--r--components/service/crypto/client/cpp/crypto_client.cpp806
-rw-r--r--components/service/crypto/client/cpp/crypto_client.h76
-rw-r--r--components/service/crypto/client/test/component.cmake14
-rw-r--r--components/service/crypto/client/test/mock/component.cmake14
-rw-r--r--components/service/crypto/client/test/mock/mock_crypto_client.cpp114
-rw-r--r--components/service/crypto/client/test/mock/mock_crypto_client.h49
-rw-r--r--components/service/crypto/client/test/standalone/component.cmake14
-rw-r--r--components/service/crypto/client/test/standalone/standalone_crypto_client.cpp138
-rw-r--r--components/service/crypto/client/test/standalone/standalone_crypto_client.h52
-rw-r--r--components/service/crypto/client/test/test_crypto_client.cpp105
-rw-r--r--components/service/crypto/client/test/test_crypto_client.h88
-rw-r--r--components/service/crypto/provider/mbedcrypto/component.cmake31
-rw-r--r--components/service/crypto/provider/mbedcrypto/config_mbed_crypto.h1954
-rw-r--r--components/service/crypto/provider/mbedcrypto/crypto_provider.c605
-rw-r--r--components/service/crypto/provider/mbedcrypto/crypto_provider.h46
-rw-r--r--components/service/crypto/provider/mbedcrypto/entropy_source/mock/component.cmake13
-rw-r--r--components/service/crypto/provider/mbedcrypto/entropy_source/mock/mock_entropy_source.c25
-rw-r--r--components/service/crypto/provider/serializer/crypto_provider_serializer.h113
-rw-r--r--components/service/crypto/provider/serializer/protobuf/component.cmake20
-rw-r--r--components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c591
-rw-r--r--components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h25
-rw-r--r--components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.c25
-rw-r--r--components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.h17
-rw-r--r--components/service/crypto/test/service/component.cmake15
-rw-r--r--components/service/crypto/test/service/crypto_service_limit_tests.cpp170
-rw-r--r--components/service/crypto/test/service/crypto_service_op_tests.cpp383
-rw-r--r--components/service/crypto/test/unit/component.cmake16
-rw-r--r--components/service/crypto/test/unit/crypto_fault_tests.cpp91
-rw-r--r--components/service/crypto/test/unit/crypto_msg_encode_decode.cpp270
-rw-r--r--components/service/crypto/test/unit/poc_crypto_ops.cpp110
-rw-r--r--external/mbed-crypto/mbedcrypto.cmake93
-rw-r--r--protocols/service/crypto/packed-c/component.cmake14
-rw-r--r--protocols/service/crypto/packed-c/opcodes.h26
-rw-r--r--protocols/service/crypto/protobuf/asymmetric_decrypt.proto18
-rw-r--r--protocols/service/crypto/protobuf/asymmetric_encrypt.proto18
-rw-r--r--protocols/service/crypto/protobuf/close_key.proto11
-rw-r--r--protocols/service/crypto/protobuf/component.cmake26
-rw-r--r--protocols/service/crypto/protobuf/destroy_key.proto13
-rw-r--r--protocols/service/crypto/protobuf/export_key.proto15
-rw-r--r--protocols/service/crypto/protobuf/export_public_key.proto15
-rw-r--r--protocols/service/crypto/protobuf/generate_key.proto17
-rw-r--r--protocols/service/crypto/protobuf/generate_random.proto15
-rw-r--r--protocols/service/crypto/protobuf/import_key.proto18
-rw-r--r--protocols/service/crypto/protobuf/key_attributes.proto130
-rw-r--r--protocols/service/crypto/protobuf/opcodes.proto23
-rw-r--r--protocols/service/crypto/protobuf/open_key.proto15
-rw-r--r--protocols/service/crypto/protobuf/sign_hash.proto17
-rw-r--r--protocols/service/crypto/protobuf/verify_hash.proto16
50 files changed, 8467 insertions, 0 deletions
diff --git a/components/service/crypto/client/cpp/component.cmake b/components/service/crypto/client/cpp/component.cmake
new file mode 100644
index 000000000..18b83e9bd
--- /dev/null
+++ b/components/service/crypto/client/cpp/component.cmake
@@ -0,0 +1,22 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/crypto_client.cpp"
+ )
+
+# The crypto client presents the PSA Crypto API and hence has a dependency on mbedcrypto for functions
+# related to setting key attributes. A minimal configuration is provided to allow a minimal library
+# to be built. This configuration may be overridden by other components that have their own
+# dependency on mbedctupto.
+set(MBEDCRYPTO_CONFIG_FILE
+ "${CMAKE_CURRENT_LIST_DIR}/config_mbed_crypto.h"
+ CACHE STRING "Configuration file for mbedcrypto")
+
diff --git a/components/service/crypto/client/cpp/config_mbed_crypto.h b/components/service/crypto/client/cpp/config_mbed_crypto.h
new file mode 100644
index 000000000..d3c2a7333
--- /dev/null
+++ b/components/service/crypto/client/cpp/config_mbed_crypto.h
@@ -0,0 +1,1955 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CONFIG_MBED_CRYPTO_H
+#define CONFIG_MBED_CRYPTO_H
+
+/**
+ * Defines the configuration to use when the crypto_client
+ * component is used in a deployment.
+ */
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ * library/aria.c
+ * library/timing.c
+ * include/mbedtls/bn_mul.h
+ *
+ * Required by:
+ * MBEDTLS_AESNI_C
+ * MBEDTLS_PADLOCK_C
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define MBEDTLS_HAVE_ASM
+
+/**
+ * \def MBEDTLS_NO_UDBL_DIVISION
+ *
+ * The platform lacks support for double-width integer division (64-bit
+ * division on a 32-bit platform, 128-bit division on a 64-bit platform).
+ *
+ * Used in:
+ * include/mbedtls/bignum.h
+ * library/bignum.c
+ *
+ * The bignum code uses double-width division to speed up some operations.
+ * Double-width division is often implemented in software that needs to
+ * be linked with the program. The presence of a double-width integer
+ * type is usually detected automatically through preprocessor macros,
+ * but the automatic detection cannot know whether the code needs to
+ * and can be linked with an implementation of division for that type.
+ * By default division is assumed to be usable if the type is present.
+ * Uncomment this option to prevent the use of double-width division.
+ *
+ * Note that division for the native integer type is always required.
+ * Furthermore, a 64-bit type is always required even on a 32-bit
+ * platform, but it need not support multiplication or division. In some
+ * cases it is also desirable to disable some double-width operations. For
+ * example, if double-width division is implemented in software, disabling
+ * it can reduce code size in some embedded targets.
+ */
+#define MBEDTLS_NO_UDBL_DIVISION
+
+/**
+ * \def MBEDTLS_NO_64BIT_MULTIPLICATION
+ *
+ * The platform lacks support for 32x32 -> 64-bit multiplication.
+ *
+ * Used in:
+ * library/poly1305.c
+ *
+ * Some parts of the library may use multiplication of two unsigned 32-bit
+ * operands with a 64-bit result in order to speed up computations. On some
+ * platforms, this is not available in hardware and has to be implemented in
+ * software, usually in a library provided by the toolchain.
+ *
+ * Sometimes it is not desirable to have to link to that library. This option
+ * removes the dependency of that library on platforms that lack a hardware
+ * 64-bit multiplier by embedding a software implementation in Mbed TLS.
+ *
+ * Note that depending on the compiler, this may decrease performance compared
+ * to using the library function provided by the toolchain.
+ */
+//#define MBEDTLS_NO_64BIT_MULTIPLICATION
+
+/**
+ * \def MBEDTLS_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define MBEDTLS_HAVE_SSE2
+
+/**
+ * \def MBEDTLS_HAVE_TIME
+ *
+ * System has time.h and time().
+ * The time does not need to be correct, only time differences are used,
+ * by contrast with MBEDTLS_HAVE_TIME_DATE
+ *
+ * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT,
+ * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and
+ * MBEDTLS_PLATFORM_STD_TIME.
+ *
+ * Comment if your system does not support time functions
+ */
+//#define MBEDTLS_HAVE_TIME
+
+/**
+ * \def MBEDTLS_HAVE_TIME_DATE
+ *
+ * System has time.h, time(), and an implementation for
+ * mbedtls_platform_gmtime_r() (see below).
+ * The time needs to be correct (not necessarily very accurate, but at least
+ * the date should be correct). This is used to verify the validity period of
+ * X.509 certificates.
+ *
+ * Comment if your system does not have a correct clock.
+ *
+ * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that
+ * behaves similarly to the gmtime_r() function from the C standard. Refer to
+ * the documentation for mbedtls_platform_gmtime_r() for more information.
+ *
+ * \note It is possible to configure an implementation for
+ * mbedtls_platform_gmtime_r() at compile-time by using the macro
+ * MBEDTLS_PLATFORM_GMTIME_R_ALT.
+ */
+//#define MBEDTLS_HAVE_TIME_DATE
+
+/**
+ * \def MBEDTLS_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default mbed TLS uses the system-provided calloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY without the
+ * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
+ * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY and specifying
+ * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define MBEDTLS_PLATFORM_MEMORY
+
+/**
+ * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. calloc() to
+ * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF)
+ *
+ * This makes sure there are no linking errors on platforms that do not support
+ * these functions. You will HAVE to provide alternatives, either at runtime
+ * via the platform_set_xxx() functions or at compile time by setting
+ * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a
+ * MBEDTLS_PLATFORM_XXX_MACRO.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def MBEDTLS_PLATFORM_EXIT_ALT
+ *
+ * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the
+ * function in the platform abstraction layer.
+ *
+ * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will
+ * provide a function "mbedtls_platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require MBEDTLS_PLATFORM_C to be defined!
+ *
+ * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows;
+ * it will be enabled automatically by check_config.h
+ *
+ * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as
+ * MBEDTLS_PLATFORM_XXX_MACRO!
+ *
+ * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define MBEDTLS_PLATFORM_EXIT_ALT
+//#define MBEDTLS_PLATFORM_TIME_ALT
+//#define MBEDTLS_PLATFORM_FPRINTF_ALT
+//#define MBEDTLS_PLATFORM_PRINTF_ALT
+//#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
+//#define MBEDTLS_PLATFORM_NV_SEED_ALT
+//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT
+
+/**
+ * \def MBEDTLS_DEPRECATED_WARNING
+ *
+ * Mark deprecated functions so that they generate a warning if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * This only works with GCC and Clang. With other compilers, you may want to
+ * use MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Uncomment to get warnings on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_WARNING
+
+/**
+ * \def MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Remove deprecated functions so that they generate an error if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * Uncomment to get errors on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_REMOVED
+
+/**
+ * \def MBEDTLS_CHECK_PARAMS
+ *
+ * This configuration option controls whether the library validates more of
+ * the parameters passed to it.
+ *
+ * When this flag is not defined, the library only attempts to validate an
+ * input parameter if: (1) they may come from the outside world (such as the
+ * network, the filesystem, etc.) or (2) not validating them could result in
+ * internal memory errors such as overflowing a buffer controlled by the
+ * library. On the other hand, it doesn't attempt to validate parameters whose
+ * values are fully controlled by the application (such as pointers).
+ *
+ * When this flag is defined, the library additionally attempts to validate
+ * parameters that are fully controlled by the application, and should always
+ * be valid if the application code is fully correct and trusted.
+ *
+ * For example, when a function accepts as input a pointer to a buffer that may
+ * contain untrusted data, and its documentation mentions that this pointer
+ * must not be NULL:
+ * - the pointer is checked to be non-NULL only if this option is enabled
+ * - the content of the buffer is always validated
+ *
+ * When this flag is defined, if a library function receives a parameter that
+ * is invalid, it will:
+ * - invoke the macro MBEDTLS_PARAM_FAILED() which by default expands to a
+ * call to the function mbedtls_param_failed()
+ * - immediately return (with a specific error code unless the function
+ * returns void and can't communicate an error).
+ *
+ * When defining this flag, you also need to:
+ * - either provide a definition of the function mbedtls_param_failed() in
+ * your application (see platform_util.h for its prototype) as the library
+ * calls that function, but does not provide a default definition for it,
+ * - or provide a different definition of the macro MBEDTLS_PARAM_FAILED()
+ * below if the above mechanism is not flexible enough to suit your needs.
+ * See the documentation of this macro later in this file.
+ *
+ * Uncomment to enable validation of application-controlled parameters.
+ */
+//#define MBEDTLS_CHECK_PARAMS
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: mbed TLS feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_TIMING_ALT
+ *
+ * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(),
+ * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay()
+ *
+ * Only works if you have MBEDTLS_TIMING_C enabled.
+ *
+ * You will need to provide a header "timing_alt.h" and an implementation at
+ * compile time.
+ */
+//#define MBEDTLS_TIMING_ALT
+
+/**
+ * \def MBEDTLS_AES_ALT
+ *
+ * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your
+ * alternate core implementation of a symmetric crypto, an arithmetic or hash
+ * module (e.g. platform specific assembly optimized implementations). Keep
+ * in mind that the function prototypes should remain the same.
+ *
+ * This replaces the whole module. If you only want to replace one of the
+ * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer
+ * provide the "struct mbedtls_aes_context" definition and omit the base
+ * function declarations and implementations. "aes_alt.h" will be included from
+ * "aes.h" to include the new function definitions.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * module.
+ *
+ * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their
+ * use constitutes a security risk. If possible, we recommend
+ * avoiding dependencies on them, and considering stronger message
+ * digests and ciphers instead.
+ *
+ */
+//#define MBEDTLS_AES_ALT
+//#define MBEDTLS_ARC4_ALT
+//#define MBEDTLS_ARIA_ALT
+//#define MBEDTLS_BLOWFISH_ALT
+//#define MBEDTLS_CAMELLIA_ALT
+//#define MBEDTLS_CCM_ALT
+//#define MBEDTLS_CHACHA20_ALT
+//#define MBEDTLS_CHACHAPOLY_ALT
+//#define MBEDTLS_CMAC_ALT
+//#define MBEDTLS_DES_ALT
+//#define MBEDTLS_DHM_ALT
+//#define MBEDTLS_ECJPAKE_ALT
+//#define MBEDTLS_GCM_ALT
+//#define MBEDTLS_NIST_KW_ALT
+//#define MBEDTLS_MD2_ALT
+//#define MBEDTLS_MD4_ALT
+//#define MBEDTLS_MD5_ALT
+//#define MBEDTLS_POLY1305_ALT
+//#define MBEDTLS_RIPEMD160_ALT
+//#define MBEDTLS_RSA_ALT
+//#define MBEDTLS_SHA1_ALT
+//#define MBEDTLS_SHA256_ALT
+//#define MBEDTLS_SHA512_ALT
+//#define MBEDTLS_XTEA_ALT
+
+/*
+ * When replacing the elliptic curve module, pleace consider, that it is
+ * implemented with two .c files:
+ * - ecp.c
+ * - ecp_curves.c
+ * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT
+ * macros as described above. The only difference is that you have to make sure
+ * that you provide functionality for both .c files.
+ */
+//#define MBEDTLS_ECP_ALT
+
+/**
+ * \def MBEDTLS_MD2_PROCESS_ALT
+ *
+ * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you
+ * alternate core implementation of symmetric crypto or hash function. Keep in
+ * mind that function prototypes should remain the same.
+ *
+ * This replaces only one function. The header file from mbed TLS is still
+ * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will
+ * no longer provide the mbedtls_sha1_process() function, but it will still provide
+ * the other function (using your mbedtls_sha1_process() function) and the definition
+ * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible
+ * with this definition.
+ *
+ * \note Because of a signature change, the core AES encryption and decryption routines are
+ * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt,
+ * respectively. When setting up alternative implementations, these functions should
+ * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt
+ * must stay untouched.
+ *
+ * \note If you use the AES_xxx_ALT macros, then is is recommended to also set
+ * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES
+ * tables.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ *
+ * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use
+ * constitutes a security risk. If possible, we recommend avoiding
+ * dependencies on them, and considering stronger message digests
+ * and ciphers instead.
+ *
+ */
+//#define MBEDTLS_MD2_PROCESS_ALT
+//#define MBEDTLS_MD4_PROCESS_ALT
+//#define MBEDTLS_MD5_PROCESS_ALT
+//#define MBEDTLS_RIPEMD160_PROCESS_ALT
+//#define MBEDTLS_SHA1_PROCESS_ALT
+//#define MBEDTLS_SHA256_PROCESS_ALT
+//#define MBEDTLS_SHA512_PROCESS_ALT
+//#define MBEDTLS_DES_SETKEY_ALT
+//#define MBEDTLS_DES_CRYPT_ECB_ALT
+//#define MBEDTLS_DES3_CRYPT_ECB_ALT
+//#define MBEDTLS_AES_SETKEY_ENC_ALT
+//#define MBEDTLS_AES_SETKEY_DEC_ALT
+//#define MBEDTLS_AES_ENCRYPT_ALT
+//#define MBEDTLS_AES_DECRYPT_ALT
+//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT
+//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT
+//#define MBEDTLS_ECDSA_VERIFY_ALT
+//#define MBEDTLS_ECDSA_SIGN_ALT
+//#define MBEDTLS_ECDSA_GENKEY_ALT
+
+/**
+ * \def MBEDTLS_ECP_INTERNAL_ALT
+ *
+ * Expose a part of the internal interface of the Elliptic Curve Point module.
+ *
+ * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your
+ * alternative core implementation of elliptic curve arithmetic. Keep in mind
+ * that function prototypes should remain the same.
+ *
+ * This partially replaces one function. The header file from mbed TLS is still
+ * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation
+ * is still present and it is used for group structures not supported by the
+ * alternative.
+ *
+ * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT
+ * and implementing the following functions:
+ * unsigned char mbedtls_internal_ecp_grp_capable(
+ * const mbedtls_ecp_group *grp )
+ * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )
+ * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp )
+ * The mbedtls_internal_ecp_grp_capable function should return 1 if the
+ * replacement functions implement arithmetic for the given group and 0
+ * otherwise.
+ * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are
+ * called before and after each point operation and provide an opportunity to
+ * implement optimized set up and tear down instructions.
+ *
+ * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and
+ * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac
+ * function, but will use your mbedtls_internal_ecp_double_jac if the group is
+ * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when
+ * receives it as an argument). If the group is not supported then the original
+ * implementation is used. The other functions and the definition of
+ * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your
+ * implementation of mbedtls_internal_ecp_double_jac and
+ * mbedtls_internal_ecp_grp_capable must be compatible with this definition.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ */
+/* Required for all the functions in this section */
+//#define MBEDTLS_ECP_INTERNAL_ALT
+/* Support for Weierstrass curves with Jacobi representation */
+//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
+//#define MBEDTLS_ECP_ADD_MIXED_ALT
+//#define MBEDTLS_ECP_DOUBLE_JAC_ALT
+//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
+//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
+/* Support for curves with Montgomery arithmetic */
+//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT
+//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT
+//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT
+
+/**
+ * \def MBEDTLS_TEST_NULL_ENTROPY
+ *
+ * Enables testing and use of mbed TLS without any configured entropy sources.
+ * This permits use of the library on platforms before an entropy source has
+ * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the
+ * MBEDTLS_ENTROPY_NV_SEED switches).
+ *
+ * WARNING! This switch MUST be disabled in production builds, and is suitable
+ * only for development.
+ * Enabling the switch negates any security provided by the library.
+ *
+ * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ */
+#define MBEDTLS_TEST_NULL_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_HARDWARE_ALT
+ *
+ * Uncomment this macro to let mbed TLS use your own implementation of a
+ * hardware entropy collector.
+ *
+ * Your function must be called \c mbedtls_hardware_poll(), have the same
+ * prototype as declared in entropy_poll.h, and accept NULL as first argument.
+ *
+ * Uncomment to use your own hardware entropy collector.
+ */
+//#define MBEDTLS_ENTROPY_HARDWARE_ALT
+
+/**
+ * \def MBEDTLS_AES_ROM_TABLES
+ *
+ * Use precomputed AES tables stored in ROM.
+ *
+ * Uncomment this macro to use precomputed AES tables stored in ROM.
+ * Comment this macro to generate AES tables in RAM at runtime.
+ *
+ * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb
+ * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the
+ * initialization time before the first AES operation can be performed.
+ * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c
+ * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded
+ * performance if ROM access is slower than RAM access.
+ *
+ * This option is independent of \c MBEDTLS_AES_FEWER_TABLES.
+ *
+ */
+//#define MBEDTLS_AES_ROM_TABLES
+
+/**
+ * \def MBEDTLS_AES_FEWER_TABLES
+ *
+ * Use less ROM/RAM for AES tables.
+ *
+ * Uncommenting this macro omits 75% of the AES tables from
+ * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES)
+ * by computing their values on the fly during operations
+ * (the tables are entry-wise rotations of one another).
+ *
+ * Tradeoff: Uncommenting this reduces the RAM / ROM footprint
+ * by ~6kb but at the cost of more arithmetic operations during
+ * runtime. Specifically, one has to compare 4 accesses within
+ * different tables to 4 accesses with additional arithmetic
+ * operations within the same table. The performance gain/loss
+ * depends on the system and memory details.
+ *
+ * This option is independent of \c MBEDTLS_AES_ROM_TABLES.
+ *
+ */
+//#define MBEDTLS_AES_FEWER_TABLES
+
+/**
+ * \def MBEDTLS_CAMELLIA_SMALL_MEMORY
+ *
+ * Use less ROM for the Camellia implementation (saves about 768 bytes).
+ *
+ * Uncomment this macro to use less memory for Camellia.
+ */
+//#define MBEDTLS_CAMELLIA_SMALL_MEMORY
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CBC
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CFB
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CTR
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_OFB
+ *
+ * Enable Output Feedback mode (OFB) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_OFB
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_XTS
+ *
+ * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES.
+ */
+#define MBEDTLS_CIPHER_MODE_XTS
+
+/**
+ * \def MBEDTLS_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * This module is required to support the TLS ciphersuites that use the NULL
+ * cipher.
+ *
+ * Uncomment this macro to enable the NULL cipher
+ */
+//#define MBEDTLS_CIPHER_NULL_CIPHER
+
+/**
+ * \def MBEDTLS_CIPHER_PADDING_PKCS7
+ *
+ * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for
+ * specific padding modes in the cipher layer with cipher modes that support
+ * padding (e.g. CBC)
+ *
+ * If you disable all padding modes, only full blocks can be used with CBC.
+ *
+ * Enable padding modes in the cipher layer.
+ */
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#define MBEDTLS_CIPHER_PADDING_ZEROS
+
+/**
+ * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ *
+ * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve
+ * module. By default all supported curves are enabled.
+ *
+ * Comment macros to disable the curve and functions for it
+ */
+#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#define MBEDTLS_ECP_DP_BP256R1_ENABLED
+#define MBEDTLS_ECP_DP_BP384R1_ENABLED
+#define MBEDTLS_ECP_DP_BP512R1_ENABLED
+#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
+#define MBEDTLS_ECP_DP_CURVE448_ENABLED
+
+/**
+ * \def MBEDTLS_ECP_NIST_OPTIM
+ *
+ * Enable specific 'modulo p' routines for each NIST prime.
+ * Depending on the prime and architecture, makes operations 4 to 8 times
+ * faster on the corresponding curve.
+ *
+ * Comment this macro to disable NIST curves optimisation.
+ */
+#define MBEDTLS_ECP_NIST_OPTIM
+
+/**
+ * \def MBEDTLS_ECP_RESTARTABLE
+ *
+ * Enable "non-blocking" ECC operations that can return early and be resumed.
+ *
+ * This allows various functions to pause by returning
+ * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in Mbed TLS's SSL module,
+ * MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in order
+ * to further progress and eventually complete their operation. This is
+ * controlled through mbedtls_ecp_set_max_ops() which limits the maximum number
+ * of ECC operations a function may perform before pausing; see
+ * mbedtls_ecp_set_max_ops() for more information.
+ *
+ * This is useful in non-threaded environments if you want to avoid blocking
+ * for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
+ *
+ * Uncomment this macro to enable restartable ECC computations.
+ *
+ * \note This option only works with the default software implementation of
+ * elliptic curve functionality. It is incompatible with
+ * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT.
+ */
+//#define MBEDTLS_ECP_RESTARTABLE
+
+/**
+ * \def MBEDTLS_ECDSA_DETERMINISTIC
+ *
+ * Enable deterministic ECDSA (RFC 6979).
+ * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
+ * may result in a compromise of the long-term signing key. This is avoided by
+ * the deterministic variant.
+ *
+ * Requires: MBEDTLS_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define MBEDTLS_ECDSA_DETERMINISTIC
+
+/**
+ * \def MBEDTLS_PK_PARSE_EC_EXTENDED
+ *
+ * Enhance support for reading EC keys using variants of SEC1 not allowed by
+ * RFC 5915 and RFC 5480.
+ *
+ * Currently this means parsing the SpecifiedECDomain choice of EC
+ * parameters (only known groups are supported, not arbitrary domains, to
+ * avoid validation issues).
+ *
+ * Disable if you only need to support RFC 5915 + 5480 key formats.
+ */
+#define MBEDTLS_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def MBEDTLS_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of mbedtls_strerror() in
+ * third party libraries easier when MBEDTLS_ERROR_C is disabled
+ * (no effect when MBEDTLS_ERROR_C is enabled).
+ *
+ * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're
+ * not using mbedtls_strerror() or error_strerror() in your application.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * mbedtls_strerror()
+ */
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+
+/**
+ * \def MBEDTLS_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: MBEDTLS_BIGNUM_C
+ */
+#define MBEDTLS_GENPRIME
+
+/**
+ * \def MBEDTLS_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+//#define MBEDTLS_FS_IO
+
+/**
+ * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * mbedtls_timing_hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+ */
+#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def MBEDTLS_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+ */
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_FORCE_SHA256
+ *
+ * Force the entropy accumulator to use a SHA-256 accumulator instead of the
+ * default SHA-512 based one (if both are available).
+ *
+ * Requires: MBEDTLS_SHA256_C
+ *
+ * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
+ * if you have performance concerns.
+ *
+ * This option is only useful if both MBEDTLS_SHA256_C and
+ * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define MBEDTLS_ENTROPY_FORCE_SHA256
+
+/**
+ * \def MBEDTLS_ENTROPY_NV_SEED
+ *
+ * Enable the non-volatile (NV) seed file-based entropy source.
+ * (Also enables the NV seed read/write functions in the platform layer)
+ *
+ * This is crucial (if not required) on systems that do not have a
+ * cryptographic entropy source (in hardware or kernel) available.
+ *
+ * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C
+ *
+ * \note The read/write functions that are used by the entropy source are
+ * determined in the platform layer, and can be modified at runtime and/or
+ * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used.
+ *
+ * \note If you use the default implementation functions that read a seedfile
+ * with regular fopen(), please make sure you make a seedfile with the
+ * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at
+ * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from
+ * and written to or you will get an entropy source error! The default
+ * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE
+ * bytes from the file.
+ *
+ * \note The entropy collector will write to the seed file before entropy is
+ * given to an external source, to update it.
+ */
+//#define MBEDTLS_ENTROPY_NV_SEED
+
+/* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+ *
+ * In PSA key storage, encode the owner of the key.
+ *
+ * This is only meaningful when building the library as part of a
+ * multi-client service. When you activate this option, you must provide
+ * an implementation of the type psa_key_owner_id_t and a translation
+ * from psa_key_file_id_t to file name in all the storage backends that
+ * you wish to support.
+ *
+ * Note that this option is meant for internal use only and may be removed
+ * without notice.
+ */
+//#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+
+/**
+ * \def MBEDTLS_MEMORY_DEBUG
+ *
+ * Enable debugging of buffer allocator memory issues. Automatically prints
+ * (to stderr) all (fatal) messages on memory allocation issues. Enables
+ * function for 'debug output' of allocated memory.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+//#define MBEDTLS_MEMORY_DEBUG
+
+/**
+ * \def MBEDTLS_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ * GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define MBEDTLS_MEMORY_BACKTRACE
+
+/**
+ * \def MBEDTLS_PK_RSA_ALT_SUPPORT
+ *
+ * Support external private RSA keys (eg from a HSM) in the PK layer.
+ *
+ * Comment this macro to disable support for external private RSA keys.
+ */
+#define MBEDTLS_PK_RSA_ALT_SUPPORT
+
+/**
+ * \def MBEDTLS_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: MBEDTLS_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+#define MBEDTLS_PKCS1_V15
+
+/**
+ * \def MBEDTLS_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define MBEDTLS_PKCS1_V21
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_SPM
+ *
+ * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure
+ * Partition Manager) integration which separates the code into two parts: a
+ * NSPE (Non-Secure Process Environment) and an SPE (Secure Process
+ * Environment).
+ *
+ * Module: library/psa_crypto.c
+ * Requires: MBEDTLS_PSA_CRYPTO_C
+ *
+ */
+//#define MBEDTLS_PSA_CRYPTO_SPM
+
+/**
+ * \def MBEDTLS_PSA_INJECT_ENTROPY
+ *
+ * Enable support for entropy injection at first boot. This feature is
+ * required on systems that do not have a built-in entropy source (TRNG).
+ * This feature is currently not supported on systems that have a built-in
+ * entropy source.
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED
+ *
+ */
+//#define MBEDTLS_PSA_INJECT_ENTROPY
+
+/**
+ * \def MBEDTLS_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem
+ * for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+ */
+//#define MBEDTLS_RSA_NO_CRT
+
+/**
+ * \def MBEDTLS_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+//#define MBEDTLS_SELF_TEST
+
+/**
+ * \def MBEDTLS_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+//#define MBEDTLS_SHA256_SMALLER
+
+/**
+ * \def MBEDTLS_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define MBEDTLS_THREADING_ALT
+
+/**
+ * \def MBEDTLS_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define MBEDTLS_THREADING_PTHREAD
+
+/**
+ * \def MBEDTLS_USE_PSA_CRYPTO
+ *
+ * Make the X.509 and TLS library use PSA for cryptographic operations, see
+ * #MBEDTLS_PSA_CRYPTO_C.
+ *
+ * Note: this option is still in progress, the full X.509 and TLS modules are
+ * not covered yet, but parts that are not ported to PSA yet will still work
+ * as usual, so enabling this option should not break backwards compatibility.
+ *
+ * \warning Support for PSA is still an experimental feature.
+ * Any public API that depends on this option may change
+ * at any time until this warning is removed.
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C.
+ */
+//#define MBEDTLS_USE_PSA_CRYPTO
+
+/**
+ * \def MBEDTLS_VERSION_FEATURES
+ *
+ * Allow run-time checking of compile-time enabled features. Thus allowing users
+ * to check at run-time if the library is for instance compiled with threading
+ * support via mbedtls_version_check_feature().
+ *
+ * Requires: MBEDTLS_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+#define MBEDTLS_VERSION_FEATURES
+
+/* \} name SECTION: mbed TLS feature support */
+
+/**
+ * \name SECTION: mbed TLS modules
+ *
+ * This section enables or disables entire modules in mbed TLS
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module: library/aesni.c
+ * Caller: library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+//#define MBEDTLS_AESNI_C
+
+/**
+ * \def MBEDTLS_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module: library/aes.c
+ * Caller: library/cipher.c
+ * library/pem.c
+ * library/ctr_drbg.c
+ *
+ * This module is required to support the TLS ciphersuites that use the AES
+ * cipher.
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define MBEDTLS_AES_C
+
+/**
+ * \def MBEDTLS_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module: library/arc4.c
+ * Caller: library/cipher.c
+ *
+ * This module is required to support the TLS ciphersuites that use the ARC4
+ * cipher.
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. If possible, we recommend avoidng dependencies on
+ * it, and considering stronger ciphers instead.
+ *
+ */
+#define MBEDTLS_ARC4_C
+
+/**
+ * \def MBEDTLS_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module: library/asn1.c
+ * Caller: library/dhm.c
+ * library/pkcs12.c
+ * library/pkcs5.c
+ * library/pkparse.c
+ */
+#define MBEDTLS_ASN1_PARSE_C
+
+/**
+ * \def MBEDTLS_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module: library/asn1write.c
+ * Caller: library/ecdsa.c
+ * library/pkwrite.c
+ */
+#define MBEDTLS_ASN1_WRITE_C
+
+/**
+ * \def MBEDTLS_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module: library/base64.c
+ * Caller: library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+#define MBEDTLS_BASE64_C
+
+/**
+ * \def MBEDTLS_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module: library/bignum.c
+ * Caller: library/dhm.c
+ * library/ecp.c
+ * library/ecdsa.c
+ * library/rsa.c
+ * library/rsa_internal.c
+ *
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
+ */
+#define MBEDTLS_BIGNUM_C
+
+/**
+ * \def MBEDTLS_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module: library/blowfish.c
+ */
+#define MBEDTLS_BLOWFISH_C
+
+/**
+ * \def MBEDTLS_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module: library/camellia.c
+ * Caller: library/cipher.c
+ *
+ * This module is required to support the TLS ciphersuites that use the
+ * Camellia cipher.
+ */
+#define MBEDTLS_CAMELLIA_C
+
+/**
+ * \def MBEDTLS_ARIA_C
+ *
+ * Enable the ARIA block cipher.
+ *
+ * Module: library/aria.c
+ * Caller: library/cipher.c
+ *
+ * This module is required to support the TLS ciphersuites that use the
+ * ARIA cipher.
+ */
+//#define MBEDTLS_ARIA_C
+
+/**
+ * \def MBEDTLS_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module: library/ccm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module is required to support AES-CCM ciphersuites in TLS.
+ */
+#define MBEDTLS_CCM_C
+
+/**
+ * \def MBEDTLS_CHACHA20_C
+ *
+ * Enable the ChaCha20 stream cipher.
+ *
+ * Module: library/chacha20.c
+ */
+#define MBEDTLS_CHACHA20_C
+
+/**
+ * \def MBEDTLS_CHACHAPOLY_C
+ *
+ * Enable the ChaCha20-Poly1305 AEAD algorithm.
+ *
+ * Module: library/chachapoly.c
+ *
+ * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
+ */
+#define MBEDTLS_CHACHAPOLY_C
+
+/**
+ * \def MBEDTLS_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module: library/cipher.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define MBEDTLS_CIPHER_C
+
+/**
+ * \def MBEDTLS_CMAC_C
+ *
+ * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
+ * ciphers.
+ *
+ * Module: library/cmac.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
+ *
+ */
+#define MBEDTLS_CMAC_C
+
+/**
+ * \def MBEDTLS_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-based random generator.
+ * The CTR_DRBG generator uses AES-256 by default.
+ * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
+ *
+ * Module: library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_AES_C
+ *
+ * This module provides the CTR_DRBG AES random number generator.
+ */
+#define MBEDTLS_CTR_DRBG_C
+
+/**
+ * \def MBEDTLS_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module: library/des.c
+ * Caller: library/pem.c
+ * library/cipher.c
+ *
+ * This module is required to support the TLS ciphersuites that use the DES
+ * cipher.
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers instead.
+ */
+#define MBEDTLS_DES_C
+
+/**
+ * \def MBEDTLS_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle module.
+ *
+ * Module: library/dhm.c
+ *
+ * This module is used by the following key exchanges:
+ * DHE-RSA, DHE-PSK
+ *
+ * \warning Using DHE constitutes a security risk as it
+ * is not possible to validate custom DH parameters.
+ * If possible, it is recommended users should consider
+ * preferring other methods of key exchange.
+ * See dhm.h for more details.
+ *
+ */
+#define MBEDTLS_DHM_C
+
+/**
+ * \def MBEDTLS_ECDH_C
+ *
+ * Enable the elliptic curve Diffie-Hellman library.
+ *
+ * Module: library/ecdh.c
+ *
+ * This module is used by the following key exchanges:
+ * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK
+ *
+ * Requires: MBEDTLS_ECP_C
+ */
+#define MBEDTLS_ECDH_C
+
+/**
+ * \def MBEDTLS_ECDSA_C
+ *
+ * Enable the elliptic curve DSA library.
+ *
+ * Module: library/ecdsa.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ * ECDHE-ECDSA
+ *
+ * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C
+ */
+#define MBEDTLS_ECDSA_C
+
+/**
+ * \def MBEDTLS_ECJPAKE_C
+ *
+ * Enable the elliptic curve J-PAKE library.
+ *
+ * \warning This is currently experimental. EC J-PAKE support is based on the
+ * Thread v1.0.0 specification; incompatible changes to the specification
+ * might still happen. For this reason, this is disabled by default.
+ *
+ * Module: library/ecjpake.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ * ECJPAKE
+ *
+ * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C
+ */
+//#define MBEDTLS_ECJPAKE_C
+
+/**
+ * \def MBEDTLS_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module: library/ecp.c
+ * Caller: library/ecdh.c
+ * library/ecdsa.c
+ * library/ecjpake.c
+ *
+ * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED
+ */
+#define MBEDTLS_ECP_C
+
+/**
+ * \def MBEDTLS_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module: library/entropy.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define MBEDTLS_ENTROPY_C
+
+/**
+ * \def MBEDTLS_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module: library/error.c
+ * Caller:
+ *
+ * This module enables mbedtls_strerror().
+ */
+#define MBEDTLS_ERROR_C
+
+/**
+ * \def MBEDTLS_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module: library/gcm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module is required to support the TLS ciphersuites that use GCM.
+ */
+#define MBEDTLS_GCM_C
+
+/**
+ * \def MBEDTLS_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Warning: the HAVEGE random generator is not suitable for virtualized
+ * environments
+ *
+ * Warning: the HAVEGE random generator is dependent on timing and specific
+ * processor traits. It is therefore not advised to use HAVEGE as
+ * your applications primary random generator or primary entropy pool
+ * input. As a secondary input to your entropy pool, it IS able add
+ * the (limited) extra entropy it provides.
+ *
+ * Module: library/havege.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_TIMING_C
+ *
+ * Uncomment to enable the HAVEGE random generator.
+ */
+//#define MBEDTLS_HAVEGE_C
+
+/**
+ * \def MBEDTLS_HKDF_C
+ *
+ * Enable the HKDF algorithm (RFC 5869).
+ *
+ * Module: library/hkdf.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the Hashed Message Authentication Code
+ * (HMAC)-based key derivation function (HKDF).
+ */
+#define MBEDTLS_HKDF_C
+
+/**
+ * \def MBEDTLS_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module: library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define MBEDTLS_HMAC_DRBG_C
+
+/**
+ * \def MBEDTLS_NIST_KW_C
+ *
+ * Enable the Key Wrapping mode for 128-bit block ciphers,
+ * as defined in NIST SP 800-38F. Only KW and KWP modes
+ * are supported. At the moment, only AES is approved by NIST.
+ *
+ * Module: library/nist_kw.c
+ *
+ * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C
+ */
+//#define MBEDTLS_NIST_KW_C
+
+/**
+ * \def MBEDTLS_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module: library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define MBEDTLS_MD_C
+
+/**
+ * \def MBEDTLS_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module: library/md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+ * \warning MD2 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+//#define MBEDTLS_MD2_C
+
+/**
+ * \def MBEDTLS_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module: library/md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+ * \warning MD4 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+//#define MBEDTLS_MD4_C
+
+/**
+ * \def MBEDTLS_MD5_C
+ *
+ * Enable the MD5 hash algorithm.
+ *
+ * Module: library/md5.c
+ * Caller: library/md.c
+ * library/pem.c
+ *
+ * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2
+ * depending on the handshake parameters. Further, it is used for checking
+ * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded
+ * encrypted keys.
+ *
+ * \warning MD5 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDTLS_MD5_C
+
+/**
+ * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
+ * calls)
+ *
+ * Module: library/memory_buffer_alloc.c
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def MBEDTLS_OID_C
+ *
+ * Enable the OID database.
+ *
+ * Module: library/oid.c
+ * Caller: library/asn1write.c
+ * library/pkcs5.c
+ * library/pkparse.c
+ * library/pkwrite.c
+ * library/rsa.c
+ *
+ * This modules translates between OIDs and internal values.
+ */
+#define MBEDTLS_OID_C
+
+/**
+ * \def MBEDTLS_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module: library/padlock.c
+ * Caller: library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+//#define MBEDTLS_PADLOCK_C
+
+/**
+ * \def MBEDTLS_PEM_PARSE_C
+ *
+ * Enable PEM decoding / parsing.
+ *
+ * Module: library/pem.c
+ * Caller: library/dhm.c
+ * library/pkparse.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+#define MBEDTLS_PEM_PARSE_C
+
+/**
+ * \def MBEDTLS_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module: library/pem.c
+ * Caller: library/pkwrite.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+#define MBEDTLS_PEM_WRITE_C
+
+/**
+ * \def MBEDTLS_PK_C
+ *
+ * Enable the generic public (asymetric) key layer.
+ *
+ * Module: library/pk.c
+ *
+ * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define MBEDTLS_PK_C
+
+/**
+ * \def MBEDTLS_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module: library/pkparse.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define MBEDTLS_PK_PARSE_C
+
+/**
+ * \def MBEDTLS_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module: library/pkwrite.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define MBEDTLS_PK_WRITE_C
+
+/**
+ * \def MBEDTLS_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module: library/pkcs5.c
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+#define MBEDTLS_PKCS5_C
+
+/**
+ * \def MBEDTLS_PKCS12_C
+ *
+ * Enable PKCS#12 PBE functions.
+ * Adds algorithms for parsing PKCS#8 encrypted private keys
+ *
+ * Module: library/pkcs12.c
+ * Caller: library/pkparse.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C
+ * Can use: MBEDTLS_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+#define MBEDTLS_PKCS12_C
+
+/**
+ * \def MBEDTLS_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
+ *
+ * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT
+ * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * \note This abstraction layer must be enabled on Windows (including MSYS2)
+ * as other module rely on it for a fixed snprintf implementation.
+ *
+ * Module: library/platform.c
+ * Caller: Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+//#define MBEDTLS_PLATFORM_C
+
+/**
+ * \def MBEDTLS_POLY1305_C
+ *
+ * Enable the Poly1305 MAC algorithm.
+ *
+ * Module: library/poly1305.c
+ * Caller: library/chachapoly.c
+ */
+#define MBEDTLS_POLY1305_C
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_C
+ *
+ * Enable the Platform Security Architecture cryptography API.
+ *
+ * Module: library/psa_crypto.c
+ *
+ * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C
+ *
+ */
+#define MBEDTLS_PSA_CRYPTO_C
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_STORAGE_C
+ *
+ * Enable the Platform Security Architecture persistent key storage.
+ *
+ * Module: library/psa_crypto_storage.c
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C,
+ * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of
+ * the PSA ITS interface
+ */
+//#define MBEDTLS_PSA_CRYPTO_STORAGE_C
+
+/**
+ * \def MBEDTLS_PSA_ITS_FILE_C
+ *
+ * Enable the emulation of the Platform Security Architecture
+ * Internal Trusted Storage (PSA ITS) over files.
+ *
+ * Module: library/psa_its_file.c
+ *
+ * Requires: MBEDTLS_FS_IO
+ */
+//#define MBEDTLS_PSA_ITS_FILE_C
+
+/**
+ * \def MBEDTLS_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module: library/ripemd160.c
+ * Caller: library/md.c
+ *
+ */
+#define MBEDTLS_RIPEMD160_C
+
+/**
+ * \def MBEDTLS_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module: library/rsa.c
+ * library/rsa_internal.c
+ *
+ * This module is used by the following key exchanges:
+ * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK
+ *
+ * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C
+ */
+#define MBEDTLS_RSA_C
+
+/**
+ * \def MBEDTLS_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module: library/sha1.c
+ * Caller: library/md.c
+ *
+ * This module is required for SSL/TLS up to version 1.1, for TLS 1.2
+ * depending on the handshake parameters, and for SHA1-signed certificates.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use constitutes
+ * a security risk. If possible, we recommend avoiding dependencies
+ * on it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDTLS_SHA1_C
+
+/**
+ * \def MBEDTLS_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module: library/sha256.c
+ * Caller: library/entropy.c
+ * library/md.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ * This module is required for the SSL/TLS 1.2 PRF function.
+ */
+#define MBEDTLS_SHA256_C
+
+/**
+ * \def MBEDTLS_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module: library/sha512.c
+ * Caller: library/entropy.c
+ * library/md.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define MBEDTLS_SHA512_C
+
+/**
+ * \def MBEDTLS_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default mbed TLS assumes it is used in a non-threaded environment or that
+ * contexts are not shared between threads. If you do intend to use contexts
+ * between threads, you will need to enable this layer to prevent race
+ * conditions. See also our Knowledge Base article about threading:
+ * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading
+ *
+ * Module: library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either MBEDTLS_THREADING_ALT or
+ * MBEDTLS_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within mbed TLS
+ */
+//#define MBEDTLS_THREADING_C
+
+/**
+ * \def MBEDTLS_TIMING_C
+ *
+ * Enable the semi-portable timing interface.
+ *
+ * \note The provided implementation only works on POSIX/Unix (including Linux,
+ * BSD and OS X) and Windows. On other platforms, you can either disable that
+ * module and provide your own implementations of the callbacks needed by Mbed
+ * TLS's \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and
+ * provide your own implementation of the whole module by setting
+ * \c MBEDTLS_TIMING_ALT in the current file.
+ *
+ * \note See also our Knowledge Base article about porting to a new
+ * environment:
+ * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
+ *
+ * Module: library/timing.c
+ * Caller: library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+//#define MBEDTLS_TIMING_C
+
+/**
+ * \def MBEDTLS_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module: library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define MBEDTLS_VERSION_C
+
+/**
+ * \def MBEDTLS_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module: library/xtea.c
+ * Caller:
+ */
+#define MBEDTLS_XTEA_C
+
+/* \} name SECTION: mbed TLS modules */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ *
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ * \{
+ */
+
+/* MPI / BIGNUM options */
+//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
+//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */
+
+/* CTR_DRBG options */
+//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
+
+/* HMAC_DRBG options */
+//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+
+/* ECP options */
+//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
+//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */
+//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */
+
+/* Entropy options */
+//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
+//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
+//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */
+
+/* Memory buffer allocator options */
+//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
+
+/* Platform options */
+//#define MBEDTLS_PLATFORM_STD_MEM_HDR <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */
+/* Note: your snprintf must correctly zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */
+
+/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
+/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
+//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */
+/* Note: your snprintf must correctly zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+
+/**
+ * Uncomment the macro to let mbed TLS use your alternate implementation of
+ * mbedtls_platform_zeroize(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * mbedtls_platform_zeroize() is a widely used function across the library to
+ * zero a block of memory. The implementation is expected to be secure in the
+ * sense that it has been written to prevent the compiler from removing calls
+ * to mbedtls_platform_zeroize() as part of redundant code elimination
+ * optimizations. However, it is difficult to guarantee that calls to
+ * mbedtls_platform_zeroize() will not be optimized by the compiler as older
+ * versions of the C language standards do not provide a secure implementation
+ * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to
+ * configure their own implementation of mbedtls_platform_zeroize(), for
+ * example by using directives specific to their compiler, features from newer
+ * C standards (e.g using memset_s() in C11) or calling a secure memset() from
+ * their system (e.g explicit_bzero() in BSD).
+ */
+//#define MBEDTLS_PLATFORM_ZEROIZE_ALT
+
+/**
+ * Uncomment the macro to let Mbed TLS use your alternate implementation of
+ * mbedtls_platform_gmtime_r(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * gmtime() is not a thread-safe function as defined in the C standard. The
+ * library will try to use safer implementations of this function, such as
+ * gmtime_r() when available. However, if Mbed TLS cannot identify the target
+ * system, the implementation of mbedtls_platform_gmtime_r() will default to
+ * using the standard gmtime(). In this case, calls from the library to
+ * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex
+ * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the
+ * library are also guarded with this mutex to avoid race conditions. However,
+ * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will
+ * unconditionally use the implementation for mbedtls_platform_gmtime_r()
+ * supplied at compile time.
+ */
+//#define MBEDTLS_PLATFORM_GMTIME_R_ALT
+
+/* \} name SECTION: Customisation configuration options */
+
+/* Target and application specific configurations
+ *
+ * Allow user to override any previous default.
+ *
+ */
+#if defined(MBEDTLS_USER_CONFIG_FILE)
+#include MBEDTLS_USER_CONFIG_FILE
+#endif
+
+#include "mbedtls/check_config.h"
+
+#endif /* CONFIG_MBED_CRYPTO_H */
diff --git a/components/service/crypto/client/cpp/crypto_client.cpp b/components/service/crypto/client/cpp/crypto_client.cpp
new file mode 100644
index 000000000..a374954ec
--- /dev/null
+++ b/components/service/crypto/client/cpp/crypto_client.cpp
@@ -0,0 +1,806 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cstring>
+#include <cstdlib>
+#include "crypto_client.h"
+#include <protocols/rpc/common/packed-c/status.h>
+#include <service/common/serializer/protobuf/pb_helper.h>
+#include <rpc_caller.h>
+#include <service/crypto/protobuf/opcodes.pb.h>
+#include <service/crypto/protobuf/generate_key.pb.h>
+#include <service/crypto/protobuf/destroy_key.pb.h>
+#include <service/crypto/protobuf/import_key.pb.h>
+#include <service/crypto/protobuf/open_key.pb.h>
+#include <service/crypto/protobuf/close_key.pb.h>
+#include <service/crypto/protobuf/export_key.pb.h>
+#include <service/crypto/protobuf/export_public_key.pb.h>
+#include <service/crypto/protobuf/sign_hash.pb.h>
+#include <service/crypto/protobuf/verify_hash.pb.h>
+#include <service/crypto/protobuf/asymmetric_encrypt.pb.h>
+#include <service/crypto/protobuf/asymmetric_decrypt.pb.h>
+#include <service/crypto/protobuf/generate_random.pb.h>
+#include <pb_encode.h>
+#include <pb_decode.h>
+
+crypto_client::crypto_client() :
+ m_caller(NULL),
+ m_err_rpc_status(TS_RPC_CALL_ACCEPTED)
+{
+
+}
+
+crypto_client::crypto_client(struct rpc_caller *caller) :
+ m_caller(caller),
+ m_err_rpc_status(TS_RPC_CALL_ACCEPTED)
+{
+
+}
+
+crypto_client::~crypto_client()
+{
+
+}
+
+int crypto_client::err_rpc_status() const
+{
+ return m_err_rpc_status;
+}
+
+psa_status_t crypto_client::generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle)
+{
+ size_t req_len;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_GenerateKeyIn req_msg = ts_crypto_GenerateKeyIn_init_default;
+
+ translate_key_attributes(req_msg.attributes, *attributes);
+ req_msg.has_attributes = true;
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_GenerateKeyIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_GenerateKeyIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_GENERATE_KEY, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ ts_crypto_GenerateKeyOut resp_msg = ts_crypto_GenerateKeyOut_init_default;
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_GenerateKeyOut_fields, &resp_msg)) {
+
+ *handle = resp_msg.handle;
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::destroy_key(psa_key_handle_t handle)
+{
+ size_t req_len;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_DestroyKeyIn req_msg = ts_crypto_DestroyKeyIn_init_default;
+
+ req_msg.handle = handle;
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_DestroyKeyIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_DestroyKeyIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_DESTROY_KEY, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::open_key(psa_key_id_t id, psa_key_handle_t *handle)
+{
+ size_t req_len;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_OpenKeyIn req_msg = ts_crypto_OpenKeyIn_init_default;
+ req_msg.id = id;
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_OpenKeyIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_OpenKeyIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_OPEN_KEY, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ ts_crypto_OpenKeyOut resp_msg = ts_crypto_OpenKeyOut_init_default;
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_OpenKeyOut_fields, &resp_msg)) {
+
+ *handle = resp_msg.handle;
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::close_key(psa_key_handle_t handle)
+{
+ size_t req_len;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_CloseKeyIn req_msg = ts_crypto_CloseKeyIn_init_default;
+
+ req_msg.handle = handle;
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_CloseKeyIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_CloseKeyIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_CLOSE_KEY, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::import_key(const psa_key_attributes_t *attributes,
+ const uint8_t *data, size_t data_length, psa_key_handle_t *handle)
+{
+ size_t req_len;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_ImportKeyIn req_msg = ts_crypto_ImportKeyIn_init_default;
+ pb_bytes_array_t *key_byte_array = pb_malloc_byte_array_containing_bytes(data, data_length);
+
+ translate_key_attributes(req_msg.attributes, *attributes);
+ req_msg.has_attributes = true;
+ req_msg.data = pb_out_byte_array(key_byte_array);
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_ImportKeyIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_ImportKeyIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_IMPORT_KEY, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ ts_crypto_ImportKeyOut resp_msg = ts_crypto_ImportKeyOut_init_default;
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_ImportKeyOut_fields, &resp_msg)) {
+
+ *handle = resp_msg.handle;
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ ::free(key_byte_array);
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::export_key(psa_key_handle_t handle,
+ uint8_t *data, size_t data_size,
+ size_t *data_length)
+{
+ size_t req_len;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_ExportKeyIn req_msg = ts_crypto_ExportKeyIn_init_default;
+ req_msg.handle = handle;
+
+ *data_length = 0; /* For failure case */
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_ExportKeyIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_ExportKeyIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_EXPORT_KEY, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ ts_crypto_ExportKeyOut resp_msg = ts_crypto_ExportKeyOut_init_default;
+ pb_bytes_array_t *exported_key = pb_malloc_byte_array(resp_len);
+
+ if (exported_key) {
+
+ resp_msg.data = pb_in_byte_array(exported_key);
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_ExportKeyOut_fields, &resp_msg)) {
+
+ if (exported_key->size <= data_size) {
+
+ memcpy(data, exported_key->bytes, exported_key->size);
+ *data_length = exported_key->size;
+ }
+ else {
+ /* Provided buffer is too small */
+ psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+
+ ::free(exported_key);
+ }
+ else {
+ /* Failed to allocate buffer for exported key */
+ psa_status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ }
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::export_public_key(psa_key_handle_t handle,
+ uint8_t *data, size_t data_size, size_t *data_length)
+{
+ size_t req_len;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_ExportPublicKeyIn req_msg = ts_crypto_ExportPublicKeyIn_init_default;
+ req_msg.handle = handle;
+
+ *data_length = 0; /* For failure case */
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_ExportPublicKeyIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_ExportPublicKeyIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_EXPORT_PUBLIC_KEY, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ ts_crypto_ExportPublicKeyOut resp_msg = ts_crypto_ExportPublicKeyOut_init_default;
+ pb_bytes_array_t *exported_key = pb_malloc_byte_array(resp_len);
+
+ if (exported_key) {
+
+ resp_msg.data = pb_in_byte_array(exported_key);
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_ExportPublicKeyOut_fields, &resp_msg)) {
+
+ if (exported_key->size <= data_size) {
+
+ memcpy(data, exported_key->bytes, exported_key->size);
+ *data_length = exported_key->size;
+ }
+ else {
+ /* Provided buffer is too small */
+ psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+
+ ::free(exported_key);
+ }
+ else {
+ /* Failed to alloocate buffer for exported key */
+ psa_status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ }
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::sign_hash(psa_key_handle_t handle, psa_algorithm_t alg,
+ const uint8_t *hash, size_t hash_length,
+ uint8_t *signature, size_t signature_size, size_t *signature_length)
+{
+ size_t req_len;
+ pb_bytes_array_t *hash_byte_array = pb_malloc_byte_array_containing_bytes(hash, hash_length);
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_SignHashIn req_msg = ts_crypto_SignHashIn_init_default;
+
+ *signature_length = 0; /* For failure case */
+
+ req_msg.handle = handle;
+ req_msg.alg = alg;
+ req_msg.hash = pb_out_byte_array(hash_byte_array);
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_SignHashIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_SignHashIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_SIGN_HASH, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ pb_bytes_array_t *sig_byte_array = pb_malloc_byte_array(PSA_SIGNATURE_MAX_SIZE);
+ ts_crypto_SignHashOut resp_msg = ts_crypto_SignHashOut_init_default;
+ resp_msg.signature = pb_in_byte_array(sig_byte_array);
+
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_SignHashOut_fields, &resp_msg)) {
+
+ if (sig_byte_array->size <= signature_size) {
+
+ memcpy(signature, sig_byte_array->bytes, sig_byte_array->size);
+ *signature_length = sig_byte_array->size;
+ }
+ else {
+ /* Provided buffer is too small */
+ psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+
+ ::free(sig_byte_array);
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ ::free(hash_byte_array);
+
+ return psa_status;
+}
+
+
+psa_status_t crypto_client::verify_hash(psa_key_handle_t handle, psa_algorithm_t alg,
+ const uint8_t *hash, size_t hash_length,
+ const uint8_t *signature, size_t signature_length)
+{
+ size_t req_len;
+ pb_bytes_array_t *hash_byte_array = pb_malloc_byte_array_containing_bytes(hash, hash_length);
+ pb_bytes_array_t *sig_byte_array = pb_malloc_byte_array_containing_bytes(signature, signature_length);
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_VerifyHashIn req_msg = ts_crypto_VerifyHashIn_init_default;
+
+ req_msg.handle = handle;
+ req_msg.alg = alg;
+ req_msg.hash = pb_out_byte_array(hash_byte_array);
+ req_msg.signature = pb_out_byte_array(sig_byte_array);
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_VerifyHashIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_VerifyHashIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_VERIFY_HASH, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ ::free(hash_byte_array);
+ ::free(sig_byte_array);
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::asymmetric_encrypt(psa_key_handle_t handle, psa_algorithm_t alg,
+ const uint8_t *input, size_t input_length,
+ const uint8_t *salt, size_t salt_length,
+ uint8_t *output, size_t output_size, size_t *output_length)
+{
+ size_t req_len;
+ pb_bytes_array_t *plaintext_byte_array = pb_malloc_byte_array_containing_bytes(input, input_length);
+ pb_bytes_array_t *salt_byte_array = pb_malloc_byte_array_containing_bytes(salt, salt_length);
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_AsymmetricEncryptIn req_msg = ts_crypto_AsymmetricEncryptIn_init_default;
+
+ *output_length = 0; /* For failure case */
+
+ req_msg.handle = handle;
+ req_msg.alg = alg;
+ req_msg.plaintext = pb_out_byte_array(plaintext_byte_array);
+ req_msg.salt = pb_out_byte_array(salt_byte_array);
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_AsymmetricEncryptIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus = PSA_ERROR_GENERIC_ERROR;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_AsymmetricEncryptIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_ASYMMETRIC_ENCRYPT, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ pb_bytes_array_t *ciphertext_byte_array = pb_malloc_byte_array(output_size);
+ ts_crypto_AsymmetricEncryptOut resp_msg = ts_crypto_AsymmetricEncryptOut_init_default;
+ resp_msg.ciphertext = pb_in_byte_array(ciphertext_byte_array);
+
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_AsymmetricEncryptOut_fields, &resp_msg)) {
+
+ if (ciphertext_byte_array->size <= output_size) {
+
+ memcpy(output, ciphertext_byte_array->bytes, ciphertext_byte_array->size);
+ *output_length = ciphertext_byte_array->size;
+ }
+ else {
+ /* Provided buffer is too small */
+ psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+
+ ::free(ciphertext_byte_array);
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ ::free(plaintext_byte_array);
+ ::free(salt_byte_array);
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::asymmetric_decrypt(psa_key_handle_t handle, psa_algorithm_t alg,
+ const uint8_t *input, size_t input_length,
+ const uint8_t *salt, size_t salt_length,
+ uint8_t *output, size_t output_size, size_t *output_length)
+{
+ size_t req_len;
+ pb_bytes_array_t *ciphertext_byte_array = pb_malloc_byte_array_containing_bytes(input, input_length);
+ pb_bytes_array_t *salt_byte_array = pb_malloc_byte_array_containing_bytes(salt, salt_length);
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_AsymmetricDecryptIn req_msg = ts_crypto_AsymmetricDecryptIn_init_default;
+
+ *output_length = 0; /* For failure case */
+
+ req_msg.handle = handle;
+ req_msg.alg = alg;
+ req_msg.ciphertext = pb_out_byte_array(ciphertext_byte_array);
+ req_msg.salt = pb_out_byte_array(salt_byte_array);
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_AsymmetricDecryptIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_AsymmetricDecryptIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_ASYMMETRIC_DECRYPT, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ pb_bytes_array_t *plaintext_byte_array = pb_malloc_byte_array(output_size);
+ ts_crypto_AsymmetricDecryptOut resp_msg = ts_crypto_AsymmetricDecryptOut_init_default;
+ resp_msg.plaintext = pb_in_byte_array(plaintext_byte_array);
+
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_AsymmetricDecryptOut_fields, &resp_msg)) {
+
+ if (plaintext_byte_array->size <= output_size) {
+
+ memcpy(output, plaintext_byte_array->bytes, plaintext_byte_array->size);
+ *output_length = plaintext_byte_array->size;
+ }
+ else {
+ /* Provided buffer is too small */
+ m_err_rpc_status = PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+ }
+ else {
+ /* Failed to decode response message */
+ m_err_rpc_status = PSA_ERROR_GENERIC_ERROR;
+ }
+
+ ::free(plaintext_byte_array);
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ ::free(ciphertext_byte_array);
+ ::free(salt_byte_array);
+
+ return psa_status;
+}
+
+psa_status_t crypto_client::generate_random(uint8_t *output, size_t output_size)
+{
+ size_t req_len;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ ts_crypto_GenerateRandomIn req_msg = ts_crypto_GenerateRandomIn_init_default;
+
+ req_msg.size = output_size;
+
+ if (pb_get_encoded_size(&req_len, ts_crypto_GenerateRandomIn_fields, &req_msg)) {
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len);
+ pb_encode(&ostream, ts_crypto_GenerateRandomIn_fields, &req_msg);
+
+ m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
+ ts_crypto_Opcode_GENERATE_RANDOM, &opstatus, &resp_buf, &resp_len);
+
+ if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ pb_bytes_array_t *output_byte_array = pb_malloc_byte_array(output_size);
+ ts_crypto_GenerateRandomOut resp_msg = ts_crypto_GenerateRandomOut_init_default;
+ resp_msg.random_bytes = pb_in_byte_array(output_byte_array);
+
+ pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len);
+
+ if (pb_decode(&istream, ts_crypto_GenerateRandomOut_fields, &resp_msg)) {
+
+ if (output_byte_array->size == output_size) {
+
+ memcpy(output, output_byte_array->bytes, output_byte_array->size);
+ }
+ else {
+ /* Mismatch between requested and generated length */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+
+ ::free(output_byte_array);
+ }
+ }
+
+ rpc_caller_end(m_caller, call_handle);
+ }
+ }
+
+ return psa_status;
+}
+
+void crypto_client::translate_key_attributes(ts_crypto_KeyAttributes &proto_attributes,
+ const psa_key_attributes_t &psa_attributes)
+{
+ proto_attributes.type = psa_get_key_type(&psa_attributes);
+ proto_attributes.key_bits = psa_get_key_bits(&psa_attributes);
+ proto_attributes.lifetime = psa_get_key_lifetime(&psa_attributes);
+ proto_attributes.id = psa_get_key_id(&psa_attributes);
+
+ proto_attributes.has_policy = true;
+ proto_attributes.policy.usage = psa_get_key_usage_flags(&psa_attributes);
+ proto_attributes.policy.alg = psa_get_key_algorithm(&psa_attributes);
+ }
diff --git a/components/service/crypto/client/cpp/crypto_client.h b/components/service/crypto/client/cpp/crypto_client.h
new file mode 100644
index 000000000..391f521a5
--- /dev/null
+++ b/components/service/crypto/client/cpp/crypto_client.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CRYPTO_CLIENT_H
+#define CRYPTO_CLIENT_H
+
+#include <cstdint>
+#include <psa/crypto.h>
+#include <service/crypto/protobuf/key_attributes.pb.h>
+
+
+struct rpc_caller;
+
+/** Provides a client interface for accessing an instance of the PSA Crypto service.
+ **/
+class crypto_client
+{
+public:
+ crypto_client(struct rpc_caller *caller);
+ virtual ~crypto_client();
+
+ int err_rpc_status() const;
+
+ /* Key lifecycle methods */
+ psa_status_t generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle);
+ psa_status_t destroy_key(psa_key_handle_t handle);
+ psa_status_t open_key(psa_key_id_t id, psa_key_handle_t *handle);
+ psa_status_t close_key(psa_key_handle_t handle);
+ psa_status_t import_key(const psa_key_attributes_t *attributes,
+ const uint8_t *data, size_t data_length, psa_key_handle_t *handle);
+
+ /* Key export methods */
+ psa_status_t export_key(psa_key_handle_t handle,
+ uint8_t *data, size_t data_size,
+ size_t *data_length);
+ psa_status_t export_public_key(psa_key_handle_t handle,
+ uint8_t *data, size_t data_size, size_t *data_length);
+
+ /* Sign/verify methods */
+ psa_status_t sign_hash(psa_key_handle_t handle, psa_algorithm_t alg,
+ const uint8_t *hash, size_t hash_length,
+ uint8_t *signature, size_t signature_size, size_t *signature_length);
+ psa_status_t verify_hash(psa_key_handle_t handle, psa_algorithm_t alg,
+ const uint8_t *hash, size_t hash_length,
+ const uint8_t *signature, size_t signature_length);
+
+ /* Asymmetric encrypt/decrypt */
+ psa_status_t asymmetric_encrypt(psa_key_handle_t handle, psa_algorithm_t alg,
+ const uint8_t *input, size_t input_length,
+ const uint8_t *salt, size_t salt_length,
+ uint8_t *output, size_t output_size, size_t *output_length);
+ psa_status_t asymmetric_decrypt(psa_key_handle_t handle, psa_algorithm_t alg,
+ const uint8_t *input, size_t input_length,
+ const uint8_t *salt, size_t salt_length,
+ uint8_t *output, size_t output_size, size_t *output_length);
+
+ /* Random number generation */
+ psa_status_t generate_random(uint8_t *output, size_t output_size);
+
+protected:
+ crypto_client();
+ void set_caller(struct rpc_caller *caller) {m_caller = caller;}
+
+private:
+
+ void translate_key_attributes(ts_crypto_KeyAttributes &proto_attributes,
+ const psa_key_attributes_t &psa_attributes);
+
+ struct rpc_caller *m_caller;
+ int m_err_rpc_status;
+};
+
+#endif /* CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/test/component.cmake b/components/service/crypto/client/test/component.cmake
new file mode 100644
index 000000000..0374e849e
--- /dev/null
+++ b/components/service/crypto/client/test/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/test_crypto_client.cpp"
+ )
+
diff --git a/components/service/crypto/client/test/mock/component.cmake b/components/service/crypto/client/test/mock/component.cmake
new file mode 100644
index 000000000..8202578c5
--- /dev/null
+++ b/components/service/crypto/client/test/mock/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/mock_crypto_client.cpp"
+ )
+
diff --git a/components/service/crypto/client/test/mock/mock_crypto_client.cpp b/components/service/crypto/client/test/mock/mock_crypto_client.cpp
new file mode 100644
index 000000000..8e55d34b4
--- /dev/null
+++ b/components/service/crypto/client/test/mock/mock_crypto_client.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "mock_crypto_client.h"
+
+mock_crypto_client::mock_crypto_client() :
+ test_crypto_client(),
+ m_crypto_provider(),
+ m_storage_provider(),
+ m_crypto_caller(),
+ m_storage_caller()
+{
+
+}
+
+mock_crypto_client::~mock_crypto_client()
+{
+
+}
+
+bool mock_crypto_client::init()
+{
+ bool should_do = test_crypto_client::init();
+
+ if (should_do) {
+
+ struct call_ep *storage_ep = mock_store_provider_init(&m_storage_provider);
+ struct rpc_caller *storage_caller = direct_caller_init_default(&m_storage_caller, storage_ep);
+
+ struct call_ep *crypto_ep = mbed_crypto_provider_init(&m_crypto_provider, storage_caller);
+ struct rpc_caller *crypto_caller = direct_caller_init_default(&m_crypto_caller, crypto_ep);
+
+ crypto_client::set_caller(crypto_caller);
+ }
+
+ return should_do;
+}
+
+bool mock_crypto_client::deinit()
+{
+ bool should_do = test_crypto_client::deinit();
+
+ if (should_do) {
+
+ mbed_crypto_provider_deinit(&m_crypto_provider);
+ mock_store_provider_deinit(&m_storage_provider);
+
+ direct_caller_deinit(&m_storage_caller);
+ direct_caller_deinit(&m_crypto_caller);
+ }
+
+ return should_do;
+}
+
+/* Test Methods */
+bool mock_crypto_client::keystore_reset_is_supported() const
+{
+ return true;
+}
+
+void mock_crypto_client::keystore_reset()
+{
+ mock_store_reset(&m_storage_provider);
+}
+
+bool mock_crypto_client::keystore_key_exists_is_supported() const
+{
+ return true;
+}
+
+bool mock_crypto_client::keystore_key_exists(uint32_t id) const
+{
+ return mock_store_exists(&m_storage_provider, id);
+}
+
+bool mock_crypto_client::keystore_keys_held_is_supported() const
+{
+ return true;
+}
+
+size_t mock_crypto_client::keystore_keys_held() const
+{
+ return mock_store_num_items(&m_storage_provider);
+}
+
+/* Factory for creating mock_crypto_client objects */
+class mock_crypto_client_factory : public test_crypto_client::factory
+{
+public:
+ mock_crypto_client_factory() :
+ test_crypto_client::factory()
+ {
+ test_crypto_client::register_factory(this);
+ }
+
+ ~mock_crypto_client_factory()
+ {
+ test_crypto_client::deregister_factory(this);
+ }
+
+ test_crypto_client *create()
+ {
+ return new mock_crypto_client;
+ };
+};
+
+/*
+ * Static construction causes this to be registered
+ * as the default factory for constructing test_crypto_client objects.
+ */
+static mock_crypto_client_factory default_factory;
diff --git a/components/service/crypto/client/test/mock/mock_crypto_client.h b/components/service/crypto/client/test/mock/mock_crypto_client.h
new file mode 100644
index 000000000..92ee6a993
--- /dev/null
+++ b/components/service/crypto/client/test/mock/mock_crypto_client.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOCK_CRYPTO_CLIENT_H
+#define MOCK_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/test/test_crypto_client.h>
+#include <rpc/direct/direct_caller.h>
+#include <service/crypto/provider/mbedcrypto/crypto_provider.h>
+#include <service/secure_storage/provider/mock_store/mock_store_provider.h>
+
+/*
+ * A specialization of the crypto_client class that extends it to add crypto
+ * and storage providers to offer a viable crypto service from a single object.
+ * The mock_store storage provider is used for persistent key storage.
+ * This is only used for test purposes and should not be used for production
+ * deployments. Provides methods used for inspecting service state that
+ * support test.
+ */
+class mock_crypto_client : public test_crypto_client
+{
+public:
+ mock_crypto_client();
+ virtual ~mock_crypto_client();
+
+ bool init();
+ bool deinit();
+
+ /* Test support methods */
+ bool keystore_reset_is_supported() const;
+ void keystore_reset();
+
+ bool keystore_key_exists_is_supported() const;
+ bool keystore_key_exists(uint32_t id) const;
+
+ bool keystore_keys_held_is_supported() const;
+ size_t keystore_keys_held() const;
+
+private:
+ struct mbed_crypto_provider m_crypto_provider;
+ struct mock_store_provider m_storage_provider;
+ struct direct_caller m_crypto_caller;
+ struct direct_caller m_storage_caller;
+};
+
+#endif /* MOCK_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/test/standalone/component.cmake b/components/service/crypto/client/test/standalone/component.cmake
new file mode 100644
index 000000000..13488e898
--- /dev/null
+++ b/components/service/crypto/client/test/standalone/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/standalone_crypto_client.cpp"
+ )
+
diff --git a/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp b/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp
new file mode 100644
index 000000000..da3224d34
--- /dev/null
+++ b/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "standalone_crypto_client.h"
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/psa/packed-c/status.h>
+
+standalone_crypto_client::standalone_crypto_client() :
+ test_crypto_client(),
+ m_crypto_provider(),
+ m_storage_provider(),
+ m_crypto_caller(),
+ m_storage_caller(),
+ m_dummy_storage_caller()
+{
+
+}
+
+standalone_crypto_client::~standalone_crypto_client()
+{
+
+}
+
+bool standalone_crypto_client::init()
+{
+ bool should_do = test_crypto_client::init();
+
+ if (should_do) {
+
+ struct rpc_caller *storage_caller;
+
+ if (!is_fault_injected(FAILED_TO_DISCOVER_SECURE_STORAGE)) {
+
+ /* Establish rpc session with storage provider */
+ struct call_ep *storage_ep = sfs_provider_init(&m_storage_provider);
+ storage_caller = direct_caller_init_default(&m_storage_caller, storage_ep);
+ }
+ else {
+
+ /*
+ * Missing storage service fault injected. To allow a somewhat viable
+ * crypto service to be started, use a dummy _caller that will safely
+ * terminate storage calls with an appropriate error.
+ */
+ storage_caller = dummy_caller_init(&m_dummy_storage_caller,
+ TS_RPC_CALL_ACCEPTED, PSA_ERROR_STORAGE_FAILURE);
+ }
+
+ struct call_ep *crypto_ep = mbed_crypto_provider_init(&m_crypto_provider, storage_caller);
+ struct rpc_caller *crypto_caller = direct_caller_init_default(&m_crypto_caller, crypto_ep);
+
+ crypto_client::set_caller(crypto_caller);
+ }
+
+ return should_do;
+}
+
+bool standalone_crypto_client::deinit()
+{
+ bool should_do = test_crypto_client::deinit();
+
+ if (should_do) {
+
+ mbed_crypto_provider_deinit(&m_crypto_provider);
+
+ direct_caller_deinit(&m_storage_caller);
+ direct_caller_deinit(&m_crypto_caller);
+ }
+
+ return should_do;
+}
+
+/* Fault injection */
+bool standalone_crypto_client::is_fault_supported(enum fault_code code) const
+{
+ return (code == test_crypto_client::FAILED_TO_DISCOVER_SECURE_STORAGE);
+}
+
+/* Test Methods */
+bool standalone_crypto_client::keystore_reset_is_supported() const
+{
+ return test_crypto_client::keystore_reset_is_supported();
+}
+
+void standalone_crypto_client::keystore_reset()
+{
+ test_crypto_client::keystore_reset();
+}
+
+bool standalone_crypto_client::keystore_key_exists_is_supported() const
+{
+ return test_crypto_client::keystore_key_exists_is_supported() ;
+}
+
+bool standalone_crypto_client::keystore_key_exists(uint32_t id) const
+{
+ return test_crypto_client::keystore_key_exists(id);
+}
+
+bool standalone_crypto_client::keystore_keys_held_is_supported() const
+{
+ return test_crypto_client::keystore_keys_held_is_supported();
+}
+
+size_t standalone_crypto_client::keystore_keys_held() const
+{
+ return test_crypto_client::keystore_keys_held();
+}
+
+/* Factory for creating standalone_crypto_client objects */
+class standalone_crypto_client_factory : public test_crypto_client::factory
+{
+public:
+ standalone_crypto_client_factory() :
+ test_crypto_client::factory()
+ {
+ test_crypto_client::register_factory(this);
+ }
+
+ ~standalone_crypto_client_factory()
+ {
+ test_crypto_client::deregister_factory(this);
+ }
+
+ test_crypto_client *create()
+ {
+ return new standalone_crypto_client;
+ };
+};
+
+/*
+ * Static construction causes this to be registered
+ * as the default factory for constructing test_crypto_client objects.
+ */
+static standalone_crypto_client_factory default_factory;
diff --git a/components/service/crypto/client/test/standalone/standalone_crypto_client.h b/components/service/crypto/client/test/standalone/standalone_crypto_client.h
new file mode 100644
index 000000000..9327fdcd6
--- /dev/null
+++ b/components/service/crypto/client/test/standalone/standalone_crypto_client.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STANDALONE_CRYPTO_CLIENT_H
+#define STANDALONE_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/test/test_crypto_client.h>
+#include <rpc/direct/direct_caller.h>
+#include <rpc/dummy/dummy_caller.h>
+#include <service/crypto/provider/mbedcrypto/crypto_provider.h>
+#include <service/secure_storage/provider/secure_flash_store/sfs_provider.h>
+
+/*
+ * A specialization of the crypto_client class that extends it to add crypto
+ * and storage providers to offer a viable crypto service from a single object.
+ * This is only used for test purposes and should not be used for production
+ * deployments. Provides methods used for inspecting service state that
+ * support test.
+ */
+class standalone_crypto_client : public test_crypto_client
+{
+public:
+ standalone_crypto_client();
+ virtual ~standalone_crypto_client();
+
+ bool init();
+ bool deinit();
+
+ /* Test support methods */
+ bool keystore_reset_is_supported() const;
+ void keystore_reset();
+
+ bool keystore_key_exists_is_supported() const;
+ bool keystore_key_exists(uint32_t id) const;
+
+ bool keystore_keys_held_is_supported() const;
+ size_t keystore_keys_held() const;
+
+private:
+ bool is_fault_supported(enum fault_code code) const;
+
+ struct mbed_crypto_provider m_crypto_provider;
+ struct sfs_provider m_storage_provider;
+ struct direct_caller m_crypto_caller;
+ struct direct_caller m_storage_caller;
+ struct dummy_caller m_dummy_storage_caller;
+};
+
+#endif /* STANDALONE_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/test/test_crypto_client.cpp b/components/service/crypto/client/test/test_crypto_client.cpp
new file mode 100644
index 000000000..72327904c
--- /dev/null
+++ b/components/service/crypto/client/test/test_crypto_client.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cassert>
+#include "test_crypto_client.h"
+
+test_crypto_client::factory *test_crypto_client::m_default_factory = NULL;
+
+test_crypto_client::test_crypto_client() :
+ crypto_client(),
+ m_is_initialized(false),
+ m_injected_faults()
+{
+
+}
+
+test_crypto_client::~test_crypto_client()
+{
+ deinit();
+}
+
+bool test_crypto_client::init()
+{
+ bool success = !m_is_initialized;
+ m_is_initialized = true;
+ return success;
+}
+
+bool test_crypto_client::deinit()
+{
+ bool success = m_is_initialized;
+ m_is_initialized = false;
+ return success;
+}
+
+test_crypto_client *test_crypto_client::create_default()
+{
+ /*
+ * It's mandatory to include a concrete test_crypto_client
+ * that registers its own factory in a deployment if you
+ * want to use this factory method.
+ */
+ assert(m_default_factory);
+ return m_default_factory->create();
+}
+
+void test_crypto_client::register_factory(factory *factory)
+{
+ /*
+ * Don't allow overriding of an existing default. This
+ * will happen if two test_crypto_client components have
+ * been included in a deployment.
+ */
+ assert(!m_default_factory);
+ m_default_factory = factory;
+}
+
+void test_crypto_client::deregister_factory(factory *factory)
+{
+ if (m_default_factory == factory) m_default_factory = NULL;
+}
+
+bool test_crypto_client::inject_fault(enum fault_code code)
+{
+ assert(!m_is_initialized);
+
+ bool is_supported = is_fault_supported(code);
+ if (is_supported) m_injected_faults.push_back(code);
+ return is_supported;
+}
+
+bool test_crypto_client::is_fault_supported(enum fault_code code) const
+{
+ /* Derived classes may override this if fault simualtion is supported */
+ (void)code;
+ return false;
+}
+
+bool test_crypto_client::is_fault_injected(enum fault_code code) const
+{
+ bool is_injected = false;
+
+ for (size_t i = 0; !is_injected && i < m_injected_faults.size(); ++i) {
+ is_injected = (m_injected_faults[i] == code);
+ }
+
+ return is_injected;
+}
+
+/*
+ * Test methods by default are not supported. Calling a non-supported
+ * method will trigger an assert. A class derived from this one may
+ * pick and choose which test methods it supports.
+ */
+bool test_crypto_client::keystore_reset_is_supported() const { return false; }
+void test_crypto_client::keystore_reset() { assert(false); }
+
+bool test_crypto_client::keystore_key_exists_is_supported() const { return false; }
+bool test_crypto_client::keystore_key_exists(uint32_t id) const { (void)id; assert(false); return false; }
+
+bool test_crypto_client::keystore_keys_held_is_supported() const { return false; }
+size_t test_crypto_client::keystore_keys_held() const { assert(false); return 0; } \ No newline at end of file
diff --git a/components/service/crypto/client/test/test_crypto_client.h b/components/service/crypto/client/test/test_crypto_client.h
new file mode 100644
index 000000000..5b927dbe0
--- /dev/null
+++ b/components/service/crypto/client/test/test_crypto_client.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEST_CRYPTO_CLIENT_H
+#define TEST_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/cpp/crypto_client.h>
+#include <vector>
+
+/*
+ * A specialization of the crypto_client class that extends it to add
+ * virtial methods to support test. Depending on the deployment,
+ * real implementations of test methods may or may not exist. For example,
+ * for a real distributed deployment where the key store is located in
+ * a secure processing environment, back door test methods that peak
+ * into the keystore are clearly not possible (or at least desirable!).
+ * Each virtual test method is paired with a is_supported() method to
+ * allow test cases to adapt to circumstances.
+ */
+class test_crypto_client : public crypto_client
+{
+public:
+ virtual ~test_crypto_client();
+
+ virtual bool init();
+ virtual bool deinit();
+
+ /*
+ * A factory method for contsructing the default class
+ * of test_crypto_client for the deployment.
+ */
+ static test_crypto_client *create_default();
+
+ /*
+ * Fault conditions that may be injected to allow error
+ * handling to be tested.
+ */
+ enum fault_code
+ {
+ FAILED_TO_DISCOVER_SECURE_STORAGE
+ };
+
+ /*
+ * Injects the specified fault. May be called multiple
+ * times to inject different fault conditions. Faults
+ * should be injected prior to calling the init() method
+ * to allow startup faults to be simulated. Returns true
+ * if the fault condition can be simulated.
+ */
+ bool inject_fault(enum fault_code code);
+
+ /* Wipe all keys held in the keystore */
+ virtual bool keystore_reset_is_supported() const;
+ virtual void keystore_reset();
+
+ /* Check if a key is held in the keystore */
+ virtual bool keystore_key_exists_is_supported() const;
+ virtual bool keystore_key_exists(uint32_t id) const;
+
+ /* Return the number of keys in the keystore */
+ virtual bool keystore_keys_held_is_supported() const;
+ virtual size_t keystore_keys_held() const;
+
+ /* An abstract factory for constructing concrete test_crypto_client objects */
+ class factory
+ {
+ public:
+ virtual test_crypto_client *create() = 0;
+ };
+
+ static void register_factory(factory *factory);
+ static void deregister_factory(factory *factory);
+
+protected:
+ test_crypto_client();
+ virtual bool is_fault_supported(enum fault_code code) const;
+ bool is_fault_injected(enum fault_code code) const;
+
+private:
+ bool m_is_initialized;
+ std::vector<fault_code> m_injected_faults;
+ static factory *m_default_factory;
+};
+
+#endif /* STANDALONE_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/provider/mbedcrypto/component.cmake b/components/service/crypto/provider/mbedcrypto/component.cmake
new file mode 100644
index 000000000..f508e53d3
--- /dev/null
+++ b/components/service/crypto/provider/mbedcrypto/component.cmake
@@ -0,0 +1,31 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/crypto_provider.c"
+ )
+
+target_include_directories(${TGT}
+ PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}"
+ )
+
+# Force use of the mbed crypto configuration required by the crypto service
+# provider. This configuration includes enabling the use of the PSA ITS API
+# for persistent key storage which is realised by the its client adapter
+# for the secure storage service.
+set(MBEDCRYPTO_CONFIG_FILE
+ "${CMAKE_CURRENT_LIST_DIR}/config_mbed_crypto.h"
+ CACHE STRING "Configuration file for mbedcrypto" FORCE)
+
+set(MBEDCRYPTO_EXTRA_INCLUDES
+ "${TS_ROOT}/components/service/common"
+ "${TS_ROOT}/components/service/secure_storage/client"
+ CACHE STRING "PSA ITS for mbedcrypto" FORCE)
diff --git a/components/service/crypto/provider/mbedcrypto/config_mbed_crypto.h b/components/service/crypto/provider/mbedcrypto/config_mbed_crypto.h
new file mode 100644
index 000000000..cb8d6bd2e
--- /dev/null
+++ b/components/service/crypto/provider/mbedcrypto/config_mbed_crypto.h
@@ -0,0 +1,1954 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CONFIG_MBED_CRYPTO_H
+#define CONFIG_MBED_CRYPTO_H
+
+/**
+ * Defines the configuration needed by the crypto service provider
+ */
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ * library/aria.c
+ * library/timing.c
+ * include/mbedtls/bn_mul.h
+ *
+ * Required by:
+ * MBEDTLS_AESNI_C
+ * MBEDTLS_PADLOCK_C
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define MBEDTLS_HAVE_ASM
+
+/**
+ * \def MBEDTLS_NO_UDBL_DIVISION
+ *
+ * The platform lacks support for double-width integer division (64-bit
+ * division on a 32-bit platform, 128-bit division on a 64-bit platform).
+ *
+ * Used in:
+ * include/mbedtls/bignum.h
+ * library/bignum.c
+ *
+ * The bignum code uses double-width division to speed up some operations.
+ * Double-width division is often implemented in software that needs to
+ * be linked with the program. The presence of a double-width integer
+ * type is usually detected automatically through preprocessor macros,
+ * but the automatic detection cannot know whether the code needs to
+ * and can be linked with an implementation of division for that type.
+ * By default division is assumed to be usable if the type is present.
+ * Uncomment this option to prevent the use of double-width division.
+ *
+ * Note that division for the native integer type is always required.
+ * Furthermore, a 64-bit type is always required even on a 32-bit
+ * platform, but it need not support multiplication or division. In some
+ * cases it is also desirable to disable some double-width operations. For
+ * example, if double-width division is implemented in software, disabling
+ * it can reduce code size in some embedded targets.
+ */
+#define MBEDTLS_NO_UDBL_DIVISION
+
+/**
+ * \def MBEDTLS_NO_64BIT_MULTIPLICATION
+ *
+ * The platform lacks support for 32x32 -> 64-bit multiplication.
+ *
+ * Used in:
+ * library/poly1305.c
+ *
+ * Some parts of the library may use multiplication of two unsigned 32-bit
+ * operands with a 64-bit result in order to speed up computations. On some
+ * platforms, this is not available in hardware and has to be implemented in
+ * software, usually in a library provided by the toolchain.
+ *
+ * Sometimes it is not desirable to have to link to that library. This option
+ * removes the dependency of that library on platforms that lack a hardware
+ * 64-bit multiplier by embedding a software implementation in Mbed TLS.
+ *
+ * Note that depending on the compiler, this may decrease performance compared
+ * to using the library function provided by the toolchain.
+ */
+//#define MBEDTLS_NO_64BIT_MULTIPLICATION
+
+/**
+ * \def MBEDTLS_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define MBEDTLS_HAVE_SSE2
+
+/**
+ * \def MBEDTLS_HAVE_TIME
+ *
+ * System has time.h and time().
+ * The time does not need to be correct, only time differences are used,
+ * by contrast with MBEDTLS_HAVE_TIME_DATE
+ *
+ * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT,
+ * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and
+ * MBEDTLS_PLATFORM_STD_TIME.
+ *
+ * Comment if your system does not support time functions
+ */
+//#define MBEDTLS_HAVE_TIME
+
+/**
+ * \def MBEDTLS_HAVE_TIME_DATE
+ *
+ * System has time.h, time(), and an implementation for
+ * mbedtls_platform_gmtime_r() (see below).
+ * The time needs to be correct (not necessarily very accurate, but at least
+ * the date should be correct). This is used to verify the validity period of
+ * X.509 certificates.
+ *
+ * Comment if your system does not have a correct clock.
+ *
+ * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that
+ * behaves similarly to the gmtime_r() function from the C standard. Refer to
+ * the documentation for mbedtls_platform_gmtime_r() for more information.
+ *
+ * \note It is possible to configure an implementation for
+ * mbedtls_platform_gmtime_r() at compile-time by using the macro
+ * MBEDTLS_PLATFORM_GMTIME_R_ALT.
+ */
+//#define MBEDTLS_HAVE_TIME_DATE
+
+/**
+ * \def MBEDTLS_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default mbed TLS uses the system-provided calloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY without the
+ * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
+ * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY and specifying
+ * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define MBEDTLS_PLATFORM_MEMORY
+
+/**
+ * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. calloc() to
+ * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF)
+ *
+ * This makes sure there are no linking errors on platforms that do not support
+ * these functions. You will HAVE to provide alternatives, either at runtime
+ * via the platform_set_xxx() functions or at compile time by setting
+ * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a
+ * MBEDTLS_PLATFORM_XXX_MACRO.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def MBEDTLS_PLATFORM_EXIT_ALT
+ *
+ * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the
+ * function in the platform abstraction layer.
+ *
+ * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will
+ * provide a function "mbedtls_platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require MBEDTLS_PLATFORM_C to be defined!
+ *
+ * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows;
+ * it will be enabled automatically by check_config.h
+ *
+ * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as
+ * MBEDTLS_PLATFORM_XXX_MACRO!
+ *
+ * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define MBEDTLS_PLATFORM_EXIT_ALT
+//#define MBEDTLS_PLATFORM_TIME_ALT
+//#define MBEDTLS_PLATFORM_FPRINTF_ALT
+//#define MBEDTLS_PLATFORM_PRINTF_ALT
+//#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
+//#define MBEDTLS_PLATFORM_NV_SEED_ALT
+//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT
+
+/**
+ * \def MBEDTLS_DEPRECATED_WARNING
+ *
+ * Mark deprecated functions so that they generate a warning if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * This only works with GCC and Clang. With other compilers, you may want to
+ * use MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Uncomment to get warnings on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_WARNING
+
+/**
+ * \def MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Remove deprecated functions so that they generate an error if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * Uncomment to get errors on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_REMOVED
+
+/**
+ * \def MBEDTLS_CHECK_PARAMS
+ *
+ * This configuration option controls whether the library validates more of
+ * the parameters passed to it.
+ *
+ * When this flag is not defined, the library only attempts to validate an
+ * input parameter if: (1) they may come from the outside world (such as the
+ * network, the filesystem, etc.) or (2) not validating them could result in
+ * internal memory errors such as overflowing a buffer controlled by the
+ * library. On the other hand, it doesn't attempt to validate parameters whose
+ * values are fully controlled by the application (such as pointers).
+ *
+ * When this flag is defined, the library additionally attempts to validate
+ * parameters that are fully controlled by the application, and should always
+ * be valid if the application code is fully correct and trusted.
+ *
+ * For example, when a function accepts as input a pointer to a buffer that may
+ * contain untrusted data, and its documentation mentions that this pointer
+ * must not be NULL:
+ * - the pointer is checked to be non-NULL only if this option is enabled
+ * - the content of the buffer is always validated
+ *
+ * When this flag is defined, if a library function receives a parameter that
+ * is invalid, it will:
+ * - invoke the macro MBEDTLS_PARAM_FAILED() which by default expands to a
+ * call to the function mbedtls_param_failed()
+ * - immediately return (with a specific error code unless the function
+ * returns void and can't communicate an error).
+ *
+ * When defining this flag, you also need to:
+ * - either provide a definition of the function mbedtls_param_failed() in
+ * your application (see platform_util.h for its prototype) as the library
+ * calls that function, but does not provide a default definition for it,
+ * - or provide a different definition of the macro MBEDTLS_PARAM_FAILED()
+ * below if the above mechanism is not flexible enough to suit your needs.
+ * See the documentation of this macro later in this file.
+ *
+ * Uncomment to enable validation of application-controlled parameters.
+ */
+//#define MBEDTLS_CHECK_PARAMS
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: mbed TLS feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_TIMING_ALT
+ *
+ * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(),
+ * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay()
+ *
+ * Only works if you have MBEDTLS_TIMING_C enabled.
+ *
+ * You will need to provide a header "timing_alt.h" and an implementation at
+ * compile time.
+ */
+//#define MBEDTLS_TIMING_ALT
+
+/**
+ * \def MBEDTLS_AES_ALT
+ *
+ * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your
+ * alternate core implementation of a symmetric crypto, an arithmetic or hash
+ * module (e.g. platform specific assembly optimized implementations). Keep
+ * in mind that the function prototypes should remain the same.
+ *
+ * This replaces the whole module. If you only want to replace one of the
+ * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer
+ * provide the "struct mbedtls_aes_context" definition and omit the base
+ * function declarations and implementations. "aes_alt.h" will be included from
+ * "aes.h" to include the new function definitions.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * module.
+ *
+ * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their
+ * use constitutes a security risk. If possible, we recommend
+ * avoiding dependencies on them, and considering stronger message
+ * digests and ciphers instead.
+ *
+ */
+//#define MBEDTLS_AES_ALT
+//#define MBEDTLS_ARC4_ALT
+//#define MBEDTLS_ARIA_ALT
+//#define MBEDTLS_BLOWFISH_ALT
+//#define MBEDTLS_CAMELLIA_ALT
+//#define MBEDTLS_CCM_ALT
+//#define MBEDTLS_CHACHA20_ALT
+//#define MBEDTLS_CHACHAPOLY_ALT
+//#define MBEDTLS_CMAC_ALT
+//#define MBEDTLS_DES_ALT
+//#define MBEDTLS_DHM_ALT
+//#define MBEDTLS_ECJPAKE_ALT
+//#define MBEDTLS_GCM_ALT
+//#define MBEDTLS_NIST_KW_ALT
+//#define MBEDTLS_MD2_ALT
+//#define MBEDTLS_MD4_ALT
+//#define MBEDTLS_MD5_ALT
+//#define MBEDTLS_POLY1305_ALT
+//#define MBEDTLS_RIPEMD160_ALT
+//#define MBEDTLS_RSA_ALT
+//#define MBEDTLS_SHA1_ALT
+//#define MBEDTLS_SHA256_ALT
+//#define MBEDTLS_SHA512_ALT
+//#define MBEDTLS_XTEA_ALT
+
+/*
+ * When replacing the elliptic curve module, pleace consider, that it is
+ * implemented with two .c files:
+ * - ecp.c
+ * - ecp_curves.c
+ * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT
+ * macros as described above. The only difference is that you have to make sure
+ * that you provide functionality for both .c files.
+ */
+//#define MBEDTLS_ECP_ALT
+
+/**
+ * \def MBEDTLS_MD2_PROCESS_ALT
+ *
+ * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you
+ * alternate core implementation of symmetric crypto or hash function. Keep in
+ * mind that function prototypes should remain the same.
+ *
+ * This replaces only one function. The header file from mbed TLS is still
+ * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will
+ * no longer provide the mbedtls_sha1_process() function, but it will still provide
+ * the other function (using your mbedtls_sha1_process() function) and the definition
+ * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible
+ * with this definition.
+ *
+ * \note Because of a signature change, the core AES encryption and decryption routines are
+ * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt,
+ * respectively. When setting up alternative implementations, these functions should
+ * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt
+ * must stay untouched.
+ *
+ * \note If you use the AES_xxx_ALT macros, then is is recommended to also set
+ * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES
+ * tables.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ *
+ * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use
+ * constitutes a security risk. If possible, we recommend avoiding
+ * dependencies on them, and considering stronger message digests
+ * and ciphers instead.
+ *
+ */
+//#define MBEDTLS_MD2_PROCESS_ALT
+//#define MBEDTLS_MD4_PROCESS_ALT
+//#define MBEDTLS_MD5_PROCESS_ALT
+//#define MBEDTLS_RIPEMD160_PROCESS_ALT
+//#define MBEDTLS_SHA1_PROCESS_ALT
+//#define MBEDTLS_SHA256_PROCESS_ALT
+//#define MBEDTLS_SHA512_PROCESS_ALT
+//#define MBEDTLS_DES_SETKEY_ALT
+//#define MBEDTLS_DES_CRYPT_ECB_ALT
+//#define MBEDTLS_DES3_CRYPT_ECB_ALT
+//#define MBEDTLS_AES_SETKEY_ENC_ALT
+//#define MBEDTLS_AES_SETKEY_DEC_ALT
+//#define MBEDTLS_AES_ENCRYPT_ALT
+//#define MBEDTLS_AES_DECRYPT_ALT
+//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT
+//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT
+//#define MBEDTLS_ECDSA_VERIFY_ALT
+//#define MBEDTLS_ECDSA_SIGN_ALT
+//#define MBEDTLS_ECDSA_GENKEY_ALT
+
+/**
+ * \def MBEDTLS_ECP_INTERNAL_ALT
+ *
+ * Expose a part of the internal interface of the Elliptic Curve Point module.
+ *
+ * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your
+ * alternative core implementation of elliptic curve arithmetic. Keep in mind
+ * that function prototypes should remain the same.
+ *
+ * This partially replaces one function. The header file from mbed TLS is still
+ * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation
+ * is still present and it is used for group structures not supported by the
+ * alternative.
+ *
+ * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT
+ * and implementing the following functions:
+ * unsigned char mbedtls_internal_ecp_grp_capable(
+ * const mbedtls_ecp_group *grp )
+ * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )
+ * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp )
+ * The mbedtls_internal_ecp_grp_capable function should return 1 if the
+ * replacement functions implement arithmetic for the given group and 0
+ * otherwise.
+ * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are
+ * called before and after each point operation and provide an opportunity to
+ * implement optimized set up and tear down instructions.
+ *
+ * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and
+ * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac
+ * function, but will use your mbedtls_internal_ecp_double_jac if the group is
+ * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when
+ * receives it as an argument). If the group is not supported then the original
+ * implementation is used. The other functions and the definition of
+ * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your
+ * implementation of mbedtls_internal_ecp_double_jac and
+ * mbedtls_internal_ecp_grp_capable must be compatible with this definition.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ */
+/* Required for all the functions in this section */
+//#define MBEDTLS_ECP_INTERNAL_ALT
+/* Support for Weierstrass curves with Jacobi representation */
+//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
+//#define MBEDTLS_ECP_ADD_MIXED_ALT
+//#define MBEDTLS_ECP_DOUBLE_JAC_ALT
+//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
+//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
+/* Support for curves with Montgomery arithmetic */
+//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT
+//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT
+//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT
+
+/**
+ * \def MBEDTLS_TEST_NULL_ENTROPY
+ *
+ * Enables testing and use of mbed TLS without any configured entropy sources.
+ * This permits use of the library on platforms before an entropy source has
+ * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the
+ * MBEDTLS_ENTROPY_NV_SEED switches).
+ *
+ * WARNING! This switch MUST be disabled in production builds, and is suitable
+ * only for development.
+ * Enabling the switch negates any security provided by the library.
+ *
+ * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ */
+//#define MBEDTLS_TEST_NULL_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_HARDWARE_ALT
+ *
+ * Uncomment this macro to let mbed TLS use your own implementation of a
+ * hardware entropy collector.
+ *
+ * Your function must be called \c mbedtls_hardware_poll(), have the same
+ * prototype as declared in entropy_poll.h, and accept NULL as first argument.
+ *
+ * Uncomment to use your own hardware entropy collector.
+ */
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+
+/**
+ * \def MBEDTLS_AES_ROM_TABLES
+ *
+ * Use precomputed AES tables stored in ROM.
+ *
+ * Uncomment this macro to use precomputed AES tables stored in ROM.
+ * Comment this macro to generate AES tables in RAM at runtime.
+ *
+ * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb
+ * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the
+ * initialization time before the first AES operation can be performed.
+ * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c
+ * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded
+ * performance if ROM access is slower than RAM access.
+ *
+ * This option is independent of \c MBEDTLS_AES_FEWER_TABLES.
+ *
+ */
+//#define MBEDTLS_AES_ROM_TABLES
+
+/**
+ * \def MBEDTLS_AES_FEWER_TABLES
+ *
+ * Use less ROM/RAM for AES tables.
+ *
+ * Uncommenting this macro omits 75% of the AES tables from
+ * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES)
+ * by computing their values on the fly during operations
+ * (the tables are entry-wise rotations of one another).
+ *
+ * Tradeoff: Uncommenting this reduces the RAM / ROM footprint
+ * by ~6kb but at the cost of more arithmetic operations during
+ * runtime. Specifically, one has to compare 4 accesses within
+ * different tables to 4 accesses with additional arithmetic
+ * operations within the same table. The performance gain/loss
+ * depends on the system and memory details.
+ *
+ * This option is independent of \c MBEDTLS_AES_ROM_TABLES.
+ *
+ */
+//#define MBEDTLS_AES_FEWER_TABLES
+
+/**
+ * \def MBEDTLS_CAMELLIA_SMALL_MEMORY
+ *
+ * Use less ROM for the Camellia implementation (saves about 768 bytes).
+ *
+ * Uncomment this macro to use less memory for Camellia.
+ */
+//#define MBEDTLS_CAMELLIA_SMALL_MEMORY
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CBC
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CFB
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CTR
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_OFB
+ *
+ * Enable Output Feedback mode (OFB) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_OFB
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_XTS
+ *
+ * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES.
+ */
+#define MBEDTLS_CIPHER_MODE_XTS
+
+/**
+ * \def MBEDTLS_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * This module is required to support the TLS ciphersuites that use the NULL
+ * cipher.
+ *
+ * Uncomment this macro to enable the NULL cipher
+ */
+//#define MBEDTLS_CIPHER_NULL_CIPHER
+
+/**
+ * \def MBEDTLS_CIPHER_PADDING_PKCS7
+ *
+ * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for
+ * specific padding modes in the cipher layer with cipher modes that support
+ * padding (e.g. CBC)
+ *
+ * If you disable all padding modes, only full blocks can be used with CBC.
+ *
+ * Enable padding modes in the cipher layer.
+ */
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#define MBEDTLS_CIPHER_PADDING_ZEROS
+
+/**
+ * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ *
+ * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve
+ * module. By default all supported curves are enabled.
+ *
+ * Comment macros to disable the curve and functions for it
+ */
+#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#define MBEDTLS_ECP_DP_BP256R1_ENABLED
+#define MBEDTLS_ECP_DP_BP384R1_ENABLED
+#define MBEDTLS_ECP_DP_BP512R1_ENABLED
+#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
+#define MBEDTLS_ECP_DP_CURVE448_ENABLED
+
+/**
+ * \def MBEDTLS_ECP_NIST_OPTIM
+ *
+ * Enable specific 'modulo p' routines for each NIST prime.
+ * Depending on the prime and architecture, makes operations 4 to 8 times
+ * faster on the corresponding curve.
+ *
+ * Comment this macro to disable NIST curves optimisation.
+ */
+#define MBEDTLS_ECP_NIST_OPTIM
+
+/**
+ * \def MBEDTLS_ECP_RESTARTABLE
+ *
+ * Enable "non-blocking" ECC operations that can return early and be resumed.
+ *
+ * This allows various functions to pause by returning
+ * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in Mbed TLS's SSL module,
+ * MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in order
+ * to further progress and eventually complete their operation. This is
+ * controlled through mbedtls_ecp_set_max_ops() which limits the maximum number
+ * of ECC operations a function may perform before pausing; see
+ * mbedtls_ecp_set_max_ops() for more information.
+ *
+ * This is useful in non-threaded environments if you want to avoid blocking
+ * for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
+ *
+ * Uncomment this macro to enable restartable ECC computations.
+ *
+ * \note This option only works with the default software implementation of
+ * elliptic curve functionality. It is incompatible with
+ * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT.
+ */
+//#define MBEDTLS_ECP_RESTARTABLE
+
+/**
+ * \def MBEDTLS_ECDSA_DETERMINISTIC
+ *
+ * Enable deterministic ECDSA (RFC 6979).
+ * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
+ * may result in a compromise of the long-term signing key. This is avoided by
+ * the deterministic variant.
+ *
+ * Requires: MBEDTLS_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define MBEDTLS_ECDSA_DETERMINISTIC
+
+/**
+ * \def MBEDTLS_PK_PARSE_EC_EXTENDED
+ *
+ * Enhance support for reading EC keys using variants of SEC1 not allowed by
+ * RFC 5915 and RFC 5480.
+ *
+ * Currently this means parsing the SpecifiedECDomain choice of EC
+ * parameters (only known groups are supported, not arbitrary domains, to
+ * avoid validation issues).
+ *
+ * Disable if you only need to support RFC 5915 + 5480 key formats.
+ */
+#define MBEDTLS_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def MBEDTLS_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of mbedtls_strerror() in
+ * third party libraries easier when MBEDTLS_ERROR_C is disabled
+ * (no effect when MBEDTLS_ERROR_C is enabled).
+ *
+ * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're
+ * not using mbedtls_strerror() or error_strerror() in your application.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * mbedtls_strerror()
+ */
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+
+/**
+ * \def MBEDTLS_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: MBEDTLS_BIGNUM_C
+ */
+#define MBEDTLS_GENPRIME
+
+/**
+ * \def MBEDTLS_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+//#define MBEDTLS_FS_IO
+
+/**
+ * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * mbedtls_timing_hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+ */
+//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def MBEDTLS_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+ */
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_FORCE_SHA256
+ *
+ * Force the entropy accumulator to use a SHA-256 accumulator instead of the
+ * default SHA-512 based one (if both are available).
+ *
+ * Requires: MBEDTLS_SHA256_C
+ *
+ * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
+ * if you have performance concerns.
+ *
+ * This option is only useful if both MBEDTLS_SHA256_C and
+ * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define MBEDTLS_ENTROPY_FORCE_SHA256
+
+/**
+ * \def MBEDTLS_ENTROPY_NV_SEED
+ *
+ * Enable the non-volatile (NV) seed file-based entropy source.
+ * (Also enables the NV seed read/write functions in the platform layer)
+ *
+ * This is crucial (if not required) on systems that do not have a
+ * cryptographic entropy source (in hardware or kernel) available.
+ *
+ * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C
+ *
+ * \note The read/write functions that are used by the entropy source are
+ * determined in the platform layer, and can be modified at runtime and/or
+ * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used.
+ *
+ * \note If you use the default implementation functions that read a seedfile
+ * with regular fopen(), please make sure you make a seedfile with the
+ * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at
+ * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from
+ * and written to or you will get an entropy source error! The default
+ * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE
+ * bytes from the file.
+ *
+ * \note The entropy collector will write to the seed file before entropy is
+ * given to an external source, to update it.
+ */
+//#define MBEDTLS_ENTROPY_NV_SEED
+
+/* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+ *
+ * In PSA key storage, encode the owner of the key.
+ *
+ * This is only meaningful when building the library as part of a
+ * multi-client service. When you activate this option, you must provide
+ * an implementation of the type psa_key_owner_id_t and a translation
+ * from psa_key_file_id_t to file name in all the storage backends that
+ * you wish to support.
+ *
+ * Note that this option is meant for internal use only and may be removed
+ * without notice.
+ */
+//#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+
+/**
+ * \def MBEDTLS_MEMORY_DEBUG
+ *
+ * Enable debugging of buffer allocator memory issues. Automatically prints
+ * (to stderr) all (fatal) messages on memory allocation issues. Enables
+ * function for 'debug output' of allocated memory.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+//#define MBEDTLS_MEMORY_DEBUG
+
+/**
+ * \def MBEDTLS_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ * GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define MBEDTLS_MEMORY_BACKTRACE
+
+/**
+ * \def MBEDTLS_PK_RSA_ALT_SUPPORT
+ *
+ * Support external private RSA keys (eg from a HSM) in the PK layer.
+ *
+ * Comment this macro to disable support for external private RSA keys.
+ */
+#define MBEDTLS_PK_RSA_ALT_SUPPORT
+
+/**
+ * \def MBEDTLS_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: MBEDTLS_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+#define MBEDTLS_PKCS1_V15
+
+/**
+ * \def MBEDTLS_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define MBEDTLS_PKCS1_V21
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_SPM
+ *
+ * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure
+ * Partition Manager) integration which separates the code into two parts: a
+ * NSPE (Non-Secure Process Environment) and an SPE (Secure Process
+ * Environment).
+ *
+ * Module: library/psa_crypto.c
+ * Requires: MBEDTLS_PSA_CRYPTO_C
+ *
+ */
+//#define MBEDTLS_PSA_CRYPTO_SPM
+
+/**
+ * \def MBEDTLS_PSA_INJECT_ENTROPY
+ *
+ * Enable support for entropy injection at first boot. This feature is
+ * required on systems that do not have a built-in entropy source (TRNG).
+ * This feature is currently not supported on systems that have a built-in
+ * entropy source.
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED
+ *
+ */
+//#define MBEDTLS_PSA_INJECT_ENTROPY
+
+/**
+ * \def MBEDTLS_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem
+ * for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+ */
+//#define MBEDTLS_RSA_NO_CRT
+
+/**
+ * \def MBEDTLS_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+//#define MBEDTLS_SELF_TEST
+
+/**
+ * \def MBEDTLS_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+//#define MBEDTLS_SHA256_SMALLER
+
+/**
+ * \def MBEDTLS_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define MBEDTLS_THREADING_ALT
+
+/**
+ * \def MBEDTLS_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define MBEDTLS_THREADING_PTHREAD
+
+/**
+ * \def MBEDTLS_USE_PSA_CRYPTO
+ *
+ * Make the X.509 and TLS library use PSA for cryptographic operations, see
+ * #MBEDTLS_PSA_CRYPTO_C.
+ *
+ * Note: this option is still in progress, the full X.509 and TLS modules are
+ * not covered yet, but parts that are not ported to PSA yet will still work
+ * as usual, so enabling this option should not break backwards compatibility.
+ *
+ * \warning Support for PSA is still an experimental feature.
+ * Any public API that depends on this option may change
+ * at any time until this warning is removed.
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C.
+ */
+//#define MBEDTLS_USE_PSA_CRYPTO
+
+/**
+ * \def MBEDTLS_VERSION_FEATURES
+ *
+ * Allow run-time checking of compile-time enabled features. Thus allowing users
+ * to check at run-time if the library is for instance compiled with threading
+ * support via mbedtls_version_check_feature().
+ *
+ * Requires: MBEDTLS_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+#define MBEDTLS_VERSION_FEATURES
+
+/* \} name SECTION: mbed TLS feature support */
+
+/**
+ * \name SECTION: mbed TLS modules
+ *
+ * This section enables or disables entire modules in mbed TLS
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module: library/aesni.c
+ * Caller: library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+//#define MBEDTLS_AESNI_C
+
+/**
+ * \def MBEDTLS_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module: library/aes.c
+ * Caller: library/cipher.c
+ * library/pem.c
+ * library/ctr_drbg.c
+ *
+ * This module is required to support the TLS ciphersuites that use the AES
+ * cipher.
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define MBEDTLS_AES_C
+
+/**
+ * \def MBEDTLS_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module: library/arc4.c
+ * Caller: library/cipher.c
+ *
+ * This module is required to support the TLS ciphersuites that use the ARC4
+ * cipher.
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. If possible, we recommend avoidng dependencies on
+ * it, and considering stronger ciphers instead.
+ *
+ */
+#define MBEDTLS_ARC4_C
+
+/**
+ * \def MBEDTLS_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module: library/asn1.c
+ * Caller: library/dhm.c
+ * library/pkcs12.c
+ * library/pkcs5.c
+ * library/pkparse.c
+ */
+#define MBEDTLS_ASN1_PARSE_C
+
+/**
+ * \def MBEDTLS_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module: library/asn1write.c
+ * Caller: library/ecdsa.c
+ * library/pkwrite.c
+ */
+#define MBEDTLS_ASN1_WRITE_C
+
+/**
+ * \def MBEDTLS_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module: library/base64.c
+ * Caller: library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+#define MBEDTLS_BASE64_C
+
+/**
+ * \def MBEDTLS_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module: library/bignum.c
+ * Caller: library/dhm.c
+ * library/ecp.c
+ * library/ecdsa.c
+ * library/rsa.c
+ * library/rsa_internal.c
+ *
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
+ */
+#define MBEDTLS_BIGNUM_C
+
+/**
+ * \def MBEDTLS_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module: library/blowfish.c
+ */
+#define MBEDTLS_BLOWFISH_C
+
+/**
+ * \def MBEDTLS_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module: library/camellia.c
+ * Caller: library/cipher.c
+ *
+ * This module is required to support the TLS ciphersuites that use the
+ * Camellia cipher.
+ */
+#define MBEDTLS_CAMELLIA_C
+
+/**
+ * \def MBEDTLS_ARIA_C
+ *
+ * Enable the ARIA block cipher.
+ *
+ * Module: library/aria.c
+ * Caller: library/cipher.c
+ *
+ * This module is required to support the TLS ciphersuites that use the
+ * ARIA cipher.
+ */
+//#define MBEDTLS_ARIA_C
+
+/**
+ * \def MBEDTLS_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module: library/ccm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module is required to support AES-CCM ciphersuites in TLS.
+ */
+#define MBEDTLS_CCM_C
+
+/**
+ * \def MBEDTLS_CHACHA20_C
+ *
+ * Enable the ChaCha20 stream cipher.
+ *
+ * Module: library/chacha20.c
+ */
+#define MBEDTLS_CHACHA20_C
+
+/**
+ * \def MBEDTLS_CHACHAPOLY_C
+ *
+ * Enable the ChaCha20-Poly1305 AEAD algorithm.
+ *
+ * Module: library/chachapoly.c
+ *
+ * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
+ */
+#define MBEDTLS_CHACHAPOLY_C
+
+/**
+ * \def MBEDTLS_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module: library/cipher.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define MBEDTLS_CIPHER_C
+
+/**
+ * \def MBEDTLS_CMAC_C
+ *
+ * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
+ * ciphers.
+ *
+ * Module: library/cmac.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
+ *
+ */
+#define MBEDTLS_CMAC_C
+
+/**
+ * \def MBEDTLS_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-based random generator.
+ * The CTR_DRBG generator uses AES-256 by default.
+ * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
+ *
+ * Module: library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_AES_C
+ *
+ * This module provides the CTR_DRBG AES random number generator.
+ */
+#define MBEDTLS_CTR_DRBG_C
+
+/**
+ * \def MBEDTLS_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module: library/des.c
+ * Caller: library/pem.c
+ * library/cipher.c
+ *
+ * This module is required to support the TLS ciphersuites that use the DES
+ * cipher.
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers instead.
+ */
+#define MBEDTLS_DES_C
+
+/**
+ * \def MBEDTLS_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle module.
+ *
+ * Module: library/dhm.c
+ *
+ * This module is used by the following key exchanges:
+ * DHE-RSA, DHE-PSK
+ *
+ * \warning Using DHE constitutes a security risk as it
+ * is not possible to validate custom DH parameters.
+ * If possible, it is recommended users should consider
+ * preferring other methods of key exchange.
+ * See dhm.h for more details.
+ *
+ */
+#define MBEDTLS_DHM_C
+
+/**
+ * \def MBEDTLS_ECDH_C
+ *
+ * Enable the elliptic curve Diffie-Hellman library.
+ *
+ * Module: library/ecdh.c
+ *
+ * This module is used by the following key exchanges:
+ * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK
+ *
+ * Requires: MBEDTLS_ECP_C
+ */
+#define MBEDTLS_ECDH_C
+
+/**
+ * \def MBEDTLS_ECDSA_C
+ *
+ * Enable the elliptic curve DSA library.
+ *
+ * Module: library/ecdsa.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ * ECDHE-ECDSA
+ *
+ * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C
+ */
+#define MBEDTLS_ECDSA_C
+
+/**
+ * \def MBEDTLS_ECJPAKE_C
+ *
+ * Enable the elliptic curve J-PAKE library.
+ *
+ * \warning This is currently experimental. EC J-PAKE support is based on the
+ * Thread v1.0.0 specification; incompatible changes to the specification
+ * might still happen. For this reason, this is disabled by default.
+ *
+ * Module: library/ecjpake.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ * ECJPAKE
+ *
+ * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C
+ */
+//#define MBEDTLS_ECJPAKE_C
+
+/**
+ * \def MBEDTLS_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module: library/ecp.c
+ * Caller: library/ecdh.c
+ * library/ecdsa.c
+ * library/ecjpake.c
+ *
+ * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED
+ */
+#define MBEDTLS_ECP_C
+
+/**
+ * \def MBEDTLS_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module: library/entropy.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define MBEDTLS_ENTROPY_C
+
+/**
+ * \def MBEDTLS_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module: library/error.c
+ * Caller:
+ *
+ * This module enables mbedtls_strerror().
+ */
+#define MBEDTLS_ERROR_C
+
+/**
+ * \def MBEDTLS_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module: library/gcm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module is required to support the TLS ciphersuites that use GCM.
+ */
+#define MBEDTLS_GCM_C
+
+/**
+ * \def MBEDTLS_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Warning: the HAVEGE random generator is not suitable for virtualized
+ * environments
+ *
+ * Warning: the HAVEGE random generator is dependent on timing and specific
+ * processor traits. It is therefore not advised to use HAVEGE as
+ * your applications primary random generator or primary entropy pool
+ * input. As a secondary input to your entropy pool, it IS able add
+ * the (limited) extra entropy it provides.
+ *
+ * Module: library/havege.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_TIMING_C
+ *
+ * Uncomment to enable the HAVEGE random generator.
+ */
+//#define MBEDTLS_HAVEGE_C
+
+/**
+ * \def MBEDTLS_HKDF_C
+ *
+ * Enable the HKDF algorithm (RFC 5869).
+ *
+ * Module: library/hkdf.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the Hashed Message Authentication Code
+ * (HMAC)-based key derivation function (HKDF).
+ */
+#define MBEDTLS_HKDF_C
+
+/**
+ * \def MBEDTLS_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module: library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define MBEDTLS_HMAC_DRBG_C
+
+/**
+ * \def MBEDTLS_NIST_KW_C
+ *
+ * Enable the Key Wrapping mode for 128-bit block ciphers,
+ * as defined in NIST SP 800-38F. Only KW and KWP modes
+ * are supported. At the moment, only AES is approved by NIST.
+ *
+ * Module: library/nist_kw.c
+ *
+ * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C
+ */
+//#define MBEDTLS_NIST_KW_C
+
+/**
+ * \def MBEDTLS_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module: library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define MBEDTLS_MD_C
+
+/**
+ * \def MBEDTLS_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module: library/md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+ * \warning MD2 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+//#define MBEDTLS_MD2_C
+
+/**
+ * \def MBEDTLS_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module: library/md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+ * \warning MD4 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+//#define MBEDTLS_MD4_C
+
+/**
+ * \def MBEDTLS_MD5_C
+ *
+ * Enable the MD5 hash algorithm.
+ *
+ * Module: library/md5.c
+ * Caller: library/md.c
+ * library/pem.c
+ *
+ * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2
+ * depending on the handshake parameters. Further, it is used for checking
+ * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded
+ * encrypted keys.
+ *
+ * \warning MD5 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDTLS_MD5_C
+
+/**
+ * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
+ * calls)
+ *
+ * Module: library/memory_buffer_alloc.c
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def MBEDTLS_OID_C
+ *
+ * Enable the OID database.
+ *
+ * Module: library/oid.c
+ * Caller: library/asn1write.c
+ * library/pkcs5.c
+ * library/pkparse.c
+ * library/pkwrite.c
+ * library/rsa.c
+ *
+ * This modules translates between OIDs and internal values.
+ */
+#define MBEDTLS_OID_C
+
+/**
+ * \def MBEDTLS_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module: library/padlock.c
+ * Caller: library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+//#define MBEDTLS_PADLOCK_C
+
+/**
+ * \def MBEDTLS_PEM_PARSE_C
+ *
+ * Enable PEM decoding / parsing.
+ *
+ * Module: library/pem.c
+ * Caller: library/dhm.c
+ * library/pkparse.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+#define MBEDTLS_PEM_PARSE_C
+
+/**
+ * \def MBEDTLS_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module: library/pem.c
+ * Caller: library/pkwrite.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+#define MBEDTLS_PEM_WRITE_C
+
+/**
+ * \def MBEDTLS_PK_C
+ *
+ * Enable the generic public (asymetric) key layer.
+ *
+ * Module: library/pk.c
+ *
+ * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define MBEDTLS_PK_C
+
+/**
+ * \def MBEDTLS_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module: library/pkparse.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define MBEDTLS_PK_PARSE_C
+
+/**
+ * \def MBEDTLS_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module: library/pkwrite.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define MBEDTLS_PK_WRITE_C
+
+/**
+ * \def MBEDTLS_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module: library/pkcs5.c
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+#define MBEDTLS_PKCS5_C
+
+/**
+ * \def MBEDTLS_PKCS12_C
+ *
+ * Enable PKCS#12 PBE functions.
+ * Adds algorithms for parsing PKCS#8 encrypted private keys
+ *
+ * Module: library/pkcs12.c
+ * Caller: library/pkparse.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C
+ * Can use: MBEDTLS_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+#define MBEDTLS_PKCS12_C
+
+/**
+ * \def MBEDTLS_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
+ *
+ * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT
+ * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * \note This abstraction layer must be enabled on Windows (including MSYS2)
+ * as other module rely on it for a fixed snprintf implementation.
+ *
+ * Module: library/platform.c
+ * Caller: Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+//#define MBEDTLS_PLATFORM_C
+
+/**
+ * \def MBEDTLS_POLY1305_C
+ *
+ * Enable the Poly1305 MAC algorithm.
+ *
+ * Module: library/poly1305.c
+ * Caller: library/chachapoly.c
+ */
+#define MBEDTLS_POLY1305_C
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_C
+ *
+ * Enable the Platform Security Architecture cryptography API.
+ *
+ * Module: library/psa_crypto.c
+ *
+ * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C
+ *
+ */
+#define MBEDTLS_PSA_CRYPTO_C
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_STORAGE_C
+ *
+ * Enable the Platform Security Architecture persistent key storage.
+ *
+ * Module: library/psa_crypto_storage.c
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C,
+ * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of
+ * the PSA ITS interface
+ */
+#define MBEDTLS_PSA_CRYPTO_STORAGE_C
+
+/**
+ * \def MBEDTLS_PSA_ITS_FILE_C
+ *
+ * Enable the emulation of the Platform Security Architecture
+ * Internal Trusted Storage (PSA ITS) over files.
+ *
+ * Module: library/psa_its_file.c
+ *
+ * Requires: MBEDTLS_FS_IO
+ */
+//#define MBEDTLS_PSA_ITS_FILE_C
+
+/**
+ * \def MBEDTLS_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module: library/ripemd160.c
+ * Caller: library/md.c
+ *
+ */
+#define MBEDTLS_RIPEMD160_C
+
+/**
+ * \def MBEDTLS_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module: library/rsa.c
+ * library/rsa_internal.c
+ *
+ * This module is used by the following key exchanges:
+ * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK
+ *
+ * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C
+ */
+#define MBEDTLS_RSA_C
+
+/**
+ * \def MBEDTLS_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module: library/sha1.c
+ * Caller: library/md.c
+ *
+ * This module is required for SSL/TLS up to version 1.1, for TLS 1.2
+ * depending on the handshake parameters, and for SHA1-signed certificates.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use constitutes
+ * a security risk. If possible, we recommend avoiding dependencies
+ * on it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDTLS_SHA1_C
+
+/**
+ * \def MBEDTLS_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module: library/sha256.c
+ * Caller: library/entropy.c
+ * library/md.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ * This module is required for the SSL/TLS 1.2 PRF function.
+ */
+#define MBEDTLS_SHA256_C
+
+/**
+ * \def MBEDTLS_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module: library/sha512.c
+ * Caller: library/entropy.c
+ * library/md.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define MBEDTLS_SHA512_C
+
+/**
+ * \def MBEDTLS_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default mbed TLS assumes it is used in a non-threaded environment or that
+ * contexts are not shared between threads. If you do intend to use contexts
+ * between threads, you will need to enable this layer to prevent race
+ * conditions. See also our Knowledge Base article about threading:
+ * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading
+ *
+ * Module: library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either MBEDTLS_THREADING_ALT or
+ * MBEDTLS_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within mbed TLS
+ */
+//#define MBEDTLS_THREADING_C
+
+/**
+ * \def MBEDTLS_TIMING_C
+ *
+ * Enable the semi-portable timing interface.
+ *
+ * \note The provided implementation only works on POSIX/Unix (including Linux,
+ * BSD and OS X) and Windows. On other platforms, you can either disable that
+ * module and provide your own implementations of the callbacks needed by Mbed
+ * TLS's \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and
+ * provide your own implementation of the whole module by setting
+ * \c MBEDTLS_TIMING_ALT in the current file.
+ *
+ * \note See also our Knowledge Base article about porting to a new
+ * environment:
+ * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
+ *
+ * Module: library/timing.c
+ * Caller: library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+//#define MBEDTLS_TIMING_C
+
+/**
+ * \def MBEDTLS_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module: library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define MBEDTLS_VERSION_C
+
+/**
+ * \def MBEDTLS_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module: library/xtea.c
+ * Caller:
+ */
+#define MBEDTLS_XTEA_C
+
+/* \} name SECTION: mbed TLS modules */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ *
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ * \{
+ */
+
+/* MPI / BIGNUM options */
+//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
+//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */
+
+/* CTR_DRBG options */
+//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
+
+/* HMAC_DRBG options */
+//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+
+/* ECP options */
+//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
+//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */
+//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */
+
+/* Entropy options */
+//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
+//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
+//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */
+
+/* Memory buffer allocator options */
+//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
+
+/* Platform options */
+//#define MBEDTLS_PLATFORM_STD_MEM_HDR <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */
+/* Note: your snprintf must correctly zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */
+
+/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
+/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
+//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */
+/* Note: your snprintf must correctly zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+
+/**
+ * Uncomment the macro to let mbed TLS use your alternate implementation of
+ * mbedtls_platform_zeroize(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * mbedtls_platform_zeroize() is a widely used function across the library to
+ * zero a block of memory. The implementation is expected to be secure in the
+ * sense that it has been written to prevent the compiler from removing calls
+ * to mbedtls_platform_zeroize() as part of redundant code elimination
+ * optimizations. However, it is difficult to guarantee that calls to
+ * mbedtls_platform_zeroize() will not be optimized by the compiler as older
+ * versions of the C language standards do not provide a secure implementation
+ * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to
+ * configure their own implementation of mbedtls_platform_zeroize(), for
+ * example by using directives specific to their compiler, features from newer
+ * C standards (e.g using memset_s() in C11) or calling a secure memset() from
+ * their system (e.g explicit_bzero() in BSD).
+ */
+//#define MBEDTLS_PLATFORM_ZEROIZE_ALT
+
+/**
+ * Uncomment the macro to let Mbed TLS use your alternate implementation of
+ * mbedtls_platform_gmtime_r(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * gmtime() is not a thread-safe function as defined in the C standard. The
+ * library will try to use safer implementations of this function, such as
+ * gmtime_r() when available. However, if Mbed TLS cannot identify the target
+ * system, the implementation of mbedtls_platform_gmtime_r() will default to
+ * using the standard gmtime(). In this case, calls from the library to
+ * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex
+ * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the
+ * library are also guarded with this mutex to avoid race conditions. However,
+ * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will
+ * unconditionally use the implementation for mbedtls_platform_gmtime_r()
+ * supplied at compile time.
+ */
+//#define MBEDTLS_PLATFORM_GMTIME_R_ALT
+
+/* \} name SECTION: Customisation configuration options */
+
+/* Target and application specific configurations
+ *
+ * Allow user to override any previous default.
+ *
+ */
+#if defined(MBEDTLS_USER_CONFIG_FILE)
+#include MBEDTLS_USER_CONFIG_FILE
+#endif
+
+#include "mbedtls/check_config.h"
+
+#endif /* CONFIG_MBED_CRYPTO_H */
diff --git a/components/service/crypto/provider/mbedcrypto/crypto_provider.c b/components/service/crypto/provider/mbedcrypto/crypto_provider.c
new file mode 100644
index 000000000..e8c77e90a
--- /dev/null
+++ b/components/service/crypto/provider/mbedcrypto/crypto_provider.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include <service/crypto/provider/mbedcrypto/crypto_provider.h>
+#include <service/crypto/provider/serializer/crypto_provider_serializer.h>
+#include <service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h>
+#include <service/secure_storage/client/psa/its/its_client.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <psa/crypto.h>
+
+/* Service request handlers */
+static rpc_status_t nop_handler(void *context, struct call_req* req);
+static rpc_status_t generate_key_handler(void *context, struct call_req* req);
+static rpc_status_t destroy_key_handler(void *context, struct call_req* req);
+static rpc_status_t open_key_handler(void *context, struct call_req* req);
+static rpc_status_t close_key_handler(void *context, struct call_req* req);
+static rpc_status_t export_key_handler(void *context, struct call_req* req);
+static rpc_status_t export_public_key_handler(void *context, struct call_req* req);
+static rpc_status_t import_key_handler(void *context, struct call_req* req);
+static rpc_status_t sign_hash_handler(void *context, struct call_req* req);
+static rpc_status_t verify_hash_handler(void *context, struct call_req* req);
+static rpc_status_t asymmetric_decrypt_handler(void *context, struct call_req* req);
+static rpc_status_t asymmetric_encrypt_handler(void *context, struct call_req* req);
+static rpc_status_t generate_random_handler(void *context, struct call_req* req);
+
+/* Handler mapping table for service */
+static const struct service_handler handler_table[] = {
+ {TS_CRYPTO_OPCODE_NOP, nop_handler},
+ {TS_CRYPTO_OPCODE_GENERATE_KEY, generate_key_handler},
+ {TS_CRYPTO_OPCODE_DESTROY_KEY, destroy_key_handler},
+ {TS_CRYPTO_OPCODE_OPEN_KEY, open_key_handler},
+ {TS_CRYPTO_OPCODE_CLOSE_KEY, close_key_handler},
+ {TS_CRYPTO_OPCODE_EXPORT_KEY, export_key_handler},
+ {TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY, export_public_key_handler},
+ {TS_CRYPTO_OPCODE_IMPORT_KEY, import_key_handler},
+ {TS_CRYPTO_OPCODE_SIGN_HASH, sign_hash_handler},
+ {TS_CRYPTO_OPCODE_VERIFY_HASH, verify_hash_handler},
+ {TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT, asymmetric_decrypt_handler},
+ {TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, asymmetric_encrypt_handler},
+ {TS_CRYPTO_OPCODE_GENERATE_RANDOM, generate_random_handler}
+};
+
+struct call_ep *mbed_crypto_provider_init(struct mbed_crypto_provider *context,
+ struct rpc_caller *storage_provider)
+{
+ struct call_ep *call_ep = NULL;
+
+ /*
+ * A storage provider is required for persistent key storage. As this
+ * is a mandatory feature of the crypto service, insist on a storage
+ * provider being available.
+ */
+ if (context && storage_provider) {
+
+ service_provider_init(&context->base_provider, context,
+ handler_table, sizeof(handler_table)/sizeof(struct service_handler));
+
+ service_set_default_serializer(&context->base_provider,
+ pb_crypto_provider_serializer_instance());
+
+ if ((psa_its_client_init(storage_provider) == PSA_SUCCESS) &&
+ (psa_crypto_init() == PSA_SUCCESS))
+ call_ep = service_provider_get_call_ep(&context->base_provider);
+ }
+
+ return call_ep;
+}
+
+void mbed_crypto_provider_deinit(struct mbed_crypto_provider *context)
+{
+ (void)context;
+}
+
+static inline const struct crypto_provider_serializer* get_crypto_serializer(const struct call_req *req)
+{
+ return (const struct crypto_provider_serializer*)call_req_get_serializer(req);
+}
+
+static rpc_status_t nop_handler(void *context, struct call_req* req)
+{
+ /* Responds to a request by returning success */
+ rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
+ psa_status_t psa_status = PSA_SUCCESS;
+
+ (void)context;
+ call_req_set_opstatus(req, psa_status);
+
+ return rpc_status;
+}
+
+static rpc_status_t generate_key_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ rpc_status = serializer->deserialize_generate_key_req(req_buf, &attributes);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ psa_key_handle_t handle;
+
+ psa_status = psa_generate_key(&attributes, &handle);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_generate_key_resp(resp_buf, handle);
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ psa_reset_key_attributes(&attributes);
+
+ return rpc_status;
+}
+
+static rpc_status_t destroy_key_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ psa_key_handle_t handle;
+
+ rpc_status = serializer->deserialize_destroy_key_req(req_buf, &handle);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+
+ psa_status = psa_destroy_key(handle);
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t open_key_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ psa_key_id_t id;
+
+ rpc_status = serializer->deserialize_open_key_req(req_buf, &id);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ psa_key_handle_t handle;
+
+ psa_status = psa_open_key(id, &handle);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_open_key_resp(resp_buf, handle);
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t close_key_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ psa_key_handle_t handle;
+
+ rpc_status = serializer->deserialize_close_key_req(req_buf, &handle);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+
+ psa_status = psa_close_key(handle);
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t export_key_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ psa_key_handle_t handle;
+
+ rpc_status = serializer->deserialize_export_key_req(req_buf, &handle);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_status = psa_get_key_attributes(handle, &attributes);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ size_t max_export_size = PSA_KEY_EXPORT_MAX_SIZE(
+ psa_get_key_type(&attributes),
+ psa_get_key_bits(&attributes));
+
+ uint8_t *key_buffer = malloc(max_export_size);
+
+ if (key_buffer) {
+
+ size_t export_size;
+ psa_status = psa_export_key(handle, key_buffer, max_export_size, &export_size);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_export_key_resp(resp_buf, key_buffer, export_size);
+ }
+
+ free(key_buffer);
+ }
+ else {
+ /* Failed to allocate key buffer */
+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+ }
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ psa_reset_key_attributes(&attributes);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t export_public_key_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ psa_key_handle_t handle;
+
+ rpc_status = serializer->deserialize_export_public_key_req(req_buf, &handle);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_status = psa_get_key_attributes(handle, &attributes);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ size_t max_export_size = PSA_KEY_EXPORT_MAX_SIZE(
+ PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_get_key_type(&attributes)),
+ psa_get_key_bits(&attributes));
+
+ uint8_t *key_buffer = malloc(max_export_size);
+
+ if (key_buffer) {
+
+ size_t export_size;
+ psa_status = psa_export_public_key(handle, key_buffer, max_export_size, &export_size);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_export_public_key_resp(resp_buf, key_buffer, export_size);
+ }
+
+ free(key_buffer);
+ }
+ else {
+ /* Failed to allocate key buffer */
+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+ }
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ psa_reset_key_attributes(&attributes);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t import_key_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ size_t key_data_len = serializer->max_deserialised_parameter_size(req_buf);
+ uint8_t *key_buffer = malloc(key_data_len);
+
+ if (key_buffer) {
+
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ rpc_status = serializer->deserialize_import_key_req(req_buf, &attributes, key_buffer, &key_data_len);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ psa_key_handle_t handle;
+
+ psa_status = psa_import_key(&attributes, key_buffer, key_data_len, &handle);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_import_key_resp(resp_buf, handle);
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ psa_reset_key_attributes(&attributes);
+ free(key_buffer);
+ }
+ else {
+
+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t sign_hash_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ psa_key_handle_t handle;
+ psa_algorithm_t alg;
+ size_t hash_len = PSA_HASH_MAX_SIZE;
+ uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
+
+ rpc_status = serializer->deserialize_sign_hash_req(req_buf, &handle, &alg, hash_buffer, &hash_len);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ size_t sig_len;
+ uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
+
+ psa_status = psa_sign_hash(handle, alg,
+ hash_buffer, hash_len,
+ sig_buffer, sizeof(sig_buffer), &sig_len);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_sign_hash_resp(resp_buf, sig_buffer, sig_len);
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t verify_hash_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ psa_key_handle_t handle;
+ psa_algorithm_t alg;
+ size_t hash_len = PSA_HASH_MAX_SIZE;
+ uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
+ size_t sig_len = PSA_SIGNATURE_MAX_SIZE;
+ uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
+
+ rpc_status = serializer->deserialize_verify_hash_req(req_buf, &handle, &alg,
+ hash_buffer, &hash_len,
+ sig_buffer, &sig_len);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+
+ psa_status = psa_verify_hash(handle, alg,
+ hash_buffer, hash_len,
+ sig_buffer, sig_len);
+
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t asymmetric_decrypt_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ size_t max_param_size = serializer->max_deserialised_parameter_size(req_buf);
+ (void)context;
+
+ psa_key_handle_t handle;
+ psa_algorithm_t alg;
+ size_t ciphertext_len = max_param_size;
+ uint8_t *ciphertext_buffer = malloc(ciphertext_len);
+ size_t salt_len = max_param_size;
+ uint8_t *salt_buffer = malloc(salt_len);
+
+ if (ciphertext_buffer && salt_buffer) {
+
+ rpc_status = serializer->deserialize_asymmetric_decrypt_req(req_buf,
+ &handle, &alg,
+ ciphertext_buffer, &ciphertext_len,
+ salt_buffer, &salt_len);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_status = psa_get_key_attributes(handle, &attributes);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ size_t max_decrypt_size = PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(
+ psa_get_key_type(&attributes),
+ psa_get_key_bits(&attributes),
+ alg);
+
+ size_t plaintext_len;
+ uint8_t *plaintext_buffer = malloc(max_decrypt_size);
+
+ if (plaintext_buffer) {
+
+ psa_status = psa_asymmetric_decrypt(handle, alg,
+ ciphertext_buffer, ciphertext_len,
+ salt_buffer, salt_len,
+ plaintext_buffer, max_decrypt_size, &plaintext_len);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_asymmetric_decrypt_resp(resp_buf,
+ plaintext_buffer, plaintext_len);
+ }
+
+ free(plaintext_buffer);
+ }
+ else {
+ /* Failed to allocate ouptput buffer */
+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+ }
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ psa_reset_key_attributes(&attributes);
+ }
+ }
+ else {
+ /* Failed to allocate buffers */
+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+ }
+
+ free(ciphertext_buffer);
+ free(salt_buffer);
+
+ return rpc_status;
+}
+
+static rpc_status_t asymmetric_encrypt_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ size_t max_param_size = serializer->max_deserialised_parameter_size(req_buf);
+ (void)context;
+
+ psa_key_handle_t handle;
+ psa_algorithm_t alg;
+ size_t plaintext_len = max_param_size;
+ uint8_t *plaintext_buffer = malloc(plaintext_len);
+ size_t salt_len = max_param_size;
+ uint8_t *salt_buffer = malloc(salt_len);
+
+ if (plaintext_buffer && salt_buffer) {
+
+ rpc_status = serializer->deserialize_asymmetric_encrypt_req(req_buf,
+ &handle, &alg,
+ plaintext_buffer, &plaintext_len,
+ salt_buffer, &salt_len);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_status = psa_get_key_attributes(handle, &attributes);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ size_t max_encrypt_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(
+ psa_get_key_type(&attributes),
+ psa_get_key_bits(&attributes),
+ alg);
+
+ size_t ciphertext_len;
+ uint8_t *ciphertext_buffer = malloc(max_encrypt_size);
+
+ if (ciphertext_buffer) {
+
+ psa_status = psa_asymmetric_encrypt(handle, alg,
+ plaintext_buffer, plaintext_len,
+ salt_buffer, salt_len,
+ ciphertext_buffer, max_encrypt_size, &ciphertext_len);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_asymmetric_encrypt_resp(resp_buf,
+ ciphertext_buffer, ciphertext_len);
+ }
+
+ free(ciphertext_buffer);
+ }
+ else {
+ /* Failed to allocate ouptput buffer */
+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+ }
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ psa_reset_key_attributes(&attributes);
+ }
+ }
+ else {
+ /* Failed to allocate buffers */
+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+ }
+
+ free(plaintext_buffer);
+ free(salt_buffer);
+
+ return rpc_status;
+}
+
+static rpc_status_t generate_random_handler(void *context, struct call_req* req)
+{
+ rpc_status_t rpc_status;
+ struct call_param_buf *req_buf = call_req_get_req_buf(req);
+ const struct crypto_provider_serializer *serializer = get_crypto_serializer(req);
+ (void)context;
+
+ size_t output_size;
+
+ rpc_status = serializer->deserialize_generate_random_req(req_buf, &output_size);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status;
+ uint8_t *output_buffer = malloc(output_size);
+
+ if (output_buffer) {
+
+ psa_status = psa_generate_random(output_buffer, output_size);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_generate_random_resp(resp_buf,
+ output_buffer, output_size);
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ free(output_buffer);
+ }
+ else {
+ /* Failed to allocate output buffer */
+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+ }
+ }
+
+ return rpc_status;
+} \ No newline at end of file
diff --git a/components/service/crypto/provider/mbedcrypto/crypto_provider.h b/components/service/crypto/provider/mbedcrypto/crypto_provider.h
new file mode 100644
index 000000000..856867d07
--- /dev/null
+++ b/components/service/crypto/provider/mbedcrypto/crypto_provider.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MBED_CRYPTO_PROVIDER_H
+#define MBED_CRYPTO_PROVIDER_H
+
+#include <rpc/common/endpoint/call_ep.h>
+#include <rpc_caller.h>
+#include <service/common/provider/service_provider.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct mbed_crypto_provider
+{
+ struct service_provider base_provider;
+};
+
+/*
+ * Initializes an instance of the crypto service provider that uses the
+ * Mbed Crypto library to implement crypto operations. Secure storage
+ * for persistent keys needs to be provided by a suitable storage
+ * provider, accessed using the secure storage service access protocol
+ * using the provided rpc_caller. Any rpc endpoint discovery and
+ * session establishment should have been performed prior to initializing
+ * the mbed_crypto_provider. On successfully initializing the provider,
+ * a pointer to the call_ep for the service is returned.
+ */
+struct call_ep *mbed_crypto_provider_init(struct mbed_crypto_provider *context,
+ struct rpc_caller *storage_provider);
+
+/*
+ * When operation of the provider is no longer required, this function
+ * frees any resource used by the previously initialized provider instance.
+ */
+void mbed_crypto_provider_deinit(struct mbed_crypto_provider *context);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MBED_CRYPTO_PROVIDER_H */
diff --git a/components/service/crypto/provider/mbedcrypto/entropy_source/mock/component.cmake b/components/service/crypto/provider/mbedcrypto/entropy_source/mock/component.cmake
new file mode 100644
index 000000000..cb48329b5
--- /dev/null
+++ b/components/service/crypto/provider/mbedcrypto/entropy_source/mock/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/mock_entropy_source.c"
+ )
diff --git a/components/service/crypto/provider/mbedcrypto/entropy_source/mock/mock_entropy_source.c b/components/service/crypto/provider/mbedcrypto/entropy_source/mock/mock_entropy_source.c
new file mode 100644
index 000000000..f76448170
--- /dev/null
+++ b/components/service/crypto/provider/mbedcrypto/entropy_source/mock/mock_entropy_source.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <mbedtls/entropy_poll.h>
+#include <stdint.h>
+
+/*
+ * A mock entropy source without any hardware dependencies. Should not be
+ * used in production deployments.
+ */
+int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen)
+{
+ ((void) data);
+ ((void) output);
+ *olen = 0;
+
+ if (len < sizeof(unsigned char) )
+ return (0);
+
+ *olen = sizeof(unsigned char);
+
+ return (0);
+}
diff --git a/components/service/crypto/provider/serializer/crypto_provider_serializer.h b/components/service/crypto/provider/serializer/crypto_provider_serializer.h
new file mode 100644
index 000000000..de7a8731f
--- /dev/null
+++ b/components/service/crypto/provider/serializer/crypto_provider_serializer.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CRYPTO_PROVIDER_SERIALIZER_H
+#define CRYPTO_PROVIDER_SERIALIZER_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <rpc/common/endpoint/call_ep.h>
+
+/* Provides a common interface for parameter serialization operations
+ * for the crypto service provider. Allows alternative serialization
+ * protocols to be used without hard-wiring a particular protocol
+ * into the service provider code. A concrete serializer must
+ * implement this interface.
+ */
+struct crypto_provider_serializer {
+
+ /* Returns the maximum deserialized parameter size that could
+ * be encoded in a request buffer. Used for determining worst-case
+ * buffer size without having to actually deserialize the message.
+ */
+ size_t (*max_deserialised_parameter_size)(const struct call_param_buf *req_buf);
+
+ /* Operation: generate_key */
+ rpc_status_t (*deserialize_generate_key_req)(const struct call_param_buf *req_buf,
+ psa_key_attributes_t *attributes);
+
+ rpc_status_t (*serialize_generate_key_resp)(struct call_param_buf *resp_buf,
+ psa_key_handle_t handle);
+
+ /* Operation: destroy_key */
+ rpc_status_t (*deserialize_destroy_key_req)(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle);
+
+ /* Operation: open_key */
+ rpc_status_t (*deserialize_open_key_req)(const struct call_param_buf *req_buf,
+ psa_key_id_t *id);
+
+ rpc_status_t (*serialize_open_key_resp)(struct call_param_buf *resp_buf,
+ psa_key_handle_t handle);
+
+ /* Operation: close_key */
+ rpc_status_t (*deserialize_close_key_req)(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle);
+
+ /* Operation: export_key */
+ rpc_status_t (*deserialize_export_key_req)(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle);
+
+ rpc_status_t (*serialize_export_key_resp)(struct call_param_buf *resp_buf,
+ const uint8_t *data, size_t data_len);
+
+ /* Operation: export_public_key */
+ rpc_status_t (*deserialize_export_public_key_req)(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle);
+
+ rpc_status_t (*serialize_export_public_key_resp)(struct call_param_buf *resp_buf,
+ const uint8_t *data, size_t data_len);
+
+ /* Operation: import_key */
+ rpc_status_t (*deserialize_import_key_req)(const struct call_param_buf *req_buf,
+ psa_key_attributes_t *attributes,
+ uint8_t *data, size_t *data_len);
+
+ rpc_status_t (*serialize_import_key_resp)(struct call_param_buf *resp_buf,
+ psa_key_handle_t handle);
+
+ /* Operation: sign_hash */
+ rpc_status_t (*deserialize_sign_hash_req)(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle, psa_algorithm_t *alg,
+ uint8_t *hash, size_t *hash_len);
+
+ rpc_status_t (*serialize_sign_hash_resp)(struct call_param_buf *resp_buf,
+ const uint8_t *sig, size_t sig_len);
+
+ /* Operation: verify_hash */
+ rpc_status_t (*deserialize_verify_hash_req)(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle, psa_algorithm_t *alg,
+ uint8_t *hash, size_t *hash_len,
+ uint8_t *sig, size_t *sig_len);
+
+ /* Operation: asymmetric_decrypt */
+ rpc_status_t (*deserialize_asymmetric_decrypt_req)(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle, psa_algorithm_t *alg,
+ uint8_t *ciphertext, size_t *ciphertext_len,
+ uint8_t *salt, size_t *salt_len);
+
+ rpc_status_t (*serialize_asymmetric_decrypt_resp)(struct call_param_buf *resp_buf,
+ const uint8_t *plaintext, size_t plaintext_len);
+
+ /* Operation: asymmetric_encrypt */
+ rpc_status_t (*deserialize_asymmetric_encrypt_req)(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle, psa_algorithm_t *alg,
+ uint8_t *plaintext, size_t *plaintext_len,
+ uint8_t *salt, size_t *salt_len);
+
+ rpc_status_t (*serialize_asymmetric_encrypt_resp)(struct call_param_buf *resp_buf,
+ const uint8_t *ciphertext, size_t ciphertext_len);
+
+ /* Operation: generate_random */
+ rpc_status_t (*deserialize_generate_random_req)(const struct call_param_buf *req_buf,
+ size_t *size);
+
+ rpc_status_t (*serialize_generate_random_resp)(struct call_param_buf *resp_buf,
+ const uint8_t *output, size_t output_len);
+};
+
+#endif /* CRYPTO_PROVIDER_SERIALIZER_H */
diff --git a/components/service/crypto/provider/serializer/protobuf/component.cmake b/components/service/crypto/provider/serializer/protobuf/component.cmake
new file mode 100644
index 000000000..2a075b74d
--- /dev/null
+++ b/components/service/crypto/provider/serializer/protobuf/component.cmake
@@ -0,0 +1,20 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/pb_crypto_provider_serializer.c"
+ "${CMAKE_CURRENT_LIST_DIR}/pb_key_attributes_translator.c"
+ )
+
+
+target_include_directories(${TGT}
+ PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}"
+ )
diff --git a/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c
new file mode 100644
index 000000000..2cf38fee8
--- /dev/null
+++ b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <service/common/serializer/protobuf/pb_helper.h>
+#include <service/crypto/protobuf/generate_key.pb.h>
+#include <service/crypto/protobuf/open_key.pb.h>
+#include <service/crypto/protobuf/close_key.pb.h>
+#include <service/crypto/protobuf/destroy_key.pb.h>
+#include <service/crypto/protobuf/export_key.pb.h>
+#include <service/crypto/protobuf/export_public_key.pb.h>
+#include <service/crypto/protobuf/import_key.pb.h>
+#include <service/crypto/protobuf/sign_hash.pb.h>
+#include <service/crypto/protobuf/verify_hash.pb.h>
+#include <service/crypto/protobuf/asymmetric_decrypt.pb.h>
+#include <service/crypto/protobuf/asymmetric_encrypt.pb.h>
+#include <service/crypto/protobuf/generate_random.pb.h>
+#include <pb_decode.h>
+#include <pb_encode.h>
+#include <psa/crypto.h>
+#include "pb_key_attributes_translator.h"
+#include "pb_crypto_provider_serializer.h"
+
+/* Returns the maximum possible deserialized parameter size for a protobuf encoded message. */
+static size_t max_deserialised_parameter_size(const struct call_param_buf *req_buf)
+{
+ /*
+ * Assume that a deserialized parameter must be the same size or smalled than the
+ * entire serialized message.
+ */
+ return req_buf->data_len;
+}
+
+/* Operation: generate_key */
+static rpc_status_t deserialize_generate_key_req(const struct call_param_buf *req_buf,
+ psa_key_attributes_t *attributes)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_GenerateKeyIn recv_msg = ts_crypto_GenerateKeyIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_GenerateKeyIn_fields, &recv_msg) && recv_msg.has_attributes) {
+
+ pb_crypto_provider_translate_key_attributes(attributes, &recv_msg.attributes);
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_generate_key_resp(struct call_param_buf *resp_buf,
+ psa_key_handle_t handle)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_GenerateKeyOut resp_msg = ts_crypto_GenerateKeyOut_init_default;
+ resp_msg.handle = handle;
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_GenerateKeyOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_GenerateKeyOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ return rpc_status;
+}
+
+/* Operation: destroy_key */
+static rpc_status_t deserialize_destroy_key_req(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_DestroyKeyIn recv_msg = ts_crypto_DestroyKeyIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_DestroyKeyIn_fields, &recv_msg)) {
+
+ *handle = recv_msg.handle;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Operation: open_key */
+static rpc_status_t deserialize_open_key_req(const struct call_param_buf *req_buf, psa_key_id_t *id)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_OpenKeyIn recv_msg = ts_crypto_OpenKeyIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_OpenKeyIn_fields, &recv_msg)) {
+
+ *id = recv_msg.id;
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_open_key_resp(struct call_param_buf *resp_buf,
+ psa_key_handle_t handle)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_OpenKeyOut resp_msg = ts_crypto_OpenKeyOut_init_default;
+ resp_msg.handle = handle;
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_OpenKeyOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_OpenKeyOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ return rpc_status;
+}
+
+/* Operation: close_key */
+static rpc_status_t deserialize_close_key_req(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_CloseKeyIn recv_msg = ts_crypto_CloseKeyIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_CloseKeyIn_fields, &recv_msg)) {
+
+ *handle = recv_msg.handle;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Operation: export_key */
+static rpc_status_t deserialize_export_key_req(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_ExportKeyIn recv_msg = ts_crypto_ExportKeyIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_ExportKeyIn_fields, &recv_msg)) {
+
+ *handle = recv_msg.handle;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_export_key_resp(struct call_param_buf *resp_buf,
+ const uint8_t *data, size_t data_len)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_ExportKeyOut resp_msg = ts_crypto_ExportKeyOut_init_default;
+ pb_bytes_array_t *key_buffer = pb_malloc_byte_array(data_len);
+
+ memcpy(&key_buffer->bytes, data, data_len);
+ resp_msg.data = pb_out_byte_array(key_buffer);
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_ExportKeyOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_ExportKeyOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ free(key_buffer);
+
+ return rpc_status;
+}
+
+/* Operation: export_public_key */
+static rpc_status_t deserialize_export_public_key_req(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_ExportPublicKeyIn recv_msg = ts_crypto_ExportPublicKeyIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_ExportPublicKeyIn_fields, &recv_msg)) {
+
+ *handle = recv_msg.handle;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_export_public_key_resp(struct call_param_buf *resp_buf,
+ const uint8_t *data, size_t data_len)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_ExportPublicKeyOut resp_msg = ts_crypto_ExportPublicKeyOut_init_default;
+
+ pb_bytes_array_t *key_buffer = pb_malloc_byte_array(data_len);
+ resp_msg.data = pb_out_byte_array(key_buffer);
+ memcpy(&key_buffer->bytes, data, data_len);
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_ExportPublicKeyOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_ExportPublicKeyOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ free(key_buffer);
+
+ return rpc_status;
+}
+
+/* Operation: import_key */
+static rpc_status_t deserialize_import_key_req(const struct call_param_buf *req_buf,
+ psa_key_attributes_t *attributes, uint8_t *data, size_t *data_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_ImportKeyIn recv_msg = ts_crypto_ImportKeyIn_init_default;
+
+ pb_bytes_array_t *key_buffer = pb_malloc_byte_array(*data_len);
+ recv_msg.data = pb_in_byte_array(key_buffer);
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_ImportKeyIn_fields, &recv_msg) &&
+ recv_msg.has_attributes &&
+ (key_buffer->size <= *data_len)) {
+
+ pb_crypto_provider_translate_key_attributes(attributes, &recv_msg.attributes);
+
+ memcpy(data, &key_buffer->bytes, key_buffer->size);
+ *data_len = key_buffer->size;
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ free(key_buffer);
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_import_key_resp(struct call_param_buf *resp_buf,
+ psa_key_handle_t handle)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_ImportKeyOut resp_msg = ts_crypto_ImportKeyOut_init_default;
+ resp_msg.handle = handle;
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_ImportKeyOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_ImportKeyOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ return rpc_status;
+}
+
+/* Operation: sign_hash */
+static rpc_status_t deserialize_sign_hash_req(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle, psa_algorithm_t *alg,
+ uint8_t *hash, size_t *hash_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_SignHashIn recv_msg = ts_crypto_SignHashIn_init_default;
+
+ pb_bytes_array_t *hash_buffer = pb_malloc_byte_array(*hash_len);
+ recv_msg.hash = pb_in_byte_array(hash_buffer);
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_SignHashIn_fields, &recv_msg)) {
+
+ *handle = recv_msg.handle;
+ *alg = recv_msg.alg;
+
+ memcpy(hash, &hash_buffer->bytes, hash_buffer->size);
+ *hash_len = hash_buffer->size;
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ free(hash_buffer);
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_sign_hash_resp(struct call_param_buf *resp_buf,
+ const uint8_t *sig, size_t sig_len)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_SignHashOut resp_msg = ts_crypto_SignHashOut_init_default;
+
+ pb_bytes_array_t *sig_buffer = pb_malloc_byte_array(sig_len);
+ resp_msg.signature = pb_out_byte_array(sig_buffer);
+ memcpy(&sig_buffer->bytes, sig, sig_len);
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_SignHashOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_SignHashOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ free(sig_buffer);
+
+ return rpc_status;
+}
+
+/* Operation: verify_hash */
+static rpc_status_t deserialize_verify_hash_req(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle, psa_algorithm_t *alg,
+ uint8_t *hash, size_t *hash_len,
+ uint8_t *sig, size_t *sig_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_VerifyHashIn recv_msg = ts_crypto_VerifyHashIn_init_default;
+
+ pb_bytes_array_t *hash_buffer = pb_malloc_byte_array(*hash_len);
+ recv_msg.hash = pb_in_byte_array(hash_buffer);
+
+ pb_bytes_array_t *sig_buffer = pb_malloc_byte_array(*sig_len);
+ recv_msg.signature = pb_in_byte_array(sig_buffer);
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_VerifyHashIn_fields, &recv_msg)) {
+
+ *handle = recv_msg.handle;
+ *alg = recv_msg.alg;
+
+ memcpy(hash, &hash_buffer->bytes, hash_buffer->size);
+ *hash_len = hash_buffer->size;
+
+ memcpy(sig, &sig_buffer->bytes, sig_buffer->size);
+ *sig_len = sig_buffer->size;
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ free(hash_buffer);
+ free(sig_buffer);
+
+ return rpc_status;
+}
+
+/* Operation: asymmetric_decrypt */
+static rpc_status_t deserialize_asymmetric_decrypt_req(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle, psa_algorithm_t *alg,
+ uint8_t *ciphertext, size_t *ciphertext_len,
+ uint8_t *salt, size_t *salt_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_AsymmetricDecryptIn recv_msg = ts_crypto_AsymmetricDecryptIn_init_default;
+
+ pb_bytes_array_t *ciphertext_buffer = pb_malloc_byte_array(*ciphertext_len);
+ recv_msg.ciphertext = pb_in_byte_array(ciphertext_buffer);
+
+ pb_bytes_array_t *salt_buffer = pb_malloc_byte_array(*salt_len);
+ recv_msg.salt = pb_in_byte_array(salt_buffer);
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_AsymmetricDecryptIn_fields, &recv_msg)) {
+
+ *handle = recv_msg.handle;
+ *alg = recv_msg.alg;
+
+ memcpy(ciphertext, &ciphertext_buffer->bytes, ciphertext_buffer->size);
+ *ciphertext_len = ciphertext_buffer->size;
+
+ memcpy(salt, &salt_buffer->bytes, salt_buffer->size);
+ *salt_len = salt_buffer->size;
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ free(ciphertext_buffer);
+ free(salt_buffer);
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_asymmetric_decrypt_resp(struct call_param_buf *resp_buf,
+ const uint8_t *plaintext, size_t plaintext_len)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_AsymmetricDecryptOut resp_msg = ts_crypto_AsymmetricDecryptOut_init_default;
+
+ pb_bytes_array_t *plaintext_buffer = pb_malloc_byte_array(plaintext_len);
+ resp_msg.plaintext = pb_out_byte_array(plaintext_buffer);
+ memcpy(&plaintext_buffer->bytes, plaintext, plaintext_len);
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_AsymmetricDecryptOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_AsymmetricDecryptOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ free(plaintext_buffer);
+
+ return rpc_status;
+}
+
+/* Operation: asymmetric_encrypt */
+static rpc_status_t deserialize_asymmetric_encrypt_req(const struct call_param_buf *req_buf,
+ psa_key_handle_t *handle, psa_algorithm_t *alg,
+ uint8_t *plaintext, size_t *plaintext_len,
+ uint8_t *salt, size_t *salt_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_AsymmetricEncryptIn recv_msg = ts_crypto_AsymmetricEncryptIn_init_default;
+
+ pb_bytes_array_t *plaintext_buffer = pb_malloc_byte_array(*plaintext_len);
+ recv_msg.plaintext = pb_in_byte_array(plaintext_buffer);
+
+ pb_bytes_array_t *salt_buffer = pb_malloc_byte_array(*salt_len);
+ recv_msg.salt = pb_in_byte_array(salt_buffer);
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_AsymmetricEncryptIn_fields, &recv_msg)) {
+
+ *handle = recv_msg.handle;
+ *alg = recv_msg.alg;
+
+ memcpy(plaintext, &plaintext_buffer->bytes, plaintext_buffer->size);
+ *plaintext_len = plaintext_buffer->size;
+
+ memcpy(salt, &salt_buffer->bytes, salt_buffer->size);
+ *salt_len = salt_buffer->size;
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ free(plaintext_buffer);
+ free(salt_buffer);
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_asymmetric_encrypt_resp(struct call_param_buf *resp_buf,
+ const uint8_t *ciphertext, size_t ciphertext_len)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_AsymmetricEncryptOut resp_msg = ts_crypto_AsymmetricEncryptOut_init_default;
+
+ pb_bytes_array_t *ciphertext_buffer = pb_malloc_byte_array(ciphertext_len);
+ resp_msg.ciphertext = pb_out_byte_array(ciphertext_buffer);
+ memcpy(&ciphertext_buffer->bytes, ciphertext, ciphertext_len);
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_AsymmetricEncryptOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_AsymmetricEncryptOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ free(ciphertext_buffer);
+
+ return rpc_status;
+}
+
+/* Operation: generate_random */
+static rpc_status_t deserialize_generate_random_req(const struct call_param_buf *req_buf,
+ size_t *size)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ ts_crypto_GenerateRandomIn recv_msg = ts_crypto_GenerateRandomIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer((const uint8_t*)req_buf->data, req_buf->data_len);
+
+ if (pb_decode(&istream, ts_crypto_GenerateRandomIn_fields, &recv_msg)) {
+
+ *size = recv_msg.size;
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_generate_random_resp(struct call_param_buf *resp_buf,
+ const uint8_t *output, size_t output_len)
+{
+ size_t packed_resp_size;
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ ts_crypto_GenerateRandomOut resp_msg = ts_crypto_GenerateRandomOut_init_default;
+
+ pb_bytes_array_t *output_buffer = pb_malloc_byte_array(output_len);
+ resp_msg.random_bytes = pb_out_byte_array(output_buffer);
+ memcpy(&output_buffer->bytes, output, output_len);
+
+ if (pb_get_encoded_size(&packed_resp_size, ts_crypto_GenerateRandomOut_fields, &resp_msg) &&
+ (packed_resp_size <= resp_buf->size)) {
+
+ pb_ostream_t ostream = pb_ostream_from_buffer((uint8_t*)resp_buf->data, packed_resp_size);
+ if (pb_encode(&ostream, ts_crypto_GenerateRandomOut_fields, &resp_msg)) {
+
+ resp_buf->data_len = packed_resp_size;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+ }
+
+ free(output_buffer);
+
+ return rpc_status;
+}
+
+/* Singleton method to provide access to the serializer instance */
+const struct crypto_provider_serializer *pb_crypto_provider_serializer_instance(void)
+{
+ static const struct crypto_provider_serializer instance = {
+ max_deserialised_parameter_size,
+ deserialize_generate_key_req,
+ serialize_generate_key_resp,
+ deserialize_destroy_key_req,
+ deserialize_open_key_req,
+ serialize_open_key_resp,
+ deserialize_close_key_req,
+ deserialize_export_key_req,
+ serialize_export_key_resp,
+ deserialize_export_public_key_req,
+ serialize_export_public_key_resp,
+ deserialize_import_key_req,
+ serialize_import_key_resp,
+ deserialize_sign_hash_req,
+ serialize_sign_hash_resp,
+ deserialize_verify_hash_req,
+ deserialize_asymmetric_decrypt_req,
+ serialize_asymmetric_decrypt_resp,
+ deserialize_asymmetric_encrypt_req,
+ serialize_asymmetric_encrypt_resp,
+ deserialize_generate_random_req,
+ serialize_generate_random_resp
+ };
+
+ return &instance;
+}
diff --git a/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h
new file mode 100644
index 000000000..64191c02d
--- /dev/null
+++ b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PB_CRYPTO_PROVIDER_SERIALIZER_H
+#define PB_CRYPTO_PROVIDER_SERIALIZER_H
+
+#include <service/crypto/provider/serializer/crypto_provider_serializer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Singleton method to provide access to the Protobuf serializer
+ * for the crypto service provider.
+ */
+extern const struct crypto_provider_serializer *pb_crypto_provider_serializer_instance(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* PB_CRYPTO_PROVIDER_SERIALIZER_H */
diff --git a/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.c b/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.c
new file mode 100644
index 000000000..14286a37d
--- /dev/null
+++ b/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "pb_key_attributes_translator.h"
+
+void pb_crypto_provider_translate_key_attributes(psa_key_attributes_t *psa_attributes,
+ const ts_crypto_KeyAttributes *proto_attributes) {
+
+ psa_set_key_type(psa_attributes, proto_attributes->type);
+ psa_set_key_bits(psa_attributes, proto_attributes->key_bits);
+ psa_set_key_lifetime(psa_attributes, proto_attributes->lifetime);
+
+ if (proto_attributes->lifetime == PSA_KEY_LIFETIME_PERSISTENT) {
+
+ psa_set_key_id(psa_attributes, proto_attributes->id);
+ }
+
+ if (proto_attributes->has_policy) {
+
+ psa_set_key_usage_flags(psa_attributes, proto_attributes->policy.usage);
+ psa_set_key_algorithm(psa_attributes, proto_attributes->policy.alg);
+ }
+}
diff --git a/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.h b/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.h
new file mode 100644
index 000000000..5de359bb3
--- /dev/null
+++ b/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PB_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H
+#define PB_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H
+
+#include <service/crypto/protobuf/key_attributes.pb.h>
+#include <psa/crypto.h>
+
+extern void pb_crypto_provider_translate_key_attributes(
+ psa_key_attributes_t *psa_attributes,
+ const ts_crypto_KeyAttributes *proto_attributes);
+
+#endif /* PB_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H */ \ No newline at end of file
diff --git a/components/service/crypto/test/service/component.cmake b/components/service/crypto/test/service/component.cmake
new file mode 100644
index 000000000..26366fd36
--- /dev/null
+++ b/components/service/crypto/test/service/component.cmake
@@ -0,0 +1,15 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/crypto_service_op_tests.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/crypto_service_limit_tests.cpp"
+ )
+
diff --git a/components/service/crypto/test/service/crypto_service_limit_tests.cpp b/components/service/crypto/test/service/crypto_service_limit_tests.cpp
new file mode 100644
index 000000000..53c856082
--- /dev/null
+++ b/components/service/crypto/test/service/crypto_service_limit_tests.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string>
+#include <vector>
+#include <cstring>
+#include <cstdint>
+#include <cassert>
+#include <service/crypto/client/cpp/crypto_client.h>
+#include <service_locator.h>
+#include <CppUTest/TestHarness.h>
+
+/*
+ * Service-level tests that focus on verifying that expected limits are met.
+ * e.g. number of keys, key sizes etc.
+ */
+TEST_GROUP(CryptoServiceLimitTests)
+{
+ void setup()
+ {
+ struct rpc_caller *caller;
+ int status;
+
+ m_rpc_session_handle = NULL;
+ m_crypto_service_context = NULL;
+ m_crypto_client = NULL;
+
+ service_locator_init();
+
+ m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0", &status);
+ assert(m_crypto_service_context);
+
+ m_rpc_session_handle = service_context_open(m_crypto_service_context, &caller);
+ assert(m_rpc_session_handle);
+
+ m_crypto_client = new crypto_client(caller);
+ }
+
+ void teardown()
+ {
+ delete m_crypto_client;
+ m_crypto_client = NULL;
+
+ service_context_close(m_crypto_service_context, m_rpc_session_handle);
+ m_rpc_session_handle = NULL;
+
+ service_context_relinquish(m_crypto_service_context);
+ m_crypto_service_context = NULL;
+ }
+
+ psa_status_t generateVolatileEccKeyPair(std::vector<psa_key_handle_t> &key_handles)
+ {
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 521);
+
+ psa_key_handle_t key_handle;
+ status = m_crypto_client->generate_key(&attributes, &key_handle);
+
+ psa_reset_key_attributes(&attributes);
+
+ if (status == PSA_SUCCESS) key_handles.push_back(key_handle);
+
+ return status;
+ }
+
+ psa_status_t generateVolatileRsaKeyPair(std::vector<psa_key_handle_t> &key_handles)
+ {
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+ psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+ psa_set_key_bits(&attributes, 512);
+
+ psa_key_handle_t key_handle;
+ status = m_crypto_client->generate_key(&attributes, &key_handle);
+
+ psa_reset_key_attributes(&attributes);
+
+ if (status == PSA_SUCCESS) key_handles.push_back(key_handle);
+
+ return status;
+ }
+
+ psa_status_t destroyKeys(const std::vector<psa_key_handle_t> &key_handles)
+ {
+ psa_status_t status = PSA_SUCCESS;
+ size_t key_index = 0;
+
+ while ((key_index < key_handles.size()) && (status == PSA_SUCCESS)) {
+
+ status = m_crypto_client->destroy_key(key_handles[key_index]);
+ ++key_index;
+ }
+
+ return status;
+ }
+
+ /*
+ * Maximum number of key slots in mbedcrypto
+ * is 32. We would expect it to be possible to
+ * generate keys up to that limit.
+ */
+ const size_t MAX_KEY_SLOTS = 32;
+
+ rpc_session_handle m_rpc_session_handle;
+ struct service_context *m_crypto_service_context;
+ crypto_client *m_crypto_client;
+};
+
+TEST(CryptoServiceLimitTests, volatileEccKeyPairLimit)
+{
+ size_t expected_limit = MAX_KEY_SLOTS;
+ size_t actual_limit = 0;
+ std::vector<psa_key_handle_t> key_handles;
+ psa_status_t generate_status = PSA_SUCCESS;
+ psa_status_t destroy_status;
+
+ while (actual_limit < expected_limit) {
+
+ generate_status = generateVolatileEccKeyPair(key_handles);
+
+ if (generate_status == PSA_SUCCESS)
+ ++actual_limit;
+ else
+ break;
+ }
+
+ destroy_status = destroyKeys(key_handles);
+
+ CHECK_EQUAL(PSA_SUCCESS, generate_status);
+ CHECK_EQUAL(PSA_SUCCESS, destroy_status);
+ CHECK_EQUAL(expected_limit, actual_limit);
+}
+
+TEST(CryptoServiceLimitTests, volatileRsaKeyPairLimit)
+{
+ size_t expected_limit = MAX_KEY_SLOTS;
+ size_t actual_limit = 0;
+ std::vector<psa_key_handle_t> key_handles;
+ psa_status_t generate_status = PSA_SUCCESS;
+ psa_status_t destroy_status;
+
+ while (actual_limit < expected_limit) {
+
+ generate_status = generateVolatileRsaKeyPair(key_handles);
+
+ if (generate_status == PSA_SUCCESS)
+ ++actual_limit;
+ else
+ break;
+ }
+
+ destroy_status = destroyKeys(key_handles);
+
+ CHECK_EQUAL(PSA_SUCCESS, generate_status);
+ CHECK_EQUAL(PSA_SUCCESS, destroy_status);
+ CHECK_EQUAL(expected_limit, actual_limit);
+} \ No newline at end of file
diff --git a/components/service/crypto/test/service/crypto_service_op_tests.cpp b/components/service/crypto/test/service/crypto_service_op_tests.cpp
new file mode 100644
index 000000000..cd4bd0406
--- /dev/null
+++ b/components/service/crypto/test/service/crypto_service_op_tests.cpp
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string>
+#include <cstring>
+#include <cstdint>
+#include <cassert>
+#include <service/crypto/client/cpp/crypto_client.h>
+#include <service_locator.h>
+#include <CppUTest/TestHarness.h>
+
+/*
+ * Service-level tests that focus on exercising each supported operation.
+ * These are mainly valid behaviour tests with the goal of checking
+ * that the number of operations supported is as expected.
+ */
+TEST_GROUP(CryptoServiceOpTests)
+{
+ void setup()
+ {
+ struct rpc_caller *caller;
+ int status;
+
+ m_rpc_session_handle = NULL;
+ m_crypto_service_context = NULL;
+ m_crypto_client = NULL;
+
+ service_locator_init();
+
+ m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0", &status);
+ assert(m_crypto_service_context);
+
+ m_rpc_session_handle = service_context_open(m_crypto_service_context, &caller);
+ assert(m_rpc_session_handle);
+
+ m_crypto_client = new crypto_client(caller);
+ }
+
+ void teardown()
+ {
+ delete m_crypto_client;
+ m_crypto_client = NULL;
+
+ service_context_close(m_crypto_service_context, m_rpc_session_handle);
+ m_rpc_session_handle = NULL;
+
+ service_context_relinquish(m_crypto_service_context);
+ m_crypto_service_context = NULL;
+ }
+
+ rpc_session_handle m_rpc_session_handle;
+ struct service_context *m_crypto_service_context;
+ crypto_client *m_crypto_client;
+};
+
+TEST(CryptoServiceOpTests, generateVolatileKeys)
+{
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ /* Generate first key */
+ psa_key_handle_t key_handle_1;
+ status = m_crypto_client->generate_key(&attributes, &key_handle_1);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* And another */
+ psa_key_handle_t key_handle_2;
+ status = m_crypto_client->generate_key(&attributes, &key_handle_2);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Expect the key handles to be different */
+ CHECK(key_handle_1 != key_handle_2);
+
+ /* Remove the keys */
+ status = m_crypto_client->destroy_key(key_handle_1);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->destroy_key(key_handle_2);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+}
+
+TEST(CryptoServiceOpTests, generatePersistentKeys)
+{
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ /* First try and generate a key with an invalid keu id */
+ psa_key_id_t key_id_invalid = 0;
+ psa_set_key_id(&attributes, key_id_invalid);
+ psa_key_handle_t key_handle_invalid;
+ status = m_crypto_client->generate_key(&attributes, &key_handle_invalid);
+ CHECK_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status);
+
+ /* Generate first key */
+ psa_key_id_t key_id_1 = 100000;
+ psa_set_key_id(&attributes, key_id_1);
+ psa_key_handle_t key_handle_1;
+ status = m_crypto_client->generate_key(&attributes, &key_handle_1);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* And another */
+ psa_key_id_t key_id_2 = 2;
+ psa_set_key_id(&attributes, key_id_2);
+ psa_key_handle_t key_handle_2;
+ status = m_crypto_client->generate_key(&attributes, &key_handle_2);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Expect the key handles to be different */
+ CHECK(key_handle_1 != key_handle_2);
+
+ /* Obtain more handles using key_open */
+ psa_key_handle_t key_handle_3;
+ status = m_crypto_client->open_key(key_id_1, &key_handle_3);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_key_handle_t key_handle_4;
+ status = m_crypto_client->open_key(key_id_1, &key_handle_4);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Relinquish handles */
+ status = m_crypto_client->close_key(key_handle_3);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->close_key(key_handle_4);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Expect close handle to now be invalid */
+ status = m_crypto_client->close_key(key_handle_4);
+ CHECK_EQUAL(PSA_ERROR_INVALID_HANDLE, status);
+
+ /* Remove the keys */
+ status = m_crypto_client->destroy_key(key_handle_1);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->destroy_key(key_handle_2);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+}
+
+TEST(CryptoServiceOpTests, exportPublicKey)
+{
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_handle_t key_handle;
+
+ psa_set_key_id(&attributes, 10);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ /* Generate a key */
+ status = m_crypto_client->generate_key(&attributes, &key_handle);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+
+ /* Export the public key */
+ uint8_t key_buf[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)];
+ size_t key_len = 0;
+
+ status = m_crypto_client->export_public_key(key_handle, key_buf, sizeof(key_buf), &key_len);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ CHECK(key_len > 0);
+
+ /* Remove the key */
+ status = m_crypto_client->destroy_key(key_handle);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+}
+
+TEST(CryptoServiceOpTests, exportAndImportKeyPair)
+{
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_handle_t key_handle_1;
+ psa_key_handle_t key_handle_2;
+
+ psa_set_key_id(&attributes, 11);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ /* Generate a key */
+ status = m_crypto_client->generate_key(&attributes, &key_handle_1);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Export the key pair */
+ uint8_t key_buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(256)];
+ size_t key_len = 0;
+
+ status = m_crypto_client->export_key(key_handle_1, key_buf, sizeof(key_buf), &key_len);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ CHECK(key_len > 0);
+
+ /* Import the key pair value with a different key id */
+ psa_set_key_id(&attributes, 12);
+ status = m_crypto_client->import_key(&attributes, key_buf, key_len, &key_handle_2);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+
+ /* Remove the keys */
+ status = m_crypto_client->destroy_key(key_handle_1);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->destroy_key(key_handle_2);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+}
+
+TEST(CryptoServiceOpTests, signAndVerifyHash)
+{
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_handle_t key_handle;
+
+ psa_set_key_id(&attributes, 13);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ /* Generate a key */
+ status = m_crypto_client->generate_key(&attributes, &key_handle);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+
+ /* Sign a hash */
+ uint8_t hash[20];
+ uint8_t signature[PSA_SIGNATURE_MAX_SIZE];
+ size_t signature_length;
+
+ memset(hash, 0x71, sizeof(hash));
+
+ status = m_crypto_client->sign_hash(key_handle,
+ PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash),
+ signature, sizeof(signature), &signature_length);
+
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ CHECK(signature_length > 0);
+
+ /* Verify the signature */
+ status = m_crypto_client->verify_hash(key_handle,
+ PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash),
+ signature, signature_length);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Change the hash and expect verify to fail */
+ hash[0] = 0x72;
+ status = m_crypto_client->verify_hash(key_handle,
+ PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash),
+ signature, signature_length);
+ CHECK_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status);
+
+ /* Remove the key */
+ status = m_crypto_client->destroy_key(key_handle);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+}
+
+TEST(CryptoServiceOpTests, asymEncryptDecrypt)
+{
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_handle_t key_handle;
+
+ psa_set_key_id(&attributes, 14);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+ psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+ psa_set_key_bits(&attributes, 256);
+
+ /* Generate a key */
+ status = m_crypto_client->generate_key(&attributes, &key_handle);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+
+ /* Encrypt a message */
+ uint8_t message[] = {'q','u','i','c','k','b','r','o','w','n','f','o','x'};
+ uint8_t ciphertext[256];
+ size_t ciphertext_len = 0;
+
+ status = m_crypto_client->asymmetric_encrypt(key_handle, PSA_ALG_RSA_PKCS1V15_CRYPT,
+ message, sizeof(message), NULL, 0,
+ ciphertext, sizeof(ciphertext), &ciphertext_len);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Decrypt it */
+ uint8_t plaintext[256];
+ size_t plaintext_len = 0;
+
+ status = m_crypto_client->asymmetric_decrypt(key_handle, PSA_ALG_RSA_PKCS1V15_CRYPT,
+ ciphertext, ciphertext_len, NULL, 0,
+ plaintext, sizeof(plaintext), &plaintext_len);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Expect the encrypted/decrypted message to match theh original */
+ CHECK_EQUAL(sizeof(message), plaintext_len);
+ CHECK(memcmp(message, plaintext, plaintext_len) == 0);
+
+ /* Remove the key */
+ status = m_crypto_client->destroy_key(key_handle);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+}
+
+TEST(CryptoServiceOpTests, generateRandomNumbers)
+{
+ psa_status_t status;
+ uint8_t num1_8bit[1];
+ uint8_t num2_8bit[1];
+ uint8_t num3_16bit[2];
+ uint8_t num4_16bit[2];
+ uint8_t num5_24bit[3];
+ uint8_t num6_24bit[3];
+ uint8_t num7_32bit[4];
+ uint8_t num8_32bit[4];
+ uint8_t num9_64bit[8];
+ uint8_t num10_64bit[8];
+ uint8_t num11_128bit[16];
+ uint8_t num12_128bit[16];
+
+ /* Clear all buffers */
+ memset(num1_8bit, 0, sizeof(num1_8bit));
+ memset(num2_8bit, 0, sizeof(num2_8bit));
+ memset(num3_16bit, 0, sizeof(num3_16bit));
+ memset(num4_16bit, 0, sizeof(num4_16bit));
+ memset(num5_24bit, 0, sizeof(num5_24bit));
+ memset(num6_24bit, 0, sizeof(num6_24bit));
+ memset(num7_32bit, 0, sizeof(num7_32bit));
+ memset(num8_32bit, 0, sizeof(num8_32bit));
+ memset(num9_64bit, 0, sizeof(num9_64bit));
+ memset(num10_64bit, 0, sizeof(num10_64bit));
+ memset(num11_128bit, 0, sizeof(num11_128bit));
+ memset(num12_128bit, 0, sizeof(num12_128bit));
+
+ /* Generate some different size random numbers */
+ status = m_crypto_client->generate_random(num1_8bit, sizeof(num1_8bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num2_8bit, sizeof(num2_8bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num3_16bit, sizeof(num3_16bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num4_16bit, sizeof(num4_16bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num5_24bit, sizeof(num5_24bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num6_24bit, sizeof(num6_24bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num7_32bit, sizeof(num7_32bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num8_32bit, sizeof(num8_32bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num9_64bit, sizeof(num9_64bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num10_64bit, sizeof(num10_64bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num11_128bit, sizeof(num11_128bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ status = m_crypto_client->generate_random(num12_128bit, sizeof(num12_128bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ /* Expect different numbers to be generated */
+ CHECK(memcmp(num1_8bit, num2_8bit, sizeof(num1_8bit)) != 0);
+ CHECK(memcmp(num3_16bit, num4_16bit, sizeof(num3_16bit)) != 0);
+ CHECK(memcmp(num5_24bit, num6_24bit, sizeof(num5_24bit)) != 0);
+ CHECK(memcmp(num7_32bit, num8_32bit, sizeof(num7_32bit)) != 0);
+ CHECK(memcmp(num9_64bit, num10_64bit, sizeof(num9_64bit)) != 0);
+ CHECK(memcmp(num11_128bit, num12_128bit, sizeof(num11_128bit)) != 0);
+}
diff --git a/components/service/crypto/test/unit/component.cmake b/components/service/crypto/test/unit/component.cmake
new file mode 100644
index 000000000..bdb38bcba
--- /dev/null
+++ b/components/service/crypto/test/unit/component.cmake
@@ -0,0 +1,16 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/crypto_msg_encode_decode.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/poc_crypto_ops.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/crypto_fault_tests.cpp"
+ )
+
diff --git a/components/service/crypto/test/unit/crypto_fault_tests.cpp b/components/service/crypto/test/unit/crypto_fault_tests.cpp
new file mode 100644
index 000000000..63a4b3910
--- /dev/null
+++ b/components/service/crypto/test/unit/crypto_fault_tests.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string>
+#include <cstring>
+#include <cstdint>
+#include <service/crypto/client/test/standalone/standalone_crypto_client.h>
+#include <CppUTest/TestHarness.h>
+
+TEST_GROUP(CryptoFaultTests)
+{
+ void setup()
+ {
+ m_crypto_client = new standalone_crypto_client;
+ }
+
+ void teardown()
+ {
+ m_crypto_client->deinit();
+ delete m_crypto_client;
+ m_crypto_client = NULL;
+ }
+
+ test_crypto_client *m_crypto_client;
+};
+
+TEST(CryptoFaultTests, volatileKeyWithBrokenStorage)
+{
+ /* Inject broken secure storage fault */
+ m_crypto_client->inject_fault(test_crypto_client::FAILED_TO_DISCOVER_SECURE_STORAGE);
+ m_crypto_client->init();
+
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ /* Expect generation of volatile key to still work with fault */
+ psa_key_handle_t key_handle;
+ status = m_crypto_client->generate_key(&attributes, &key_handle);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+}
+
+TEST(CryptoFaultTests, persistentKeysWithBrokenStorage)
+{
+ /* Inject broken secure storage fault */
+ m_crypto_client->inject_fault(test_crypto_client::FAILED_TO_DISCOVER_SECURE_STORAGE);
+ m_crypto_client->init();
+
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ /* Expect persist key generation to fail */
+ psa_key_id_t key_id_1 = 1;
+ psa_set_key_id(&attributes, key_id_1);
+ psa_key_handle_t key_handle_1;
+ status = m_crypto_client->generate_key(&attributes, &key_handle_1);
+ CHECK(PSA_SUCCESS != status);
+
+ psa_reset_key_attributes(&attributes);
+}
+
+TEST(CryptoFaultTests, randomNumbersWithBrokenStorage)
+{
+ /* Inject broken secure storage fault */
+ m_crypto_client->inject_fault(test_crypto_client::FAILED_TO_DISCOVER_SECURE_STORAGE);
+ m_crypto_client->init();
+
+ psa_status_t status;
+ uint8_t num12_128bit[16];
+
+ memset(num12_128bit, 0, sizeof(num12_128bit));
+
+ /* Expect random number generation to work, despite the broken storage */
+ status = m_crypto_client->generate_random(num12_128bit, sizeof(num12_128bit));
+ CHECK_EQUAL(PSA_SUCCESS, status);
+}
diff --git a/components/service/crypto/test/unit/crypto_msg_encode_decode.cpp b/components/service/crypto/test/unit/crypto_msg_encode_decode.cpp
new file mode 100644
index 000000000..ea8e38826
--- /dev/null
+++ b/components/service/crypto/test/unit/crypto_msg_encode_decode.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <CppUTest/TestHarness.h>
+#include <service/crypto/protobuf/generate_key.pb.h>
+#include <service/crypto/protobuf/export_public_key.pb.h>
+#include <service/crypto/protobuf/sign_hash.pb.h>
+#include <pb.h>
+#include <pb_encode.h>
+#include <pb_decode.h>
+
+
+TEST_GROUP(CryptoMsgTests) {
+
+ void setup() {
+ print_info = false;
+ }
+
+ /* Nanopb encode/decode methods */
+ static bool encode_byte_array(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
+
+ const pb_bytes_array_t *byte_array = (const pb_bytes_array_t *)*arg;
+ if (!pb_encode_tag_for_field(stream, field)) return false;
+
+ return pb_encode_string(stream, byte_array->bytes, byte_array->size);
+ }
+
+ static bool decode_byte_array(pb_istream_t *stream, const pb_field_t *field, void **arg) {
+
+ (void)field;
+ pb_bytes_array_t *byte_array = (pb_bytes_array_t *)*arg;
+ if (stream->bytes_left > byte_array->size) return false;
+
+ return pb_read(stream, byte_array->bytes, stream->bytes_left);
+ }
+
+ static pb_callback_t out_byte_array(const pb_bytes_array_t *byte_array) {
+
+ pb_callback_t callback;
+ callback.funcs.encode = encode_byte_array;
+ callback.arg = (void*)byte_array;
+
+ return callback;
+ }
+
+ static pb_callback_t in_byte_array(pb_bytes_array_t *byte_array) {
+
+ pb_callback_t callback;
+ callback.funcs.decode = decode_byte_array;
+ callback.arg = (void*)byte_array;
+ return callback;
+ }
+
+ bool print_info;
+};
+
+TEST(CryptoMsgTests, GenerateKeyInMsgTest) {
+ /* Sender - set values and serialize */
+ ts_crypto_GenerateKeyIn sent_msg = ts_crypto_GenerateKeyIn_init_default;
+ ts_crypto_KeyAttributes sent_key_attributes = ts_crypto_KeyAttributes_init_default;
+
+ sent_key_attributes.type =
+ ts_crypto_KeyType_KEY_TYPE_ECC_PUBLIC_KEY_BASE |
+ ts_crypto_EccCurve_ECC_CURVE_SECP_R1;
+
+ sent_key_attributes.key_bits = 256;
+ sent_key_attributes.lifetime = ts_crypto_KeyLifetime_KEY_LIFETIME_PERSISTENT;
+ sent_key_attributes.id = 3;
+
+ sent_key_attributes.has_policy = true;
+ sent_key_attributes.policy.usage = ts_crypto_KeyUsage_KEY_USAGE_SIGN_HASH;
+ sent_key_attributes.policy.alg =
+ ts_crypto_Alg_ALG_DETERMINISTIC_ECDSA_BASE |
+ ts_crypto_Alg_ALG_SHA_256;
+
+ sent_msg.attributes = sent_key_attributes;
+ sent_msg.has_attributes = true;
+
+ size_t sent_msg_len;
+ CHECK(pb_get_encoded_size(&sent_msg_len, ts_crypto_GenerateKeyIn_fields, &sent_msg));
+ uint8_t *sent_msg_buf = (uint8_t*)malloc(sent_msg_len);
+ CHECK(sent_msg_len > 0);
+ CHECK(sent_msg_buf);
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK(pb_encode(&ostream, ts_crypto_GenerateKeyIn_fields, &sent_msg));
+ CHECK_EQUAL(sent_msg_len, ostream.bytes_written);
+
+ /* Receiver - deserialize and use values */
+ ts_crypto_GenerateKeyIn recv_msg = ts_crypto_GenerateKeyIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK_EQUAL(sent_msg_len, istream.bytes_left);
+ CHECK(pb_decode(&istream, ts_crypto_GenerateKeyIn_fields, &recv_msg));
+ CHECK_EQUAL(0, istream.bytes_left);
+
+ free(sent_msg_buf);
+
+ CHECK(recv_msg.has_attributes);
+ CHECK_EQUAL(sent_key_attributes.type, recv_msg.attributes.type);
+ CHECK_EQUAL(sent_key_attributes.key_bits, recv_msg.attributes.key_bits);
+ CHECK_EQUAL(sent_key_attributes.lifetime, recv_msg.attributes.lifetime);
+ CHECK_EQUAL(sent_key_attributes.id, recv_msg.attributes.id);
+
+ CHECK(recv_msg.attributes.has_policy);
+ CHECK_EQUAL(sent_key_attributes.policy.usage, recv_msg.attributes.policy.usage);
+ CHECK_EQUAL(sent_key_attributes.policy.alg, recv_msg.attributes.policy.alg);
+
+ if (print_info) {
+ printf("Serialized op_export_public_key len: %ld\n", sent_msg_len);
+ }
+}
+
+TEST(CryptoMsgTests, ExportPublicKeyInMsgTest) {
+ /* Sender - set values and serialize */
+ ts_crypto_ExportPublicKeyIn sent_msg = ts_crypto_ExportPublicKeyIn_init_default;
+
+ sent_msg.handle = 55;
+
+ size_t sent_msg_len;
+ CHECK(pb_get_encoded_size(&sent_msg_len, ts_crypto_ExportPublicKeyIn_fields, &sent_msg));
+ uint8_t *sent_msg_buf = (uint8_t*)malloc(sent_msg_len);
+ CHECK(sent_msg_len > 0);
+ CHECK(sent_msg_buf);
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK(pb_encode(&ostream, ts_crypto_ExportPublicKeyIn_fields, &sent_msg));
+ CHECK_EQUAL(sent_msg_len, ostream.bytes_written);
+
+ /* Receiver - deserialize and use values */
+ ts_crypto_ExportPublicKeyIn recv_msg = ts_crypto_ExportPublicKeyIn_init_default;
+
+ pb_istream_t istream = pb_istream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK_EQUAL(sent_msg_len, istream.bytes_left);
+ CHECK(pb_decode(&istream, ts_crypto_ExportPublicKeyIn_fields, &recv_msg));
+ CHECK_EQUAL(0, istream.bytes_left);
+
+ CHECK_EQUAL(sent_msg.handle, recv_msg.handle);
+
+ free(sent_msg_buf);
+
+ if (print_info) {
+ printf("Serialized op_export_public_key len: %ld\n", sent_msg_len);
+ }
+}
+
+TEST(CryptoMsgTests, ExportPublicKeyOutMsgTest) {
+ /* Sender - set values and serialize */
+ ts_crypto_ExportPublicKeyOut sent_msg = ts_crypto_ExportPublicKeyOut_init_default;
+
+ PB_BYTES_ARRAY_T(5) example_key = {5, {0x31, 0x32, 0x33, 0x34, 0x35}};
+ sent_msg.data = out_byte_array((const pb_bytes_array_t *)&example_key);
+
+ size_t sent_msg_len;
+ CHECK(pb_get_encoded_size(&sent_msg_len, ts_crypto_ExportPublicKeyOut_fields, &sent_msg));
+ uint8_t *sent_msg_buf = (uint8_t*)malloc(sent_msg_len);
+ CHECK(sent_msg_len > 0);
+ CHECK(sent_msg_buf);
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK(pb_encode(&ostream, ts_crypto_ExportPublicKeyOut_fields, &sent_msg));
+ CHECK_EQUAL(sent_msg_len, ostream.bytes_written);
+
+ /* Receiver - deserialize and use values */
+ PB_BYTES_ARRAY_T(5) recv_key = {5, {0}};
+ ts_crypto_ExportPublicKeyOut recv_msg = ts_crypto_ExportPublicKeyOut_init_default;
+ recv_msg.data = in_byte_array((pb_bytes_array_t *)&recv_key);
+
+ pb_istream_t istream = pb_istream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK_EQUAL(sent_msg_len, istream.bytes_left);
+ CHECK(pb_decode(&istream, ts_crypto_ExportPublicKeyOut_fields, &recv_msg));
+ CHECK_EQUAL(0, istream.bytes_left);
+
+ free(sent_msg_buf);
+
+ CHECK_EQUAL(example_key.size, recv_key.size);
+ CHECK(memcmp(example_key.bytes, recv_key.bytes, example_key.size) == 0);
+
+ if (print_info) {
+ printf("Serialized result_export_public_key len: %ld\n", sent_msg_len);
+ }
+}
+
+TEST(CryptoMsgTests, SignHashInMsgTest) {
+ /* Sender - set values and serialize */
+ ts_crypto_SignHashIn sent_msg = ts_crypto_SignHashIn_init_default;
+
+ PB_BYTES_ARRAY_T(6) msg_to_sign = {6, {0x34, 0x32, 0x33, 0x34, 0x35, 0x36}};
+ sent_msg.hash = out_byte_array((const pb_bytes_array_t *)&msg_to_sign);
+
+ sent_msg.handle = 71;
+ sent_msg.alg =
+ ts_crypto_Alg_ALG_DETERMINISTIC_ECDSA_BASE |
+ ts_crypto_Alg_ALG_SHA_256;
+
+ size_t sent_msg_len;
+ CHECK(pb_get_encoded_size(&sent_msg_len, ts_crypto_SignHashIn_fields, &sent_msg));
+ uint8_t *sent_msg_buf = (uint8_t*)malloc(sent_msg_len);
+ CHECK(sent_msg_len > 0);
+ CHECK(sent_msg_buf);
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK(pb_encode(&ostream, ts_crypto_SignHashIn_fields, &sent_msg));
+ CHECK_EQUAL(sent_msg_len, ostream.bytes_written);
+
+ /* Receiver - deserialize and use values */
+ PB_BYTES_ARRAY_T(6) recv_msg_to_sign = {6, {0}};
+ ts_crypto_SignHashIn recv_msg = ts_crypto_SignHashIn_init_default;
+ recv_msg.hash = in_byte_array((pb_bytes_array_t *)&recv_msg_to_sign);
+
+ pb_istream_t istream = pb_istream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK_EQUAL(sent_msg_len, istream.bytes_left);
+ CHECK(pb_decode(&istream, ts_crypto_SignHashIn_fields, &recv_msg));
+ CHECK_EQUAL(0, istream.bytes_left);
+
+ free(sent_msg_buf);
+
+ CHECK_EQUAL(sent_msg.handle, recv_msg.handle);
+ CHECK_EQUAL(sent_msg.alg, recv_msg.alg);
+
+ CHECK_EQUAL(msg_to_sign.size, recv_msg_to_sign.size);
+ CHECK(memcmp(msg_to_sign.bytes, recv_msg_to_sign.bytes, msg_to_sign.size) == 0);
+
+ if (print_info) {
+ printf("Serialized op_asym_sign len: %ld\n", sent_msg_len);
+ }
+}
+
+TEST(CryptoMsgTests, SignHashOutMsgTest) {
+ /* Sender - set values and serialize */
+ ts_crypto_SignHashOut sent_msg = ts_crypto_SignHashOut_init_default;
+
+ PB_BYTES_ARRAY_T(10) example_signature = {10, {0x01, 0x02, 0x5a, 0x7c, 0x35, 0x01, 0x02, 0x5a, 0x7c, 0x35}};
+ sent_msg.signature = out_byte_array((const pb_bytes_array_t *)&example_signature);
+
+ size_t sent_msg_len;
+ CHECK(pb_get_encoded_size(&sent_msg_len, ts_crypto_SignHashOut_fields, &sent_msg));
+ uint8_t *sent_msg_buf = (uint8_t*)malloc(sent_msg_len);
+ CHECK(sent_msg_len > 0);
+ CHECK(sent_msg_buf);
+
+ pb_ostream_t ostream = pb_ostream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK(pb_encode(&ostream, ts_crypto_SignHashOut_fields, &sent_msg));
+ CHECK_EQUAL(sent_msg_len, ostream.bytes_written);
+
+ /* Receiver - deserialize and use values */
+ PB_BYTES_ARRAY_T(10) recv_signature = {10, {0}};
+ ts_crypto_SignHashOut recv_msg = ts_crypto_SignHashOut_init_default;
+ recv_msg.signature = in_byte_array((pb_bytes_array_t *)&recv_signature);
+
+ pb_istream_t istream = pb_istream_from_buffer(sent_msg_buf, sent_msg_len);
+ CHECK_EQUAL(sent_msg_len, istream.bytes_left);
+ CHECK(pb_decode(&istream, ts_crypto_SignHashOut_fields, &recv_msg));
+ CHECK_EQUAL(0, istream.bytes_left);
+
+ free(sent_msg_buf);
+
+ CHECK_EQUAL(example_signature.size, recv_signature.size);
+ CHECK(memcmp(example_signature.bytes, recv_signature.bytes, example_signature.size) == 0);
+
+ if (print_info) {
+ printf("Serialized result_asym_sign len: %ld\n", sent_msg_len);
+ }
+}
diff --git a/components/service/crypto/test/unit/poc_crypto_ops.cpp b/components/service/crypto/test/unit/poc_crypto_ops.cpp
new file mode 100644
index 000000000..30be0eb24
--- /dev/null
+++ b/components/service/crypto/test/unit/poc_crypto_ops.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <cstdio>
+#include <cstring>
+#include <psa/crypto.h>
+#include <CppUTest/TestHarness.h>
+
+/* Tests to prototype each of the Crypto operations used for the PoC Crypto SP
+ * demonstrator.
+ */
+TEST_GROUP(PocCryptoOpTests) {
+
+ void setup() {
+ print_info = false;
+ (void)psa_crypto_init();
+ }
+
+ void generateEcdsaKeyPair() {
+ psa_status_t status;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1));
+ psa_set_key_bits(&attributes, 256);
+
+ status = psa_generate_key(&attributes, &ecdsa_key_handle);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+
+ if (print_info) {
+ printf("Generated ECDSA key pair\n");
+ printf(" Inputs: attributes: %ld\n", sizeof(attributes));
+ printf(" Outputs: handle: %ld status: %ld\n", sizeof(ecdsa_key_handle), sizeof(status));
+ }
+ }
+
+ void exportPublicKey() {
+ psa_status_t status;
+ exported_key_len = 0;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ status = psa_get_key_attributes(ecdsa_key_handle, &attributes);
+
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ size_t max_export_size = PSA_KEY_EXPORT_MAX_SIZE(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_get_key_type(&attributes)),
+ psa_get_key_bits(&attributes));
+
+ status = psa_export_public_key(ecdsa_key_handle, exported_key, sizeof(exported_key),
+ &exported_key_len);
+
+ CHECK_EQUAL(PSA_SUCCESS, status);
+ CHECK_EQUAL(max_export_size, exported_key_len);
+
+ psa_reset_key_attributes(&attributes);
+
+ if (print_info) {
+ printf("Exported a public key\n");
+ printf(" Inputs: handle: %ld\n", sizeof(ecdsa_key_handle));
+ printf(" Outputs: exported_length: %ld status: %ld\n", sizeof(exported_key_len), sizeof(status));
+ printf(" Outputs: space of key value: %ld bytes\n", exported_key_len);
+ }
+ }
+
+ void signMessage() {
+ psa_status_t status;
+ uint8_t hash[20];
+ uint8_t signature[PSA_SIGNATURE_MAX_SIZE];
+ size_t signature_length;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ memset(hash, 0x55, sizeof(hash));
+
+ status = psa_get_key_attributes(ecdsa_key_handle, &attributes);
+
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ status = psa_sign_hash(ecdsa_key_handle, psa_get_key_algorithm(&attributes),
+ hash, sizeof(hash),
+ signature, sizeof(signature),
+ &signature_length);
+ CHECK_EQUAL(PSA_SUCCESS, status);
+
+ psa_reset_key_attributes(&attributes);
+
+ if (print_info) {
+ printf("Signed a message\n");
+ printf(" Inputs: handle: %ld algo 1 message %ld\n", sizeof(ecdsa_key_handle), sizeof(hash));
+ printf(" Outputs: signature: %ld\n", signature_length);
+ }
+ }
+
+ bool print_info;
+ psa_key_handle_t ecdsa_key_handle;
+ uint8_t exported_key[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)];
+ size_t exported_key_len;
+};
+
+TEST(PocCryptoOpTests, checkOpSequence) {
+
+ generateEcdsaKeyPair();
+ exportPublicKey();
+ signMessage();
+} \ No newline at end of file
diff --git a/external/mbed-crypto/mbedcrypto.cmake b/external/mbed-crypto/mbedcrypto.cmake
new file mode 100644
index 000000000..bf0058875
--- /dev/null
+++ b/external/mbed-crypto/mbedcrypto.cmake
@@ -0,0 +1,93 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+set(MBEDCRYPTO_URL "https://github.com/ARMmbed/mbed-crypto.git" CACHE STRING "mbedcrypto repository URL")
+set(MBEDCRYPTO_REFSPEC "mbedcrypto-3.1.0" CACHE STRING "mbedcrypto git refspec")
+set(MBEDCRYPTO_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/mbedcrypto_install" CACHE PATH "mbedcrypto installation directory")
+set(MBEDCRYPTO_PACKAGE_PATH "${MBEDCRYPTO_INSTALL_PATH}/lib/mbedcrypto/cmake" CACHE PATH "mbedcrypto CMake package directory")
+
+include(FetchContent)
+
+# Checking git
+find_program(GIT_COMMAND "git")
+if (NOT GIT_COMMAND)
+ message(FATAL_ERROR "Please install git")
+endif()
+
+# Fetching mbedcrypto
+FetchContent_Declare(
+ mbedcrypto
+ GIT_REPOSITORY ${MBEDCRYPTO_URL}
+ GIT_TAG ${MBEDCRYPTO_REFSPEC}
+ GIT_SHALLOW TRUE
+)
+
+# FetchContent_GetProperties exports mbedcrypto_SOURCE_DIR and mbedcrypto_BINARY_DIR variables
+FetchContent_GetProperties(mbedcrypto)
+if(NOT mbedcrypto_POPULATED)
+ message(STATUS "Fetching mbedcrypto")
+ FetchContent_Populate(mbedcrypto)
+endif()
+
+# Convert the include path list to a string. Needed to make parameter passing to
+# mbedcrypto build work fine.
+string(REPLACE ";" "\\;" MBEDCRYPTO_EXTRA_INCLUDES "${MBEDCRYPTO_EXTRA_INCLUDES}")
+
+#Configure the library
+if(NOT CMAKE_CROSSCOMPILING)
+ execute_process(COMMAND
+ ${CMAKE_COMMAND}
+ -DENABLE_PROGRAMS=OFF
+ -DENABLE_TESTING=OFF
+ -DCMAKE_INSTALL_PREFIX=${MBEDCRYPTO_INSTALL_PATH}
+ -DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE}
+ -Dthirdparty_def=-DMBEDTLS_CONFIG_FILE="${MBEDCRYPTO_CONFIG_FILE}"
+ -Dthirdparty_inc=${MBEDCRYPTO_EXTRA_INCLUDES}
+ -GUnix\ Makefiles
+ ${mbedcrypto_SOURCE_DIR}
+ WORKING_DIRECTORY
+ ${mbedcrypto_BINARY_DIR}
+ )
+else()
+ execute_process(COMMAND
+ ${CMAKE_COMMAND}
+ -DENABLE_PROGRAMS=OFF
+ -DENABLE_TESTING=OFF
+ -DCMAKE_INSTALL_PREFIX=${MBEDCRYPTO_INSTALL_PATH}
+ -DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE}
+ -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY
+ -Dthirdparty_def=-DMBEDTLS_CONFIG_FILE="${MBEDCRYPTO_CONFIG_FILE}"
+ -Dthirdparty_inc=${MBEDCRYPTO_EXTRA_INCLUDES}
+ -GUnix\ Makefiles
+ ${mbedcrypto_SOURCE_DIR}
+ WORKING_DIRECTORY
+ ${mbedcrypto_BINARY_DIR}
+ RESULT_VARIABLE _exec_error
+ )
+
+ if (_exec_error)
+ message(FATAL_ERROR "Configuration step of mbedcrypto failed with ${_exec_error}.")
+ endif()
+endif()
+
+#TODO: add dependnecy to generated project on this file!
+#TODO: add custom target to rebuild mbedcrypto
+
+#Build the library
+execute_process(COMMAND
+ ${CMAKE_COMMAND} --build ${mbedcrypto_BINARY_DIR} -- install -j8
+ RESULT_VARIABLE _exec_error
+ )
+if (_exec_error)
+ message(FATAL_ERROR "Build step of mbedcrypto failed with ${_exec_error}.")
+endif()
+
+#Create an imported target to have clean abstraction in the build-system.
+add_library(mbedcrypto STATIC IMPORTED)
+set_property(TARGET mbedcrypto PROPERTY IMPORTED_LOCATION "${MBEDCRYPTO_INSTALL_PATH}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}mbedcrypto${CMAKE_STATIC_LIBRARY_SUFFIX}")
+set_property(TARGET mbedcrypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MBEDCRYPTO_INSTALL_PATH}/include")
+
diff --git a/protocols/service/crypto/packed-c/component.cmake b/protocols/service/crypto/packed-c/component.cmake
new file mode 100644
index 000000000..041f7d549
--- /dev/null
+++ b/protocols/service/crypto/packed-c/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_include_directories(${TGT}
+ PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}"
+ )
diff --git a/protocols/service/crypto/packed-c/opcodes.h b/protocols/service/crypto/packed-c/opcodes.h
new file mode 100644
index 000000000..40f8ab3ee
--- /dev/null
+++ b/protocols/service/crypto/packed-c/opcodes.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TS_CRYPTO_OPCODES_H
+#define TS_CRYPTO_OPCODES_H
+
+/* C/C++ definition of crypto service opcodes
+ */
+#define TS_CRYPTO_OPCODE_NOP (0x0000)
+#define TS_CRYPTO_OPCODE_GENERATE_KEY (0x0101)
+#define TS_CRYPTO_OPCODE_DESTROY_KEY (0x0102)
+#define TS_CRYPTO_OPCODE_OPEN_KEY (0x0103)
+#define TS_CRYPTO_OPCODE_CLOSE_KEY (0x0104)
+#define TS_CRYPTO_OPCODE_EXPORT_KEY (0x0105)
+#define TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY (0x0106)
+#define TS_CRYPTO_OPCODE_IMPORT_KEY (0x0107)
+#define TS_CRYPTO_OPCODE_SIGN_HASH (0x0108)
+#define TS_CRYPTO_OPCODE_VERIFY_HASH (0x0109)
+#define TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT (0x010a)
+#define TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT (0x010b)
+#define TS_CRYPTO_OPCODE_GENERATE_RANDOM (0x010c)
+
+#endif /* TS_CRYPTO_OPCODES_H */
diff --git a/protocols/service/crypto/protobuf/asymmetric_decrypt.proto b/protocols/service/crypto/protobuf/asymmetric_decrypt.proto
new file mode 100644
index 000000000..0155c3043
--- /dev/null
+++ b/protocols/service/crypto/protobuf/asymmetric_decrypt.proto
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message AsymmetricDecryptIn {
+ uint32 handle = 1;
+ uint32 alg = 2;
+ bytes ciphertext = 3;
+ bytes salt = 4;
+}
+
+message AsymmetricDecryptOut {
+ bytes plaintext = 1;
+}
diff --git a/protocols/service/crypto/protobuf/asymmetric_encrypt.proto b/protocols/service/crypto/protobuf/asymmetric_encrypt.proto
new file mode 100644
index 000000000..c85b9da18
--- /dev/null
+++ b/protocols/service/crypto/protobuf/asymmetric_encrypt.proto
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message AsymmetricEncryptIn {
+ uint32 handle = 1;
+ uint32 alg = 2;
+ bytes plaintext = 3;
+ bytes salt = 4;
+}
+
+message AsymmetricEncryptOut {
+ bytes ciphertext = 1;
+}
diff --git a/protocols/service/crypto/protobuf/close_key.proto b/protocols/service/crypto/protobuf/close_key.proto
new file mode 100644
index 000000000..b9f5ea3fd
--- /dev/null
+++ b/protocols/service/crypto/protobuf/close_key.proto
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message CloseKeyIn {
+ uint32 handle = 1;
+}
diff --git a/protocols/service/crypto/protobuf/component.cmake b/protocols/service/crypto/protobuf/component.cmake
new file mode 100644
index 000000000..7583f18ea
--- /dev/null
+++ b/protocols/service/crypto/protobuf/component.cmake
@@ -0,0 +1,26 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+set_property(TARGET ${TGT} APPEND PROPERTY PROTOBUF_FILES
+ "${CMAKE_CURRENT_LIST_DIR}/asymmetric_decrypt.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/asymmetric_encrypt.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/destroy_key.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/open_key.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/close_key.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/export_key.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/export_public_key.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/generate_key.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/generate_random.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/import_key.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/key_attributes.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/opcodes.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/sign_hash.proto"
+ "${CMAKE_CURRENT_LIST_DIR}/verify_hash.proto"
+ )
diff --git a/protocols/service/crypto/protobuf/destroy_key.proto b/protocols/service/crypto/protobuf/destroy_key.proto
new file mode 100644
index 000000000..8b718af4d
--- /dev/null
+++ b/protocols/service/crypto/protobuf/destroy_key.proto
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message DestroyKeyIn {
+ uint32 handle = 1;
+}
+
+message DestroyKeyOut {}
diff --git a/protocols/service/crypto/protobuf/export_key.proto b/protocols/service/crypto/protobuf/export_key.proto
new file mode 100644
index 000000000..14cc6a985
--- /dev/null
+++ b/protocols/service/crypto/protobuf/export_key.proto
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message ExportKeyIn {
+ uint32 handle = 1;
+}
+
+message ExportKeyOut {
+ bytes data = 1;
+}
diff --git a/protocols/service/crypto/protobuf/export_public_key.proto b/protocols/service/crypto/protobuf/export_public_key.proto
new file mode 100644
index 000000000..e8443257b
--- /dev/null
+++ b/protocols/service/crypto/protobuf/export_public_key.proto
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message ExportPublicKeyIn {
+ uint32 handle = 1;
+}
+
+message ExportPublicKeyOut {
+ bytes data = 1;
+}
diff --git a/protocols/service/crypto/protobuf/generate_key.proto b/protocols/service/crypto/protobuf/generate_key.proto
new file mode 100644
index 000000000..48025a659
--- /dev/null
+++ b/protocols/service/crypto/protobuf/generate_key.proto
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+import "service/crypto/protobuf/key_attributes.proto";
+
+message GenerateKeyIn {
+ KeyAttributes attributes = 1;
+}
+
+message GenerateKeyOut {
+ uint32 handle = 1;
+}
diff --git a/protocols/service/crypto/protobuf/generate_random.proto b/protocols/service/crypto/protobuf/generate_random.proto
new file mode 100644
index 000000000..3fbb5bea5
--- /dev/null
+++ b/protocols/service/crypto/protobuf/generate_random.proto
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message GenerateRandomIn {
+ uint64 size = 1;
+}
+
+message GenerateRandomOut {
+ bytes random_bytes = 1;
+}
diff --git a/protocols/service/crypto/protobuf/import_key.proto b/protocols/service/crypto/protobuf/import_key.proto
new file mode 100644
index 000000000..727b2bcf0
--- /dev/null
+++ b/protocols/service/crypto/protobuf/import_key.proto
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+import "service/crypto/protobuf/key_attributes.proto";
+
+message ImportKeyIn {
+ KeyAttributes attributes = 1;
+ bytes data = 3;
+}
+
+message ImportKeyOut {
+ uint32 handle = 1;
+}
diff --git a/protocols/service/crypto/protobuf/key_attributes.proto b/protocols/service/crypto/protobuf/key_attributes.proto
new file mode 100644
index 000000000..7e504f643
--- /dev/null
+++ b/protocols/service/crypto/protobuf/key_attributes.proto
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+/* Key types */
+enum KeyType {
+ option allow_alias = true;
+
+ KEY_TYPE_NONE = 0x0000;
+ KEY_TYPE_RAW_DATA = 0x1001;
+ KEY_TYPE_HMAC = 0x1100;
+ KEY_TYPE_DERIVE = 0x1200;
+ KEY_TYPE_AES = 0x2400;
+ KEY_TYPE_DES = 0x2301;
+ KEY_TYPE_CAMELLIA = 0x2403;
+ KEY_TYPE_ARC4 = 0x2002;
+ KEY_TYPE_CHACHA20 = 0x2004;
+ KEY_TYPE_PUBLIC_KEY = 0x4001;
+ KEY_TYPE_RSA_KEY_PAIR = 0x7001;
+ KEY_TYPE_ECC_PUBLIC_KEY_BASE = 0x4100;
+ KEY_TYPE_ECC_KEY_PAIR_BASE = 0x7100;
+ KEY_TYPE_ECC_CURVE_MASK = 0x00ff;
+ KEY_TYPE_DH_PUBLIC_KEY_BASE = 0x4200;
+ KEY_TYPE_DH_KEY_PAIR_BASE = 0x7200;
+ KEY_TYPE_DH_GROUP_MASK = 0x00ff;
+}
+
+/* ECC curves for use with ECC Key types */
+enum EccCurve {
+ ECC_CURVE_NONE = 0x00;
+ ECC_CURVE_SECP_K1 = 0x17;
+ ECC_CURVE_SECP_R1 = 0x12;
+ ECC_CURVE_SECP_R2 = 0x1b;
+ ECC_CURVE_SECT_K1 = 0x27;
+ ECC_CURVE_SECT_R1 = 0x22;
+ ECC_CURVE_SECT_R2 = 0x2b;
+ ECC_CURVE_BRAINPOOL_P_R1 = 0x30;
+ ECC_CURVE_MONTGOMERY = 0x41;
+}
+
+/* Diffie-Hellman groups for use with DH key types */
+enum DhGroup {
+ DH_GROUP_NONE = 0x00;
+ DH_GROUP_RFC7919 = 0x03;
+}
+
+/* Crypto algorithms */
+enum Alg {
+ ALG_NONE = 0x00000000;
+ ALG_HASH_MASK = 0x000000ff;
+ ALG_MD2 = 0x01000001;
+ ALG_MD4 = 0x01000002;
+ ALG_MD5 = 0x01000003;
+ ALG_RIPEMD160 = 0x01000004;
+ ALG_SHA_1 = 0x01000005;
+ ALG_SHA_224 = 0x01000008;
+ ALG_SHA_256 = 0x01000009;
+ ALG_SHA_384 = 0x0100000a;
+ ALG_SHA_512 = 0x0100000b;
+ ALG_SHA_512_224 = 0x0100000c;
+ ALG_SHA_512_256 = 0x0100000d;
+ ALG_SHA3_224 = 0x01000010;
+ ALG_SHA3_256 = 0x01000011;
+ ALG_SHA3_384 = 0x01000012;
+ ALG_SHA3_512 = 0x01000013;
+ ALG_CBC_MAC = 0x02c00001;
+ ALG_CMAC = 0x02c00002;
+ ALG_ARC4 = 0x04800001;
+ ALG_CHACHA20 = 0x04800005;
+ ALG_CTR = 0x04c00001;
+ ALG_CFB = 0x04c00002;
+ ALG_OFB = 0x04c00003;
+ ALG_XTS = 0x044000ff;
+ ALG_CBC_NO_PADDING = 0x04600100;
+ ALG_CBC_PKCS7 = 0x04600101;
+ ALG_AEAD_FROM_BLOCK_FLAG = 0x00400000;
+ ALG_CCM = 0x06401001;
+ ALG_GCM = 0x06401002;
+ ALG_CHACHA20_POLY1305 = 0x06001005;
+ ALG_RSA_PKCS1V15_SIGN_BASE = 0x10020000;
+ ALG_RSA_PSS_BASE = 0x10030000;
+ ALG_ECDSA_BASE = 0x10060000;
+ ALG_DETERMINISTIC_ECDSA_BASE = 0x10070000;
+ ALG_RSA_PKCS1V15_CRYPT = 0x12020000;
+ ALG_RSA_OAEP_BASE = 0x12030000;
+ ALG_HKDF_BASE = 0x20000100;
+ ALG_TLS12_PRF_BASE = 0x20000200;
+ ALG_TLS12_PSK_TO_MS_BASE = 0x20000300;
+ ALG_KEY_DERIVATION_MASK = 0x0803ffff;
+ ALG_KEY_AGREEMENT_MASK = 0x10fc0000;
+ ALG_FFDH = 0x30100000;
+ ALG_ECDH = 0x30200000;
+}
+
+/* Key lifetime */
+enum KeyLifetime {
+ KEY_LIFETIME_VOLATILE = 0x00000000;
+ KEY_LIFETIME_PERSISTENT = 0x00000001;
+}
+
+/* Key usage constraints */
+enum KeyUsage {
+ KEY_USAGE_NONE = 0x00000000;
+ KEY_USAGE_EXPORT = 0x00000001;
+ KEY_USAGE_COPY = 0x00000002;
+ KEY_USAGE_ENCRYPT = 0x00000100;
+ KEY_USAGE_DECRYPT = 0x00000200;
+ KEY_USAGE_SIGN_HASH = 0x00000400;
+ KEY_USAGE_VERIFY_HASH = 0x00000800;
+ KEY_USAGE_DERIVE = 0x00001000;
+}
+
+/* Key policy to define what key can be used for */
+message KeyPolicy {
+ uint32 usage = 1;
+ uint32 alg = 2;
+}
+
+/* Key attributes object */
+message KeyAttributes {
+ uint32 type = 1;
+ uint32 key_bits = 2;
+ uint32 lifetime = 3;
+ uint32 id = 4;
+ KeyPolicy policy = 5;
+} \ No newline at end of file
diff --git a/protocols/service/crypto/protobuf/opcodes.proto b/protocols/service/crypto/protobuf/opcodes.proto
new file mode 100644
index 000000000..b16127ec2
--- /dev/null
+++ b/protocols/service/crypto/protobuf/opcodes.proto
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+enum Opcode {
+ NOP = 0x0000;
+ GENERATE_KEY = 0x0101;
+ DESTROY_KEY = 0x0102;
+ OPEN_KEY = 0x0103;
+ CLOSE_KEY = 0x0104;
+ EXPORT_KEY = 0x0105;
+ EXPORT_PUBLIC_KEY = 0x0106;
+ IMPORT_KEY = 0x0107;
+ SIGN_HASH = 0x0108;
+ VERIFY_HASH = 0x0109;
+ ASYMMETRIC_DECRYPT = 0x010a;
+ ASYMMETRIC_ENCRYPT = 0x010b;
+ GENERATE_RANDOM = 0x010c;
+}
diff --git a/protocols/service/crypto/protobuf/open_key.proto b/protocols/service/crypto/protobuf/open_key.proto
new file mode 100644
index 000000000..90fb2ad6c
--- /dev/null
+++ b/protocols/service/crypto/protobuf/open_key.proto
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message OpenKeyIn {
+ uint32 id = 1;
+}
+
+message OpenKeyOut {
+ uint32 handle = 1;
+}
diff --git a/protocols/service/crypto/protobuf/sign_hash.proto b/protocols/service/crypto/protobuf/sign_hash.proto
new file mode 100644
index 000000000..a40900862
--- /dev/null
+++ b/protocols/service/crypto/protobuf/sign_hash.proto
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message SignHashIn {
+ uint32 handle = 1;
+ uint32 alg = 2;
+ bytes hash = 3;
+}
+
+message SignHashOut {
+ bytes signature = 1;
+}
diff --git a/protocols/service/crypto/protobuf/verify_hash.proto b/protocols/service/crypto/protobuf/verify_hash.proto
new file mode 100644
index 000000000..9253d9408
--- /dev/null
+++ b/protocols/service/crypto/protobuf/verify_hash.proto
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+syntax = "proto3";
+
+package ts_crypto;
+
+message VerifyHashIn {
+ uint32 handle = 1;
+ uint32 alg = 2;
+ bytes hash = 3;
+ bytes signature = 4;
+}
+
+message VerifyHashOut {}