Crypto: Add test vectors for RFC7539

Adds two specific tests to verify Chacha20 and Chacha20-Poly1305
against test vectors available in RFC7539.

Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I082777bd8da7f3a41840d7ef5d2f666fb4c23eb7
diff --git a/test/secure_fw/suites/crypto/crypto_tests_common.c b/test/secure_fw/suites/crypto/crypto_tests_common.c
index 3eb495e..49d4d5e 100644
--- a/test/secure_fw/suites/crypto/crypto_tests_common.c
+++ b/test/secure_fw/suites/crypto/crypto_tests_common.c
@@ -189,7 +189,7 @@
     /* Set the IV */
     status = psa_cipher_set_iv(&handle, iv, iv_length);
     if (status != PSA_SUCCESS) {
-        TEST_FAIL("Error setting the IV on the cypher operation object");
+        TEST_FAIL("Error setting the IV on the cipher operation object");
         goto abort;
     }
 
@@ -401,6 +401,572 @@
     }
 }
 
+#ifdef TFM_CRYPTO_TEST_CHACHA20
+/* Chacha20 test vectors are taken directly from RFC7539 */
+static const uint8_t chacha20_testKey[] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+static const uint8_t chacha20_testNonce[] = {
+  0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x4a,
+  0x00, 0x00, 0x00, 0x00
+};
+
+/* The initial counter of the Chacha20 RFC7539 test vectors is 1, while the PSA
+ * APIs assume it to be zero. This means that this expected ciphertext is not
+ * the same as the one presented in the RFC
+ */
+static const uint8_t chacha20_testCiphertext_expected[] = {
+  0xe3, 0x64, 0x7a, 0x29, 0xde, 0xd3, 0x15, 0x28, 0xef, 0x56, 0xba, 0xc7,
+  0x0f, 0x7a, 0x7a, 0xc3, 0xb7, 0x35, 0xc7, 0x44, 0x4d, 0xa4, 0x2d, 0x99,
+  0x82, 0x3e, 0xf9, 0x93, 0x8c, 0x8e, 0xbf, 0xdc, 0xf0, 0x5b, 0xb7, 0x1a,
+  0x82, 0x2c, 0x62, 0x98, 0x1a, 0xa1, 0xea, 0x60, 0x8f, 0x47, 0x93, 0x3f,
+  0x2e, 0xd7, 0x55, 0xb6, 0x2d, 0x93, 0x12, 0xae, 0x72, 0x03, 0x76, 0x74,
+  0xf3, 0xe9, 0x3e, 0x24, 0x4c, 0x23, 0x28, 0xd3, 0x2f, 0x75, 0xbc, 0xc1,
+  0x5b, 0xb7, 0x57, 0x4f, 0xde, 0x0c, 0x6f, 0xcd, 0xf8, 0x7b, 0x7a, 0xa2,
+  0x5b, 0x59, 0x72, 0x97, 0x0c, 0x2a, 0xe6, 0xcc, 0xed, 0x86, 0xa1, 0x0b,
+  0xe9, 0x49, 0x6f, 0xc6, 0x1c, 0x40, 0x7d, 0xfd, 0xc0, 0x15, 0x10, 0xed,
+  0x8f, 0x4e, 0xb3, 0x5d, 0x0d, 0x62
+};
+#endif /* TFM_CRYPTO_TEST_CHACHA20 */
+
+#if defined(TFM_CRYPTO_TEST_CHACHA20) ||      \
+    defined(TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305)
+/* The plaintext of the vectors is the same for both Chacha20 and
+ * Chacha20-Poly1305
+ */
+static const uint8_t chacha20_testPlaintext[] = {
+  0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47,
+  0x65, 0x6e, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+  0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66,
+  0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
+  0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79,
+  0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
+  0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+  0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
+  0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
+  0x62, 0x65, 0x20, 0x69, 0x74, 0x2e
+};
+/* To hold intermediate results in both Chacha20 and Chacha20-Poly1305 */
+static uint8_t chacha20_testCiphertext[sizeof(chacha20_testPlaintext)] = {0};
+static uint8_t chacha20_testDecryptedtext[sizeof(chacha20_testPlaintext)] = {0};
+#endif /* TFM_CRYPTO_TEST_CHACHA20 || TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */
+
+#ifdef TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305
+/* Chacha20-Poly1305 test vectors are taken directly from RFC7539 */
+static const uint8_t chacha20poly1305_testKey[] = {
+  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
+};
+
+static const uint8_t chacha20poly1305_testNonce[] = {
+  0x07, 0x00, 0x00, 0x00, /* constant */
+  0x40, 0x41, 0x42, 0x43, /* IV[0] */
+  0x44, 0x45, 0x46, 0x47  /* IV[1] */
+};
+
+static const uint8_t chacha20poly1305_testAad[] = {
+  0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7
+};
+
+static const uint8_t chacha20poly1305_testCiphertext_expected[] = {
+  0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc,
+  0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
+  0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e,
+  0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
+  0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6,
+  0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
+  0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4,
+  0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
+  0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65,
+  0x86, 0xce, 0xc6, 0x4b, 0x61, 0x16
+};
+
+static const uint8_t chacha20poly1305_testTag_expected[] = {
+  0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
+  0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
+};
+#endif /* TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */
+
+#define LOG_INF(...) printf(__VA_ARGS__)
+#define LOG_HEXDUMP_INF(a,b,c)      \
+    do {                            \
+       LOG_INF(c);            \
+       for (int i=0; i<b; i++) {    \
+           LOG_INF("0x%x, ", a[i]); \
+       }                            \
+       printf("\r\n");              \
+    }                               \
+    while (0)
+
+#ifdef TFM_CRYPTO_TEST_CHACHA20
+void psa_cipher_rfc7539_test(struct test_result_t *ret)
+{
+    psa_cipher_operation_t handle = psa_cipher_operation_init();
+    psa_cipher_operation_t handle_dec = psa_cipher_operation_init();
+    psa_status_t status = PSA_SUCCESS;
+    psa_key_handle_t key_handle;
+    psa_key_attributes_t key_attributes = psa_key_attributes_init();
+    psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+    const psa_key_type_t key_type = PSA_KEY_TYPE_CHACHA20;
+    const psa_algorithm_t alg = PSA_ALG_STREAM_CIPHER;
+    bool bAbortDecryption = false;
+    /* Variables required during multipart update */
+    size_t data_left = sizeof(chacha20_testPlaintext);
+    size_t lengths[] = {42, 24, 48};
+    size_t start_idx = 0;
+    size_t output_length = 0; size_t total_output_length = 0;
+    int comp_result;
+
+    ret->val = TEST_PASSED;
+
+    /* Setup the key policy */
+    psa_set_key_usage_flags(&key_attributes, usage);
+    psa_set_key_algorithm(&key_attributes, alg);
+    psa_set_key_type(&key_attributes, key_type);
+    psa_set_key_id(&key_attributes, CIPHER_TEST_KEY_ID);
+    status = psa_import_key(&key_attributes, chacha20_testKey,
+                            sizeof(chacha20_testKey), &key_handle);
+
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error importing a key");
+        return;
+    }
+
+    /* Setup the encryption object */
+    status = psa_cipher_encrypt_setup(&handle, key_handle, alg);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Encryption setup shouldn't fail");
+        goto destroy_key;
+    }
+
+    /* Set the IV */
+    status = psa_cipher_set_iv(&handle,
+                               chacha20_testNonce, sizeof(chacha20_testNonce));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error setting the IV on the cipher operation object");
+        goto abort;
+    }
+
+    for (int i=0; i<sizeof(lengths)/sizeof(size_t); i++) {
+        /* Encrypt one chunk of information */
+        status = psa_cipher_update(
+                        &handle,
+                        &chacha20_testPlaintext[start_idx],
+                        lengths[i],
+                        &chacha20_testCiphertext[total_output_length],
+                        sizeof(chacha20_testCiphertext) - total_output_length,
+                        &output_length);
+
+        if (status != PSA_SUCCESS) {
+            TEST_FAIL("Error encrypting one chunk of information");
+            goto abort;
+        }
+
+        if (output_length != lengths[i]) {
+            TEST_FAIL("Expected encrypted length is different from expected");
+            goto abort;
+        }
+
+        data_left -= lengths[i];
+        total_output_length += output_length;
+
+        start_idx += lengths[i];
+    }
+
+    /* Finalise the cipher operation */
+    status = psa_cipher_finish(
+                    &handle,
+                    &chacha20_testCiphertext[total_output_length],
+                    sizeof(chacha20_testCiphertext) - total_output_length,
+                    &output_length);
+
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error finalising the cipher operation");
+        goto abort;
+    }
+
+    if (output_length != 0) {
+        TEST_FAIL("Un-padded mode final output length unexpected");
+        goto abort;
+    }
+
+    /* Add the last output produced, it might be encrypted padding */
+    total_output_length += output_length;
+
+    /* Compare encrypted data produced with single-shot and multipart APIs */
+    comp_result = compare_buffers(chacha20_testCiphertext_expected,
+                                  chacha20_testCiphertext,
+                                  total_output_length);
+    if (comp_result != 0) {
+        TEST_FAIL("Single-shot crypt doesn't match with multipart crypt");
+        goto destroy_key;
+    }
+
+    /* Setup the decryption object */
+    status = psa_cipher_decrypt_setup(&handle_dec, key_handle, alg);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error setting up cipher operation object");
+        goto destroy_key;
+    }
+
+    /* From now on, in case of failure we want to abort the decryption op */
+    bAbortDecryption = true;
+
+    /* Set the IV for decryption */
+    status = psa_cipher_set_iv(&handle_dec,
+                               chacha20_testNonce, sizeof(chacha20_testNonce));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error setting the IV for decryption");
+        goto abort;
+    }
+
+    /* Decrypt - total_output_length considers encrypted padding */
+    data_left = total_output_length;
+    /* Update in different chunks of plainText */
+    lengths[0] = 14; lengths[1] = 70; lengths[2] = 30;
+    start_idx = 0;
+    output_length = 0; total_output_length = 0;
+    for (int i=0; i<sizeof(lengths)/sizeof(size_t); i++) {
+        status = psa_cipher_update(
+                    &handle_dec,
+                    &chacha20_testCiphertext[start_idx],
+                    lengths[i],
+                    &chacha20_testDecryptedtext[total_output_length],
+                    sizeof(chacha20_testDecryptedtext) - total_output_length,
+                    &output_length);
+
+        if (status != PSA_SUCCESS) {
+            TEST_FAIL("Error decrypting one chunk of information");
+            goto abort;
+        }
+
+        if (output_length != lengths[i]) {
+            TEST_FAIL("Expected encrypted length is different from expected");
+            goto abort;
+        }
+
+        data_left -= lengths[i];
+        total_output_length += output_length;
+
+        start_idx += lengths[i];
+    }
+
+    /* Finalise the cipher operation for decryption */
+    status = psa_cipher_finish(
+                    &handle_dec,
+                    &chacha20_testDecryptedtext[total_output_length],
+                    sizeof(chacha20_testDecryptedtext) - total_output_length,
+                    &output_length);
+
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error finalising the cipher operation");
+        goto abort;
+    }
+
+    /* Finalize the count of output which has been produced */
+    total_output_length += output_length;
+
+    /* Check that the decrypted length is equal to the original length */
+    if (total_output_length != sizeof(chacha20_testPlaintext)) {
+        TEST_FAIL("After finalising, unexpected decrypted length");
+        goto destroy_key;
+    }
+
+    /* Check that the plain text matches the decrypted data */
+    comp_result = compare_buffers(chacha20_testPlaintext,
+                                  chacha20_testDecryptedtext,
+                                  sizeof(chacha20_testPlaintext));
+    if (comp_result != 0) {
+        TEST_FAIL("Decrypted data doesn't match with plain text");
+    }
+
+    /* Go directly to the destroy_key label at this point */
+    goto destroy_key;
+
+abort:
+    /* Abort the operation */
+    status = bAbortDecryption ? psa_cipher_abort(&handle_dec) :
+                                psa_cipher_abort(&handle);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error aborting the operation");
+    }
+destroy_key:
+    /* Destroy the key */
+    status = psa_destroy_key(key_handle);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error destroying a key");
+    }
+
+    return;
+}
+#endif /* TFM_CRYPTO_TEST_CHACHA20 */
+
+#ifdef TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305
+void psa_aead_rfc7539_test(struct test_result_t *ret)
+{
+    psa_aead_operation_t handle = psa_aead_operation_init();
+    psa_aead_operation_t handle_dec = psa_aead_operation_init();
+    psa_status_t status = PSA_SUCCESS;
+    psa_key_handle_t key_handle;
+    psa_key_attributes_t key_attributes = psa_key_attributes_init();
+    psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+    const psa_key_type_t key_type = PSA_KEY_TYPE_CHACHA20;
+    const psa_algorithm_t alg = PSA_ALG_CHACHA20_POLY1305;
+    uint8_t tag[16] = {0}; /* tag in chacha20-poly1305 is 16 bytes */
+    size_t tag_length = 0;
+    bool bAbortDecryption = false;
+    /* Variables related to multipart update */
+    size_t data_left = sizeof(chacha20_testPlaintext);
+    size_t lengths[] = {42, 24, 48};
+    size_t start_idx = 0;
+    size_t output_length = 0; size_t total_output_length = 0;
+    int comp_result;
+
+    ret->val = TEST_PASSED;
+
+    /* Setup the key policy */
+    psa_set_key_usage_flags(&key_attributes, usage);
+    psa_set_key_algorithm(&key_attributes, alg);
+    psa_set_key_type(&key_attributes, key_type);
+    status = psa_import_key(&key_attributes, chacha20poly1305_testKey,
+                            sizeof(chacha20poly1305_testKey), &key_handle);
+
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error importing a key");
+        return;
+    }
+
+    /* Setup the encryption object */
+    status = psa_aead_encrypt_setup(&handle, key_handle, alg);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Encryption setup shouldn't fail");
+        goto destroy_key;
+    }
+
+    /* Set the IV */
+    status = psa_aead_set_nonce(&handle,
+                                chacha20poly1305_testNonce,
+                                sizeof(chacha20poly1305_testNonce));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error setting the nonce on the aead operation object");
+        goto abort;
+    }
+
+    /* Set lengths */
+    status = psa_aead_set_lengths(&handle,
+                                  sizeof(chacha20poly1305_testAad),
+                                  sizeof(chacha20_testPlaintext));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error setting the lengths on the aead operation object");
+        goto abort;
+    }
+
+    /* Update AD in one go */
+    status = psa_aead_update_ad(&handle,
+                                chacha20poly1305_testAad,
+                                sizeof(chacha20poly1305_testAad));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error updating AD");
+        goto abort;
+    }
+
+    for (int i=0; i<sizeof(lengths)/sizeof(size_t); i++) {
+        /* Encrypt one chunk of information */
+        status = psa_aead_update(
+                        &handle,
+                        &chacha20_testPlaintext[start_idx],
+                        lengths[i],
+                        &chacha20_testCiphertext[total_output_length],
+                        sizeof(chacha20_testCiphertext) - total_output_length,
+                        &output_length);
+
+        if (status != PSA_SUCCESS) {
+            TEST_FAIL("Error encrypting one chunk of information");
+            goto abort;
+        }
+
+        if (output_length != lengths[i]) {
+            TEST_FAIL("Expected encrypted length is different from expected");
+            goto abort;
+        }
+
+        data_left -= lengths[i];
+        total_output_length += output_length;
+
+        start_idx += lengths[i];
+    }
+
+    /* Finalise the cipher operation */
+    status = psa_aead_finish(
+                    &handle,
+                    &chacha20_testCiphertext[total_output_length],
+                    sizeof(chacha20_testCiphertext) - total_output_length,
+                    &output_length,
+                    tag,
+                    sizeof(tag),
+                    &tag_length);
+
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error finalising the cipher operation");
+        goto abort;
+    }
+
+    if (output_length != 0) {
+        TEST_FAIL("Un-padded mode final output length unexpected");
+        goto abort;
+    }
+
+    if (tag_length != 16) {
+        TEST_FAIL("Unexpected tag length different than 16");
+        goto abort;
+    }
+
+    /* Add the last output produced, it might be encrypted padding */
+    total_output_length += output_length;
+
+    /* Compare encrypted data produced with single-shot and multipart APIs */
+    comp_result = compare_buffers(chacha20poly1305_testCiphertext_expected,
+                                  chacha20_testCiphertext,
+                                  total_output_length);
+    if (comp_result != 0) {
+        TEST_FAIL("Encrypted data does not match reference data");
+        goto destroy_key;
+    }
+
+    comp_result = compare_buffers(chacha20poly1305_testTag_expected,
+                                  tag, tag_length);
+    if (comp_result != 0) {
+        TEST_FAIL("Computed tag does not match reference data");
+        goto destroy_key;
+    }
+
+    /* Setup the decryption object */
+    status = psa_aead_decrypt_setup(&handle_dec, key_handle, alg);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error setting up aead operation object");
+        goto destroy_key;
+    }
+
+    /* From now on, in case of failure we want to abort the decryption op */
+    bAbortDecryption = true;
+
+    /* Set the IV for decryption */
+    status = psa_aead_set_nonce(&handle_dec,
+                                chacha20poly1305_testNonce,
+                                sizeof(chacha20poly1305_testNonce));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error setting the nonce for decryption");
+        goto abort;
+    }
+
+    /* Set lengths */
+    status = psa_aead_set_lengths(&handle_dec,
+                                  sizeof(chacha20poly1305_testAad),
+                                  sizeof(chacha20_testPlaintext));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error setting the lengths on the aead operation object");
+        goto abort;
+    }
+
+    /* Update AD in one go */
+    status = psa_aead_update_ad(&handle_dec,
+                                chacha20poly1305_testAad,
+                                sizeof(chacha20poly1305_testAad));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error updating AD");
+        goto abort;
+    }
+
+    /* Decrypt - total_output_length considers encrypted padding */
+    data_left = total_output_length;
+    /* Update in different chunks of plainText */
+    lengths[0] = 14; lengths[1] = 70; lengths[2] = 30;
+    start_idx = 0;
+    output_length = 0; total_output_length = 0;
+    for (int i=0; i<sizeof(lengths)/sizeof(size_t); i++) {
+        status = psa_aead_update(
+                    &handle_dec,
+                    &chacha20_testCiphertext[start_idx],
+                    lengths[i],
+                    &chacha20_testDecryptedtext[total_output_length],
+                    sizeof(chacha20_testDecryptedtext) - total_output_length,
+                    &output_length);
+
+        if (status != PSA_SUCCESS) {
+            TEST_FAIL("Error decrypting one chunk of information");
+            goto abort;
+        }
+
+        if (output_length != lengths[i]) {
+            TEST_FAIL("Expected encrypted length is different from expected");
+            goto abort;
+        }
+
+        data_left -= lengths[i];
+        total_output_length += output_length;
+
+        start_idx += lengths[i];
+    }
+
+    /* Finalise the cipher operation for decryption (destroys decrypted data) */
+    status = psa_aead_verify(
+                    &handle_dec,
+                    &chacha20_testDecryptedtext[total_output_length],
+                    sizeof(chacha20_testDecryptedtext) - total_output_length,
+                    &output_length,
+                    tag,
+                    tag_length);
+
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error verifying the aead operation");
+        goto abort;
+    }
+
+    /* Finalize the count of output which has been produced */
+    total_output_length += output_length;
+
+    /* Check that the decrypted length is equal to the original length */
+    if (total_output_length != sizeof(chacha20_testPlaintext)) {
+        TEST_FAIL("After finalising, unexpected decrypted length");
+        goto destroy_key;
+    }
+
+    /* Check that the plain text matches the decrypted data */
+    comp_result = compare_buffers(chacha20_testPlaintext,
+                                  chacha20_testDecryptedtext,
+                                  sizeof(chacha20_testPlaintext));
+    if (comp_result != 0) {
+        TEST_FAIL("Decrypted data doesn't match with plain text");
+    }
+
+    /* Go directly to the destroy_key label at this point */
+    goto destroy_key;
+
+abort:
+    /* Abort the operation */
+    status = bAbortDecryption ? psa_aead_abort(&handle_dec) :
+                                psa_aead_abort(&handle);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error aborting the operation");
+    }
+destroy_key:
+    /* Destroy the key */
+    status = psa_destroy_key(key_handle);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error destroying a key");
+    }
+
+    return;
+}
+#endif /* TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */
+
 void psa_cipher_test(const psa_key_type_t key_type,
                      const psa_algorithm_t alg,
                      const uint8_t *key,
@@ -467,7 +1033,7 @@
 
     psa_reset_key_attributes(&key_attributes);
 
-    /* Replicate the encryption-decryption test above using single-shot APIs */
+    /* Encrypt single part functions */
     status = psa_cipher_encrypt(CIPHER_TEST_KEY_ID, alg, plain_text,
                                 sizeof(plain_text),
                                 input.encrypted_data_pad,
@@ -544,7 +1110,7 @@
     if (alg != PSA_ALG_ECB_NO_PADDING) {
         status = psa_cipher_set_iv(&handle, iv, iv_length);
         if (status != PSA_SUCCESS) {
-            TEST_FAIL("Error setting the IV on the cypher operation object");
+            TEST_FAIL("Error setting the IV on the cipher operation object");
             goto abort;
         }
     }
@@ -1210,8 +1776,8 @@
          * just to skip the multipart APIs test flow from this point on
          */
         if (status == PSA_ERROR_NOT_SUPPORTED) {
-            TEST_LOG("Algorithm NOT SUPPORTED by the implementation "\
-                     "- skip multipart API flow\r\n");
+            TEST_LOG("psa_aead_encrypt_setup(): Algorithm NOT SUPPORTED by"\
+                     " the implementation - skip multipart API flow\r\n");
         } else {
             TEST_FAIL("Error setting up encryption object");
         }
@@ -1230,8 +1796,8 @@
          */
         if (PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) == PSA_ALG_CCM
             && status == PSA_ERROR_NOT_SUPPORTED) {
-            TEST_LOG("Algorithm NOT SUPPORTED by the implementation "\
-                     "- skip multipart API flow\r\n");
+            TEST_LOG("psa_aead_set_lengths(): Algorithm NOT SUPPORTED by the"\
+                     "implementation - skip multipart API flow\r\n");
         } else {
             TEST_FAIL("Error setting lengths");
         }
@@ -1246,16 +1812,14 @@
     status = psa_aead_set_nonce(&encop, nonce, nonce_length);
     if (status != PSA_SUCCESS) {
         /* Implementations using the mbed TLS _ALT APIs, that don't support
-         * multipart API flows in GCM or ChaCha20_Poly1305 modes, will return
-         * PSA_ERROR_NOT_SUPPORTED when calling psa_aead_set_nonce(). In this
-         * case, it's fine just to skip the multipart APIs test flow from
-         * this point on
+         * multipart API flows in GCM, will return PSA_ERROR_NOT_SUPPORTED when
+         * calling psa_aead_set_nonce(). In this case, it's fine just to skip
+         * the multipart APIs test flow from this point on
          */
-        if ((PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) == PSA_ALG_GCM ||
-             PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) ==
-             PSA_ALG_CHACHA20_POLY1305) && status == PSA_ERROR_NOT_SUPPORTED) {
-            TEST_LOG("Algorithm NOT SUPPORTED by the implementation "\
-                     "- skip multipart API flow\r\n");
+        if (PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) == PSA_ALG_GCM
+            && status == PSA_ERROR_NOT_SUPPORTED) {
+            TEST_LOG("psa_aead_set_nonce(): Algorithm NOT SUPPORTED by the "\
+                     "implementation - skip multipart API flow\r\n");
         } else {
             TEST_FAIL("Error setting nonce");
         }
