Add test cases for AES GCM input and output buffer overlap

This commit adds test cases for input and output buffer overlap. The
data for the test cases is a duplicate of existing encrypt/decrypt test
cases.

The two test functions gcm_<encrypt/decrypt>_input_output_buffer_overlap
are modified to use a single malloc buffer rounded to the nearest
128-bits/16-bytes for input and output.

Signed-off-by: Harry Ramsey <harry.ramsey@arm.com>
diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function
index 8bb7b8b..107cc8d 100644
--- a/tests/suites/test_suite_gcm.function
+++ b/tests/suites/test_suite_gcm.function
@@ -605,6 +605,146 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void gcm_encrypt_input_output_buffer_overlap(int cipher_id, data_t *key_str,
+                                             data_t *src_str, data_t *iv_str,
+                                             data_t *add_str, data_t *dst,
+                                             int tag_len_bits, data_t *tag,
+                                             int init_result)
+{
+    unsigned char *buffer = NULL;
+    size_t buffer_len;
+    unsigned char tag_output[16];
+    mbedtls_gcm_context ctx;
+    size_t tag_len = tag_len_bits / 8;
+    size_t n1;
+    size_t n1_add;
+
+    BLOCK_CIPHER_PSA_INIT();
+    mbedtls_gcm_init(&ctx);
+
+    /* GCM includes padding and therefore input length can be shorter than the output length
+     * Therefore we must ensure we round up to the nearest 128-bits/16-bytes.
+     */
+    buffer_len = src_str->len;
+    if (buffer_len % 16 != 0) {
+        buffer_len += (16 - (buffer_len % 16));
+    }
+    TEST_CALLOC(buffer, buffer_len);
+    if (buffer == NULL) {
+        TEST_FAIL("Could not allocate memory for input output buffer overlap");
+        goto exit;
+    }
+    memcpy(buffer, src_str->x, src_str->len);
+
+    memset(tag_output, 0x00, 16);
+
+    TEST_ASSERT(mbedtls_gcm_setkey(&ctx, cipher_id, key_str->x, key_str->len * 8) == init_result);
+    if (init_result == 0) {
+        TEST_ASSERT(mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, src_str->len, iv_str->x,
+                                              iv_str->len, add_str->x, add_str->len, buffer,
+                                              buffer, tag_len, tag_output) == 0);
+
+        TEST_MEMORY_COMPARE(buffer, src_str->len, dst->x, dst->len);
+        TEST_MEMORY_COMPARE(tag_output, tag_len, tag->x, tag->len);
+
+        for (n1 = 0; n1 <= src_str->len; n1 += 1) {
+            for (n1_add = 0; n1_add <= add_str->len; n1_add += 1) {
+                mbedtls_test_set_step(n1 * 10000 + n1_add);
+                if (!check_multipart(&ctx, MBEDTLS_GCM_ENCRYPT,
+                                     iv_str, add_str, src_str,
+                                     dst, tag,
+                                     n1, n1_add)) {
+                    goto exit;
+                }
+            }
+        }
+    }
+
+exit:
+    if (buffer != NULL) {
+        free(buffer);
+    }
+    mbedtls_gcm_free(&ctx);
+    BLOCK_CIPHER_PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void gcm_decrypt_input_output_buffer_overlap(int cipher_id, data_t *key_str,
+                                             data_t *src_str, data_t *iv_str,
+                                             data_t *add_str, int tag_len_bits,
+                                             data_t *tag_str, char *result,
+                                             data_t *pt_result, int init_result)
+{
+    unsigned char *buffer = NULL;
+    size_t buffer_len;
+    mbedtls_gcm_context ctx;
+    int ret;
+    size_t tag_len = tag_len_bits / 8;
+    size_t n1;
+    size_t n1_add;
+
+    BLOCK_CIPHER_PSA_INIT();
+    mbedtls_gcm_init(&ctx);
+
+    /* GCM includes padding and therefore input length can be shorter than the output length
+     * Therefore we must ensure we round up to the nearest 128-bits/16-bytes.
+     */
+    buffer_len = src_str->len;
+    if (buffer_len % 16 != 0) {
+        buffer_len += (16 - (buffer_len % 16));
+    }
+    TEST_CALLOC(buffer, buffer_len);
+    if (buffer == NULL) {
+        TEST_FAIL("Could not allocate memory for input output buffer overlap");
+        goto exit;
+    }
+    memcpy(buffer, src_str->x, src_str->len);
+
+    TEST_ASSERT(mbedtls_gcm_setkey(&ctx, cipher_id, key_str->x, key_str->len * 8) == init_result);
+    if (init_result == 0) {
+        ret = mbedtls_gcm_auth_decrypt(&ctx,
+                                       src_str->len,
+                                       iv_str->x,
+                                       iv_str->len,
+                                       add_str->x,
+                                       add_str->len,
+                                       tag_str->x,
+                                       tag_len,
+                                       buffer,
+                                       buffer);
+
+        if (strcmp("FAIL", result) == 0) {
+            TEST_ASSERT(ret == MBEDTLS_ERR_GCM_AUTH_FAILED);
+        } else {
+            TEST_ASSERT(ret == 0);
+            TEST_MEMORY_COMPARE(buffer, src_str->len, pt_result->x, pt_result->len);
+
+            for (n1 = 0; n1 <= src_str->len; n1 += 1) {
+                for (n1_add = 0; n1_add <= add_str->len; n1_add += 1) {
+                    mbedtls_test_set_step(n1 * 10000 + n1_add);
+                    if (!check_multipart(&ctx, MBEDTLS_GCM_DECRYPT,
+                                         iv_str, add_str, src_str,
+                                         pt_result, tag_str,
+                                         n1, n1_add)) {
+                        goto exit;
+                    }
+                }
+            }
+        }
+    }
+
+exit:
+    if (buffer != NULL) {
+        free(buffer);
+    }
+    mbedtls_gcm_free(&ctx);
+    BLOCK_CIPHER_PSA_DONE();
+
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST:MBEDTLS_CCM_GCM_CAN_AES */
 void gcm_selftest()
 {