Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 2.28] Fix doc on GCM API #9774

Open
wants to merge 5 commits into
base: mbedtls-2.28
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions include/mbedtls/gcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,9 @@ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
/**
* \brief This function performs GCM encryption or decryption of a buffer.
*
* \note For encryption, the output buffer can be the same as the
* input buffer. For decryption, the output buffer cannot be
* the same as input buffer. If the buffers overlap, the output
* buffer must trail at least 8 Bytes behind the input buffer.
* \note The output buffer \p output can be the same as the input
* buffer \p input. If \p output is greater than \p input, they
* cannot overlap.
*
* \warning When this function performs a decryption, it outputs the
* authentication tag and does not verify that the data is
Expand Down Expand Up @@ -171,9 +170,11 @@ int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
* \brief This function performs a GCM authenticated decryption of a
* buffer.
*
* \note For decryption, the output buffer cannot be the same as
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
* \note The output buffer \p output can be the same as the input
* buffer \p input. If \p output is greater than \p input, they
* cannot overlap. Implementations which require
* MBEDTLS_GCM_ALT to be enabled may not provide support for
* overlapping buffers.
*
* \param ctx The GCM context. This must be initialized.
* \param length The length of the ciphertext to decrypt, which is also
Expand Down Expand Up @@ -243,9 +244,11 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
* Bytes. Only the last call before calling
* mbedtls_gcm_finish() can be less than 16 Bytes.
*
* \note For decryption, the output buffer cannot be the same as
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
* \note The output buffer \p output can be the same as the input
* buffer \p input. If \p output is greater than \p input, they
* cannot overlap. Implementations which require
* MBEDTLS_GCM_ALT to be enabled may not provide support for
* overlapping buffers.
*
* \param ctx The GCM context. This must be initialized.
* \param length The length of the input data. This must be a multiple of
Expand Down
673 changes: 673 additions & 0 deletions tests/suites/test_suite_gcm.aes128_de.data

Large diffs are not rendered by default.

673 changes: 673 additions & 0 deletions tests/suites/test_suite_gcm.aes128_en.data

Large diffs are not rendered by default.

673 changes: 673 additions & 0 deletions tests/suites/test_suite_gcm.aes192_de.data

Large diffs are not rendered by default.

672 changes: 672 additions & 0 deletions tests/suites/test_suite_gcm.aes192_en.data

Large diffs are not rendered by default.

672 changes: 672 additions & 0 deletions tests/suites/test_suite_gcm.aes256_de.data

Large diffs are not rendered by default.

672 changes: 672 additions & 0 deletions tests/suites/test_suite_gcm.aes256_en.data

Large diffs are not rendered by default.

216 changes: 216 additions & 0 deletions tests/suites/test_suite_gcm.camellia.data

Large diffs are not rendered by default.

100 changes: 100 additions & 0 deletions tests/suites/test_suite_gcm.function
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,103 @@ void gcm_selftest()
TEST_ASSERT(mbedtls_gcm_self_test(1) == 0);
}
/* 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;

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 == 0) {
buffer_len += (16 - (buffer_len % 16));
}
TEST_CALLOC(buffer, buffer_len);
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_ASSERT(mbedtls_test_hexcmp(buffer, dst->x,
src_str->len, dst->len) == 0);
TEST_ASSERT(mbedtls_test_hexcmp(tag_output, tag->x,
tag_len, tag->len) == 0);
}

exit:
mbedtls_free(buffer);
mbedtls_gcm_free(&ctx);
}
/* 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;

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 == 0) {
buffer_len += (16 - (buffer_len % 16));
}
TEST_CALLOC(buffer, buffer_len);
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_ASSERT(mbedtls_test_hexcmp(buffer, pt_result->x,
src_str->len,
pt_result->len) == 0);
}
}

exit:
mbedtls_free(buffer);
mbedtls_gcm_free(&ctx);
}
/* END_CASE */