diff --git a/test/secure_fw/suites/crypto/crypto_tests_common.h b/test/secure_fw/suites/crypto/crypto_tests_common.h
index 7a14e10..57e0e37 100644
--- a/test/secure_fw/suites/crypto/crypto_tests_common.h
+++ b/test/secure_fw/suites/crypto/crypto_tests_common.h
@@ -40,9 +40,8 @@
 #define BYTE_SIZE_CHUNK (16)
 
 /**
- * \brief Size in bytes of the plain data processed in cipher
- *        tests
- * 
+ * \brief Size in bytes of the plain data processed in cipher tests
+ *
  */
 #define PLAIN_DATA_SIZE (3 * BYTE_SIZE_CHUNK)
 
@@ -59,18 +58,15 @@
  */
 #define ENC_DEC_BUFFER_SIZE_PAD_MODES (ENC_DEC_BUFFER_SIZE + BYTE_SIZE_CHUNK)
 
-
 /**
  * \brief Size in bytes of the small input plain data that is used for
  *        the dedicated tests for padded modes which process smaller
- *        chunks of data 
+ *        chunks of data
  */
 #define PLAIN_DATA_SIZE_PAD_TEST (BYTE_SIZE_CHUNK + BYTE_SIZE_CHUNK / 2)
 /**
- * \brief Size in bytes of the encrypted/decrypted buffers for the
- *        dedicated tests for padded modes which process smaller
- *        chunks of data
- * 
+ * \brief Size in bytes of the encrypted/decrypted buffers for the dedicated
+ *        tests for padded modes which process smaller chunks of data
  */
 #define ENC_DEC_BUFFER_SIZE_PAD_TEST (2 * BYTE_SIZE_CHUNK)
 
@@ -285,6 +281,24 @@
 void psa_sign_verify_message_test(psa_algorithm_t alg,
                                   struct test_result_t *ret);
 
+#ifdef TFM_CRYPTO_TEST_CHACHA20
+/**
+ * \brief Verification of Chacha20 using RFC7539 test vectors
+ *
+ * \param[out] ret Test result
+ */
+void psa_cipher_rfc7539_test(struct test_result_t *ret);
+#endif /* TFM_CRYPTO_TEST_CHACHA20 */
+
+#ifdef TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305
+/**
+ * \brief Verification of Chacha20-Poly1305 using RFC7539 test vectors
+ *
+ * \param[out] ret Test result
+ */
+void psa_aead_rfc7539_test(struct test_result_t *ret);
+#endif /* TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/test/secure_fw/suites/crypto/non_secure/crypto_ns_interface_testsuite.c b/test/secure_fw/suites/crypto/non_secure/crypto_ns_interface_testsuite.c
index 1c15bbe..52d9a16 100644
--- a/test/secure_fw/suites/crypto/non_secure/crypto_ns_interface_testsuite.c
+++ b/test/secure_fw/suites/crypto/non_secure/crypto_ns_interface_testsuite.c
@@ -185,11 +185,11 @@
 #endif /* TFM_CRYPTO_TEST_ALG_CBC */
 #ifdef TFM_CRYPTO_TEST_CHACHA20
     {&tfm_crypto_test_1048, "TFM_NS_CRYPTO_TEST_1048",
-     "Non Secure Symmetric encryption (CHACHA20-256) interface"},
+     "Non Secure Symmetric encryption (CHACHA20) interface"},
 #endif /* TFM_CRYPTO_TEST_CHACHA20 */
 #ifdef TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305
     {&tfm_crypto_test_1049, "TFM_NS_CRYPTO_TEST_1049",
-     "Non Secure AEAD (CHACHA20-256-POLY1305) interface"},
+     "Non Secure AEAD (CHACHA20-POLY1305) interface"},
 #endif /* TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */
 };
 
