Merge pull request #8733 from ivq/gcm_ad_len_check
Add back restriction on AD length of GCM
diff --git a/library/gcm.c b/library/gcm.c
index c677ca4..033cb59 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -354,9 +354,17 @@
{
const unsigned char *p;
size_t use_len, offset;
+ uint64_t new_add_len;
- /* IV is limited to 2^64 bits, so 2^61 bytes */
- if ((uint64_t) add_len >> 61 != 0) {
+ /* AD is limited to 2^64 bits, ie 2^61 bytes
+ * Also check for possible overflow */
+#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
+ if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
+ return MBEDTLS_ERR_GCM_BAD_INPUT;
+ }
+#endif
+ new_add_len = ctx->add_len + (uint64_t) add_len;
+ if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
return MBEDTLS_ERR_GCM_BAD_INPUT;
}
@@ -539,6 +547,9 @@
(void) output_size;
*output_length = 0;
+ /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
+ * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
+ * the two multiplications would overflow. */
orig_len = ctx->len * 8;
orig_add_len = ctx->add_len * 8;
diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function
index 599c926..8bb7b8b 100644
--- a/tests/suites/test_suite_gcm.function
+++ b/tests/suites/test_suite_gcm.function
@@ -153,6 +153,21 @@
mbedtls_free(output);
}
+static void gcm_reset_ctx(mbedtls_gcm_context *ctx, const uint8_t *key,
+ size_t key_bits, const uint8_t *iv, size_t iv_len,
+ int starts_ret)
+{
+ int mode = MBEDTLS_GCM_ENCRYPT;
+ mbedtls_cipher_id_t valid_cipher = MBEDTLS_CIPHER_ID_AES;
+
+ mbedtls_gcm_init(ctx);
+ TEST_EQUAL(mbedtls_gcm_setkey(ctx, valid_cipher, key, key_bits), 0);
+ TEST_EQUAL(starts_ret, mbedtls_gcm_starts(ctx, mode, iv, iv_len));
+exit:
+ /* empty */
+ return;
+}
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -478,6 +493,118 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+/* NISP SP 800-38D, Section 5.2.1.1 requires that bit length of IV should
+ * satisfy 1 <= bit_len(IV) <= 2^64 - 1. */
+void gcm_invalid_iv_len(void)
+{
+ mbedtls_gcm_context ctx;
+ mbedtls_gcm_init(&ctx);
+ uint8_t b16[16] = { 0 };
+
+ BLOCK_CIPHER_PSA_INIT();
+
+ // Invalid IV length 0
+ gcm_reset_ctx(&ctx, b16, sizeof(b16) * 8, b16, 0, MBEDTLS_ERR_GCM_BAD_INPUT);
+ mbedtls_gcm_free(&ctx);
+
+ // Only testable on platforms where sizeof(size_t) >= 8.
+#if SIZE_MAX >= UINT64_MAX
+ // Invalid IV length 2^61
+ gcm_reset_ctx(&ctx, b16, sizeof(b16) * 8, b16, 1ULL << 61, MBEDTLS_ERR_GCM_BAD_INPUT);
+ mbedtls_gcm_free(&ctx);
+#endif
+
+ goto exit; /* To suppress error that exit is defined but not used */
+exit:
+ mbedtls_gcm_free(&ctx);
+ BLOCK_CIPHER_PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void gcm_add_len_too_long(void)
+{
+ // Only testable on platforms where sizeof(size_t) >= 8.
+#if SIZE_MAX >= UINT64_MAX
+ mbedtls_gcm_context ctx;
+ mbedtls_gcm_init(&ctx);
+ uint8_t b16[16] = { 0 };
+ BLOCK_CIPHER_PSA_INIT();
+
+ /* NISP SP 800-38D, Section 5.2.1.1 requires that bit length of AD should
+ * be <= 2^64 - 1, ie < 2^64. This is the minimum invalid length in bytes. */
+ uint64_t len_max = 1ULL << 61;
+
+ gcm_reset_ctx(&ctx, b16, sizeof(b16) * 8, b16, sizeof(b16), 0);
+ // Feed AD that just exceeds the length limit
+ TEST_EQUAL(mbedtls_gcm_update_ad(&ctx, b16, len_max),
+ MBEDTLS_ERR_GCM_BAD_INPUT);
+ mbedtls_gcm_free(&ctx);
+
+ gcm_reset_ctx(&ctx, b16, sizeof(b16) * 8, b16, sizeof(b16), 0);
+ // Feed AD that just exceeds the length limit in two calls
+ TEST_EQUAL(mbedtls_gcm_update_ad(&ctx, b16, 1), 0);
+ TEST_EQUAL(mbedtls_gcm_update_ad(&ctx, b16, len_max - 1),
+ MBEDTLS_ERR_GCM_BAD_INPUT);
+ mbedtls_gcm_free(&ctx);
+
+ gcm_reset_ctx(&ctx, b16, sizeof(b16) * 8, b16, sizeof(b16), 0);
+ // Test if potential total AD length overflow is handled properly
+ TEST_EQUAL(mbedtls_gcm_update_ad(&ctx, b16, 1), 0);
+ TEST_EQUAL(mbedtls_gcm_update_ad(&ctx, b16, UINT64_MAX), MBEDTLS_ERR_GCM_BAD_INPUT);
+
+exit:
+ mbedtls_gcm_free(&ctx);
+ BLOCK_CIPHER_PSA_DONE();
+#endif
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void gcm_input_len_too_long(void)
+{
+ // Only testable on platforms where sizeof(size_t) >= 8
+#if SIZE_MAX >= UINT64_MAX
+ mbedtls_gcm_context ctx;
+ uint8_t b16[16] = { 0 };
+ uint8_t out[1];
+ size_t out_len;
+ mbedtls_gcm_init(&ctx);
+ BLOCK_CIPHER_PSA_INIT();
+
+ /* NISP SP 800-38D, Section 5.2.1.1 requires that bit length of input should
+ * be <= 2^39 - 256. This is the maximum valid length in bytes. */
+ uint64_t len_max = (1ULL << 36) - 32;
+
+ gcm_reset_ctx(&ctx, b16, sizeof(b16) * 8, b16, sizeof(b16), 0);
+ // Feed input that just exceeds the length limit
+ TEST_EQUAL(mbedtls_gcm_update(&ctx, b16, len_max + 1, out, len_max + 1,
+ &out_len),
+ MBEDTLS_ERR_GCM_BAD_INPUT);
+ mbedtls_gcm_free(&ctx);
+
+ gcm_reset_ctx(&ctx, b16, sizeof(b16) * 8, b16, sizeof(b16), 0);
+ // Feed input that just exceeds the length limit in two calls
+ TEST_EQUAL(mbedtls_gcm_update(&ctx, b16, 1, out, 1, &out_len), 0);
+ TEST_EQUAL(mbedtls_gcm_update(&ctx, b16, len_max, out, len_max, &out_len),
+ MBEDTLS_ERR_GCM_BAD_INPUT);
+ mbedtls_gcm_free(&ctx);
+
+ gcm_reset_ctx(&ctx, b16, sizeof(b16) * 8, b16, sizeof(b16), 0);
+ // Test if potential total input length overflow is handled properly
+ TEST_EQUAL(mbedtls_gcm_update(&ctx, b16, 1, out, 1, &out_len), 0);
+ TEST_EQUAL(mbedtls_gcm_update(&ctx, b16, UINT64_MAX, out, UINT64_MAX,
+ &out_len),
+ MBEDTLS_ERR_GCM_BAD_INPUT);
+
+exit:
+ mbedtls_gcm_free(&ctx);
+ BLOCK_CIPHER_PSA_DONE();
+#endif
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST:MBEDTLS_CCM_GCM_CAN_AES */
void gcm_selftest()
{
diff --git a/tests/suites/test_suite_gcm.misc.data b/tests/suites/test_suite_gcm.misc.data
index f22b7a3..108630e 100644
--- a/tests/suites/test_suite_gcm.misc.data
+++ b/tests/suites/test_suite_gcm.misc.data
@@ -1,2 +1,14 @@
GCM - Invalid parameters
gcm_invalid_param:
+
+GCM - Invalid IV length
+depends_on:MBEDTLS_GCM_C:MBEDTLS_CCM_GCM_CAN_AES
+gcm_invalid_iv_len:
+
+GCM - Additional data length too long
+depends_on:MBEDTLS_GCM_C:MBEDTLS_CCM_GCM_CAN_AES
+gcm_add_len_too_long:
+
+GCM - Input length too long
+depends_on:MBEDTLS_GCM_C:MBEDTLS_CCM_GCM_CAN_AES
+gcm_input_len_too_long: