Crypto: Align implementation to pass PSA API compliance

-- Enable the option to specify maximum supported key
   length and maximum number of key slots at build time
   for the key module
-- Enable the option to specify internal buffer size
   for scratch allocation at build time for the
   engine module
-- Make sure that MD-2 and MD-4 hashes are enabled and
   supported by the back end as they are tested by the
   PSA API compliance tests
-- Other alignment needed to pass PSA API compliance
   tests, as changes in return codes, more error
   checking, and documentation update when needed

Change-Id: I4bb78b06de2fa01580c4cbd361c946d32c614240
Signed-off-by: Jamie Fox <jamie.fox@arm.com>
Co-Authored-by: Antonio de Angelis <antonio.deangelis@arm.com>
diff --git a/secure_fw/services/crypto/crypto_aead.c b/secure_fw/services/crypto/crypto_aead.c
index ec8b3a1..1698fd0 100644
--- a/secure_fw/services/crypto/crypto_aead.c
+++ b/secure_fw/services/crypto/crypto_aead.c
@@ -16,6 +16,16 @@
 #include "tfm_crypto_api.h"
 #include "crypto_utils.h"
 
+/**
+ * \def CRYPTO_AEAD_MAX_KEY_LENGTH
+ *
+ * \brief Specifies the maximum key length supported by the
+ *        AEAD operations in this implementation
+ */
+#ifndef CRYPTO_AEAD_MAX_KEY_LENGTH
+#define CRYPTO_AEAD_MAX_KEY_LENGTH (32)
+#endif
+
 /*!
  * \defgroup public_psa Public functions, PSA
  *
@@ -36,12 +46,15 @@
 {
     psa_status_t status = PSA_SUCCESS;
     enum tfm_crypto_err_t err;
-    uint8_t key_data[TFM_CRYPTO_MAX_KEY_LENGTH];
+    uint8_t key_data[CRYPTO_AEAD_MAX_KEY_LENGTH];
     uint32_t key_size;
     psa_key_type_t key_type;
 
+    /* Initialise ciphertext_length to zero */
+    *ciphertext_length = 0;
+
     if (PSA_ALG_IS_AEAD(alg) == 0) {
-        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+        return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
     }
 
     if (PSA_AEAD_TAG_SIZE(alg) == 0) {
@@ -49,7 +62,7 @@
     }
 
     if (PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) > ciphertext_size) {
-        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+        return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
     }
 
     if ((nonce_length == 0) ||
@@ -98,7 +111,12 @@
     /* Access the key data */
     err = tfm_crypto_get_key_information(key, &key_type, (size_t *)&key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+        return err;
+    }
+
+    /* Support only AES based AEAD */
+    if (key_type != PSA_KEY_TYPE_AES) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
     }
 
     /* Access the crypto service key module to retrieve key data */
@@ -106,7 +124,7 @@
                              PSA_KEY_USAGE_ENCRYPT,
                              alg,
                              key_data,
-                             TFM_CRYPTO_MAX_KEY_LENGTH,
+                             CRYPTO_AEAD_MAX_KEY_LENGTH,
                              (size_t *)&key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         return err;
@@ -126,6 +144,13 @@
                                             ciphertext,
                                             ciphertext_size,
                                             (uint32_t *)ciphertext_length);
+    if (status == PSA_SUCCESS) {
+        /* The ciphertext_length needs to take into account the tag length */
+        *ciphertext_length += PSA_AEAD_TAG_SIZE(alg);
+    } else {
+        /* In case of failure set the ciphertext_length to zero */
+        *ciphertext_length = 0;
+    }
 
     return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
 }
@@ -144,20 +169,24 @@
 {
     psa_status_t status = PSA_SUCCESS;
     enum tfm_crypto_err_t err;
-    uint8_t key_data[TFM_CRYPTO_MAX_KEY_LENGTH];
+    uint8_t key_data[CRYPTO_AEAD_MAX_KEY_LENGTH];
     uint32_t key_size;
     psa_key_type_t key_type;
 
+    /* Initialise plaintext_length to zero */
+    *plaintext_length = 0;
+
     if (PSA_ALG_IS_AEAD(alg) == 0) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if ((PSA_AEAD_TAG_SIZE(alg) == 0) ||
+        (ciphertext_length < PSA_AEAD_TAG_SIZE(alg))) {
         return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    if (PSA_AEAD_TAG_SIZE(alg) == 0) {
-        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    if (PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) > plaintext_size) {
-        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    if (PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg,ciphertext_length) > plaintext_size) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
     }
 
     if ((nonce_length == 0) ||
@@ -206,7 +235,12 @@
     /* Access the key data */
     err = tfm_crypto_get_key_information(key, &key_type, (size_t *)&key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+        return err;
+    }
+
+    /* Support only AES based AEAD */
+    if (key_type != PSA_KEY_TYPE_AES) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
     }
 
     /* Access the crypto service key module to retrieve key data */
@@ -214,7 +248,7 @@
                              PSA_KEY_USAGE_DECRYPT,
                              alg,
                              key_data,
-                             TFM_CRYPTO_MAX_KEY_LENGTH,
+                             CRYPTO_AEAD_MAX_KEY_LENGTH,
                              (size_t *)&key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         return err;
@@ -234,6 +268,9 @@
                                             plaintext,
                                             plaintext_size,
                                             (uint32_t *)plaintext_length);
+    if (status != PSA_SUCCESS) {
+        *plaintext_length = 0;
+    }
 
     return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
 }