diff --git a/test/secure_fw/suites/crypto/secure/crypto_sec_interface_testsuite.c b/test/secure_fw/suites/crypto/secure/crypto_sec_interface_testsuite.c
index c731b08..d319d94 100644
--- a/test/secure_fw/suites/crypto/secure/crypto_sec_interface_testsuite.c
+++ b/test/secure_fw/suites/crypto/secure/crypto_sec_interface_testsuite.c
@@ -79,9 +79,11 @@
 #endif /* TFM_CRYPTO_TEST_ALG_CBC */
 #ifdef TFM_CRYPTO_TEST_CHACHA20
 static void tfm_crypto_test_1049(struct test_result_t *ret);
+static void tfm_crypto_test_1051(struct test_result_t *ret);
 #endif /* TFM_CRYPTO_TEST_CHACHA20 */
 #ifdef TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305
 static void tfm_crypto_test_1050(struct test_result_t *ret);
+static void tfm_crypto_test_1052(struct test_result_t *ret);
 #endif /* TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */
 
 static struct test_t crypto_tests[] = {
@@ -189,11 +191,19 @@
 #endif /* TFM_CRYPTO_TEST_ALG_CBC */
 #ifdef TFM_CRYPTO_TEST_CHACHA20
     {&tfm_crypto_test_1049, "TFM_S_CRYPTO_TEST_1049",
-     "Secure Symmetric encryption (CHACHA20-256) interface"},
+     "Secure Symmetric encryption (CHACHA20) interface"},
 #endif /* TFM_CRYPTO_TEST_CHACHA20 */
 #ifdef TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305
     {&tfm_crypto_test_1050, "TFM_S_CRYPTO_TEST_1050",
-     "Secure AEAD (CHACHA20-256-POLY1305) interface"},
+     "Secure AEAD (CHACHA20-POLY1305) interface"},
+#endif /* TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */
+#ifdef TFM_CRYPTO_TEST_CHACHA20
+    {&tfm_crypto_test_1051, "TFM_S_CRYPTO_TEST_1051",
+     "Secure RFC7539 verification on Chacha20"},
+#endif /* TFM_CRYPTO_TEST_CHACHA20 */
+#ifdef TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305
+    {&tfm_crypto_test_1052, "TFM_S_CRYPTO_TEST_1052",
+     "Secure RFC7539 verification on Chacha20-Poly1305"},
 #endif /* TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */
 };
 
@@ -485,6 +495,11 @@
     psa_cipher_test(PSA_KEY_TYPE_CHACHA20, PSA_ALG_STREAM_CIPHER,
                     test_key_256, BIT_SIZE_TEST_LONG_KEY, ret);
 }
+
+static void tfm_crypto_test_1051(struct test_result_t *ret)
+{
+    psa_cipher_rfc7539_test(ret);
+}
 #endif /* TFM_CRYPTO_TEST_CHACHA20 */
 
 #ifdef TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305
@@ -493,4 +508,9 @@
     psa_aead_test(PSA_KEY_TYPE_CHACHA20, PSA_ALG_CHACHA20_POLY1305,
                   test_key_256, BIT_SIZE_TEST_LONG_KEY, ret);
 }
+
+static void tfm_crypto_test_1052(struct test_result_t *ret)
+{
+    psa_aead_rfc7539_test(ret);
+}
 #endif /* TFM_CRYPTO_TEST_ALG_CHACHA20_POLY1305 */