Crypto: Add support for more ciphers
Extends the crypto engine to support more block ciphers and more cipher
modes with the Mbed TLS engine implementation.
Change-Id: I7d866d0276cbf97d49e3406e845ea230f8c74022
Signed-off-by: Jamie Fox <jamie.fox@arm.com>
diff --git a/secure_fw/services/crypto/crypto_engine.c b/secure_fw/services/crypto/crypto_engine.c
index 4f9290f..e1fdb17 100644
--- a/secure_fw/services/crypto/crypto_engine.c
+++ b/secure_fw/services/crypto/crypto_engine.c
@@ -27,51 +27,118 @@
static uint8_t mbedtls_mem_buf[TFM_CRYPTO_MBEDTLS_MEM_BUF_LEN] = {0};
/**
- * \brief This function maps Mbed TLS return codes to PSA return codes.
+ * \brief Converts a PSA key type and key size to an Mbed TLS cipher ID.
*
- * \param[in] ret Mbed TLS return value
+ * \param[in] key_type PSA key type
+ * \param[in] key_size Key size in bits
*
- * \return Return values as specified by \ref psa_status_t
+ * \return An mbedtls_cipher_id_t value corresponding to key_type and key_size,
+ * or MBEDTLS_CIPHER_ID_NONE if no such cipher ID is supported by
+ * Mbed TLS.
*/
-static psa_status_t mbedtls_to_psa_return(int ret)
+static mbedtls_cipher_id_t psa_to_mbedtls_cipher_id(psa_key_type_t key_type,
+ size_t key_size)
{
- /* zero return value means success */
- if (ret == 0) {
- return PSA_SUCCESS;
- }
-
- /* FIXME: For the time being map all errors to PSA_ERROR_UNKNOW_ERROR */
- switch (ret) {
+ switch (key_type) {
+ case PSA_KEY_TYPE_AES:
+ return MBEDTLS_CIPHER_ID_AES;
+ case PSA_KEY_TYPE_DES:
+ return (key_size == 192) ? MBEDTLS_CIPHER_ID_3DES
+ : MBEDTLS_CIPHER_ID_DES;
+ case PSA_KEY_TYPE_CAMELLIA:
+ return MBEDTLS_CIPHER_ID_CAMELLIA;
+ case PSA_KEY_TYPE_ARC4:
+ return MBEDTLS_CIPHER_ID_ARC4;
default:
- return PSA_ERROR_UNKNOWN_ERROR;
+ return MBEDTLS_CIPHER_ID_NONE;
}
}
-#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
-psa_status_t tfm_crypto_engine_init(void)
+/**
+ * \brief Converts a PSA algorithm to an Mbed TLS cipher mode.
+ *
+ * \param[in] alg PSA algorithm
+ *
+ * \return An mbedtls_cipher_mode_t value corresponding to alg, or
+ * MBEDTLS_MODE_NONE if no such cipher mode is supported by Mbed TLS.
+ */
+static mbedtls_cipher_mode_t psa_to_mbedtls_cipher_mode(psa_algorithm_t alg)
{
- psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
+ if (PSA_ALG_IS_BLOCK_CIPHER(alg)) {
+ /* Clear the padding mask */
+ alg &= ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
+ }
-#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
- /* Initialise the Mbed TLS static memory allocator so that Mbed TLS
- * allocates memory from the provided static buffer instead of from
- * the heap.
- */
- mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf,
- TFM_CRYPTO_MBEDTLS_MEM_BUF_LEN);
- /* The previous function doesn't return any error code */
- return_value = PSA_SUCCESS;
-#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
-
- return return_value;
+ switch (alg) {
+ case PSA_ALG_CBC_BASE:
+ return MBEDTLS_MODE_CBC;
+ case PSA_ALG_CFB_BASE:
+ return MBEDTLS_MODE_CFB;
+ case PSA_ALG_OFB_BASE:
+ return MBEDTLS_MODE_OFB;
+ case PSA_ALG_XTS_BASE:
+ return MBEDTLS_MODE_NONE; /* FIXME: requires Mbed TLS 2.11 */
+ case PSA_ALG_CTR:
+ return MBEDTLS_MODE_CTR;
+ case PSA_ALG_ARC4:
+ return MBEDTLS_MODE_STREAM; /* ARC4 is a stream cipher */
+ case PSA_ALG_CCM:
+ return MBEDTLS_MODE_CCM;
+ case PSA_ALG_GCM:
+ return MBEDTLS_MODE_GCM;
+ default:
+ return MBEDTLS_MODE_NONE;
+ }
}
-psa_status_t tfm_crypto_engine_hash_setup(const psa_algorithm_t alg,
- struct hash_engine_info *engine_info)
+/**
+ * \brief Given a PSA key type, algorithm and key size, finds the corresponding
+ * Mbed TLS cipher info struct.
+ *
+ * \param[in] key_type PSA key type
+ * \param[in] alg PSA algorithm
+ * \param[in] key_size Key size in bits
+ *
+ * \return A pointer to the mbedtls_cipher_info_t struct corresponding to
+ * key_type, alg and key_size, or NULL if Mbed TLS does not support this
+ * combination.
+ */
+static const mbedtls_cipher_info_t *get_mbedtls_cipher_info(
+ psa_key_type_t key_type,
+ psa_algorithm_t alg,
+ size_t key_size)
{
- psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
+ mbedtls_cipher_id_t cipher_id;
+ mbedtls_cipher_mode_t cipher_mode;
-#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
+ /* Get the Mbed TLS cipher ID */
+ cipher_id = psa_to_mbedtls_cipher_id(key_type, key_size);
+ if (cipher_id == MBEDTLS_CIPHER_ID_NONE) {
+ /* The requested key type is not supported by Mbed TLS */
+ return NULL;
+ }
+
+ /* Get the Mbed TLS cipher mode */
+ cipher_mode = psa_to_mbedtls_cipher_mode(alg);
+ if (cipher_mode == MBEDTLS_MODE_NONE) {
+ /* The requested algorithm is not supported by Mbed TLS */
+ return NULL;
+ }
+
+ /* Get the Mbed TLS cipher info pointer */
+ return mbedtls_cipher_info_from_values(cipher_id, key_size, cipher_mode);
+}
+
+/**
+ * \brief Converts a PSA algorithm to an Mbed TLS message digest type.
+ *
+ * \param[in] alg PSA algorithm
+ *
+ * \return An mbedtls_md_type_t value corresponding to alg, or
+ * MBEDTLS_MD_NONE if no such message digest is available.
+ */
+static mbedtls_md_type_t psa_to_mbedtls_md_type(psa_algorithm_t alg)
+{
mbedtls_md_type_t type = MBEDTLS_MD_NONE;
/* Mbed TLS message digest setup */
@@ -121,17 +188,77 @@
type = MBEDTLS_MD_SHA512;
#endif
break;
+ case PSA_ALG_SHA3_224:
+ case PSA_ALG_SHA3_256:
+ case PSA_ALG_SHA3_384:
+ case PSA_ALG_SHA3_512:
+ /* SHA3 not yet supported */
+ type = MBEDTLS_MD_NONE;
+ break;
+ case PSA_ALG_SHA_512_224:
+ case PSA_ALG_SHA_512_256:
+ /* SHA-512 Truncated modes not yet supported */
+ type = MBEDTLS_MD_NONE;
+ break;
default:
break;
}
+ return type;
+}
+
+/**
+ * \brief This function maps Mbed TLS return codes to PSA return codes.
+ *
+ * \param[in] ret Mbed TLS return value
+ *
+ * \return Return values as specified by \ref psa_status_t
+ */
+static psa_status_t mbedtls_to_psa_return(int ret)
+{
+ /* zero return value means success */
+ if (ret == 0) {
+ return PSA_SUCCESS;
+ }
+
+ /* FIXME: For the time being map all errors to PSA_ERROR_UNKNOW_ERROR */
+ switch (ret) {
+ default:
+ return PSA_ERROR_UNKNOWN_ERROR;
+ }
+}
+#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
+
+psa_status_t tfm_crypto_engine_init(void)
+{
+ psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
+
+#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
+ /* Initialise the Mbed TLS static memory allocator so that Mbed TLS
+ * allocates memory from the provided static buffer instead of from
+ * the heap.
+ */
+ mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf,
+ TFM_CRYPTO_MBEDTLS_MEM_BUF_LEN);
+ /* The previous function doesn't return any error code */
+ return_value = PSA_SUCCESS;
+#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
+
+ return return_value;
+}
+
+psa_status_t tfm_crypto_engine_hash_setup(const psa_algorithm_t alg,
+ struct hash_engine_info *engine_info)
+{
+ psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
+
+#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
+ mbedtls_md_type_t type = MBEDTLS_MD_NONE;
+
+ type = psa_to_mbedtls_md_type(alg);
+
engine_info->type = (uint32_t) type;
- /* Mbed TLS currently does not support SHA3: PSA_ALG_SHA3_224,
- * PSA_ALG_SHA3_256, PSA_ALG_SHA3_384, PSA_ALG_SHA3_512;
- * Mbed TLS currently does not support SHA-512 Truncated modes:
- * PSA_ALG_SHA_512_224, PSA_ALG_SHA_512_256
- */
if (type == MBEDTLS_MD_NONE) {
return_value = PSA_ERROR_NOT_SUPPORTED;
} else {
@@ -222,35 +349,24 @@
psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
- mbedtls_cipher_type_t type = MBEDTLS_CIPHER_NONE;
+ const mbedtls_cipher_info_t *info;
mbedtls_cipher_padding_t padding_mode = MBEDTLS_PADDING_NONE;
psa_algorithm_t padding_mode_field = PSA_ALG_BLOCK_CIPHER_PAD_NONE;
- /* FIXME: Check that key is compatible with alg. It's assumed that key
- * key_type will be AES, this needs to be extended as well. A
- * proper function to determine cipher type based on inputs
- * will need to be designed here.
- */
if ((engine_cipher_mode != ENGINE_CIPHER_MODE_ENCRYPT) &&
(engine_cipher_mode != ENGINE_CIPHER_MODE_DECRYPT)) {
return_value = PSA_ERROR_NOT_SUPPORTED;
} else {
- /* Mbed TLS cipher setup */
- if (key_size == 128) {
- if (alg == PSA_ALG_CBC_BASE) {
- type = MBEDTLS_CIPHER_AES_128_CBC;
- } else if (alg == PSA_ALG_CFB_BASE) {
- if (engine_cipher_mode == ENGINE_CIPHER_MODE_ENCRYPT) {
- type = MBEDTLS_CIPHER_AES_128_CFB128;
- }
- }
- }
-
- if (type == MBEDTLS_CIPHER_NONE) {
+ /* Get the Mbed TLS cipher info from PSA key_type/alg/key_size. */
+ info = get_mbedtls_cipher_info(key_type, alg, key_size);
+ if (info == NULL) {
+ /* The combination of key_type, alg and key_size is not a valid
+ * Mbed TLS cipher configuration.
+ */
return_value = PSA_ERROR_NOT_SUPPORTED;
} else {
- /* If CBC, need to set check the padding mode */
- if ((alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK) == PSA_ALG_CBC_BASE) {
+ /* If CBC, need to check the padding mode */
+ if ((alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK) == PSA_ALG_CBC_BASE){
/* Check the value of padding field */
padding_mode_field = alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
@@ -275,7 +391,7 @@
}
if (return_value == PSA_SUCCESS) {
- engine_info->type = (uint32_t) type;
+ engine_info->type = (uint32_t) (info->type);
engine_info->cipher_mode = engine_cipher_mode;
engine_info->padding_mode = (uint32_t) padding_mode;
}