From 1d8cf6117c0cb10875ebf1083a6cdc168a94d938 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sun, 14 Jun 2026 16:24:30 +0800 Subject: [PATCH] Update GHASH --- CMakeLists.txt | 2 +- include/gmssl/ghash.h | 9 ++++++++- include/gmssl/version.h | 2 +- src/ghash.c | 30 ++++++++++++++++++++---------- tests/ghashtest.c | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b5d31751..f0883907 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -763,7 +763,7 @@ endif() # set(CPACK_PACKAGE_NAME "GmSSL") set(CPACK_PACKAGE_VENDOR "GmSSL develop team") -set(CPACK_PACKAGE_VERSION "3.2.0-dev.1045") +set(CPACK_PACKAGE_VERSION "3.2.0-dev.1046") set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) set(CPACK_NSIS_MODIFY_PATH ON) include(CPack) diff --git a/include/gmssl/ghash.h b/include/gmssl/ghash.h index 73fbca86..4cf4b59d 100644 --- a/include/gmssl/ghash.h +++ b/include/gmssl/ghash.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2024 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2026 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -24,6 +24,13 @@ extern "C" { #define GHASH_SIZE (16) +/* + * GHASH encodes aadlen and clen as 64-bit bit lengths. + * Callers must ensure that each one-shot length, and the accumulated clen + * passed to ghash_update(), is no greater than UINT64_MAX/8 bytes. + * If aadlen or clen is non-zero, the corresponding input pointer must be + * non-NULL. + */ // h = ENC_k(0^128) void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, diff --git a/include/gmssl/version.h b/include/gmssl/version.h index 4a014613..7f58cf65 100644 --- a/include/gmssl/version.h +++ b/include/gmssl/version.h @@ -19,7 +19,7 @@ extern "C" { // Also update CPACK_PACKAGE_VERSION in CMakeLists.txt #define GMSSL_VERSION_NUM 30200 -#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1045" +#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1046" int gmssl_version_num(void); const char *gmssl_version_str(void); diff --git a/src/ghash.c b/src/ghash.c index f3d33558..e72ebebf 100644 --- a/src/ghash.c +++ b/src/ghash.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2024 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2026 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -36,13 +36,14 @@ void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, const uint8_t gf128_t H; gf128_t X; gf128_t L; + uint8_t block[16]; gf128_from_bytes(H, h); gf128_set_zero(X); - PUTU64(out, (uint64_t)aadlen << 3); - PUTU64(out + 8, (uint64_t)clen << 3); - gf128_from_bytes(L, out); + PUTU64(block, (uint64_t)aadlen << 3); + PUTU64(block + 8, (uint64_t)clen << 3); + gf128_from_bytes(L, block); while (aadlen) { gf128_t A; @@ -51,9 +52,9 @@ void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, const uint8_t aad += 16; aadlen -= 16; } else { - memset(out, 0, 16); - memcpy(out, aad, aadlen); - gf128_from_bytes(A, out); + memset(block, 0, 16); + memcpy(block, aad, aadlen); + gf128_from_bytes(A, block); aadlen = 0; } gf128_add(X, X, A); @@ -67,9 +68,9 @@ void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, const uint8_t c += 16; clen -= 16; } else { - memset(out, 0, 16); - memcpy(out, c, clen); - gf128_from_bytes(C, out); + memset(block, 0, 16); + memcpy(block, c, clen); + gf128_from_bytes(C, block); clen = 0; } gf128_add(X, X, C); @@ -79,6 +80,11 @@ void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, const uint8_t gf128_add(X, X, L); gf128_mul(H, X, H); // clear secrets in H gf128_to_bytes(H, out); + + gmssl_secure_clear(H, sizeof(H)); + gmssl_secure_clear(X, sizeof(X)); + gmssl_secure_clear(L, sizeof(L)); + gmssl_secure_clear(block, sizeof(block)); } void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen) @@ -113,6 +119,10 @@ void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen) assert(ctx->num < 16); + if (!clen) { + return; + } + ctx->clen += clen; if (ctx->num) { diff --git a/tests/ghashtest.c b/tests/ghashtest.c index 6c74e92f..8764e930 100644 --- a/tests/ghashtest.c +++ b/tests/ghashtest.c @@ -108,6 +108,7 @@ int test_ghash(void) format_print(stderr, 0, 2, "C = %s\n", ghash_tests[i].C); format_bytes(stderr, 0, 2, "GHASH(H,A,C) = ", out, 16); format_print(stderr, 0, 2, " = %s\n\n", ghash_tests[i].T); + return -1; } } @@ -115,6 +116,43 @@ int test_ghash(void) return 1; } +int test_ghash_update(void) +{ + uint8_t H[16]; + uint8_t A[32]; + uint8_t C[80]; + uint8_t C_alias[80]; + uint8_t T[16]; + uint8_t out[16]; + size_t Hlen, Alen, Clen, Tlen; + GHASH_CTX ghash_ctx; + + hex_to_bytes(ghash_tests[3].H, strlen(ghash_tests[3].H), H, &Hlen); + hex_to_bytes(ghash_tests[3].A, strlen(ghash_tests[3].A), A, &Alen); + hex_to_bytes(ghash_tests[3].C, strlen(ghash_tests[3].C), C, &Clen); + hex_to_bytes(ghash_tests[3].T, strlen(ghash_tests[3].T), T, &Tlen); + + ghash_init(&ghash_ctx, H, A, Alen); + ghash_update(&ghash_ctx, C, 7); + ghash_update(&ghash_ctx, NULL, 0); + ghash_update(&ghash_ctx, C + 7, Clen - 7); + ghash_finish(&ghash_ctx, out); + if (memcmp(out, T, Tlen) != 0) { + error_print(); + return -1; + } + + memcpy(C_alias, C, Clen); + ghash(H, A, Alen, C_alias, Clen, C_alias); + if (memcmp(C_alias, T, Tlen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + static int speed_ghash(void) { GHASH_CTX ghash_ctx; @@ -148,6 +186,7 @@ static int speed_ghash(void) int main(int argc, char **argv) { if (test_ghash() != 1) goto err; + if (test_ghash_update() != 1) goto err; #if ENABLE_TEST_SPEED speed_ghash();