From c12edeb7b1f2894b2ef93e435a89da78ab9974ec Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sat, 13 Jun 2026 22:14:56 +0800 Subject: [PATCH] Fix SM4 API bugs and change behavior --- CMakeLists.txt | 2 +- include/gmssl/sm4_cbc_mac.h | 8 +- include/gmssl/version.h | 2 +- src/sm4_cbc.c | 73 +++++++++------- src/sm4_cbc_mac.c | 35 +++++++- src/sm4_cbc_sm3_hmac.c | 14 ++- src/sm4_ccm.c | 18 ++-- src/sm4_cfb.c | 46 +++++----- src/sm4_ctr.c | 48 +++++------ src/sm4_ctr_sm3_hmac.c | 14 ++- src/sm4_ecb.c | 18 ++-- src/sm4_gcm.c | 66 ++++++++------ src/sm4_ofb.c | 23 +++-- src/sm4_xts.c | 67 ++++++++++++-- tests/sm4_cbc_mactest.c | 88 +++++++++++++++++-- tests/sm4_cbctest.c | 109 ++++++++++++++++++++++- tests/sm4_ccmtest.c | 140 ++++++++++++++++++++++++++++-- tests/sm4_cfbtest.c | 60 ++++++++++++- tests/sm4_ctrtest.c | 94 +++++++++++++++++++- tests/sm4_ecbtest.c | 53 +++++++++++- tests/sm4_gcmtest.c | 144 ++++++++++++++++++++++++++++++- tests/sm4_ofbtest.c | 38 +++++++- tests/sm4_sm3_hmactest.c | 132 +++++++++++++++++++++++++++- tests/sm4_xtstest.c | 168 +++++++++++++++++++++++++++++++++++- tools/sm4.c | 4 +- tools/sm4_cbc_mac.c | 16 +--- tools/sm4_cbc_sm3_hmac.c | 4 +- tools/sm4_ctr_sm3_hmac.c | 4 +- tools/sm4_xts.c | 5 +- 29 files changed, 1281 insertions(+), 212 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 39811567..ea8f1d15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -768,7 +768,7 @@ endif() # set(CPACK_PACKAGE_NAME "GmSSL") set(CPACK_PACKAGE_VENDOR "GmSSL develop team") -set(CPACK_PACKAGE_VERSION "3.2.0-dev.1034") +set(CPACK_PACKAGE_VERSION "3.2.0-dev.1035") set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) set(CPACK_NSIS_MODIFY_PATH ON) include(CPack) diff --git a/include/gmssl/sm4_cbc_mac.h b/include/gmssl/sm4_cbc_mac.h index 26deb18c..fdb5171f 100644 --- a/include/gmssl/sm4_cbc_mac.h +++ b/include/gmssl/sm4_cbc_mac.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2023 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. @@ -26,9 +26,9 @@ typedef struct { #define SM4_CBC_MAC_SIZE (SM4_BLOCK_SIZE) -void sm4_cbc_mac_init(SM4_CBC_MAC_CTX *ctx, const uint8_t key[16]); -void sm4_cbc_mac_update(SM4_CBC_MAC_CTX *ctx, const uint8_t *data, size_t datalen); -void sm4_cbc_mac_finish(SM4_CBC_MAC_CTX *ctx, uint8_t mac[16]); +int sm4_cbc_mac_init(SM4_CBC_MAC_CTX *ctx, const uint8_t key[16]); +int sm4_cbc_mac_update(SM4_CBC_MAC_CTX *ctx, const uint8_t *data, size_t datalen); +int sm4_cbc_mac_finish(SM4_CBC_MAC_CTX *ctx, uint8_t mac[16]); #ifdef __cplusplus diff --git a/include/gmssl/version.h b/include/gmssl/version.h index 83e984be..fe075b82 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.1034" +#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1035" int gmssl_version_num(void); const char *gmssl_version_str(void); diff --git a/src/sm4_cbc.c b/src/sm4_cbc.c index 96040361..ec282cca 100644 --- a/src/sm4_cbc.c +++ b/src/sm4_cbc.c @@ -22,6 +22,11 @@ int sm4_cbc_padding_encrypt(const SM4_KEY *key, const uint8_t piv[16], size_t rem = inlen % 16; int padding = 16 - inlen % 16; + if (!key || !piv || (!in && inlen) || !out || !outlen) { + error_print(); + return -1; + } + memcpy(iv, piv, 16); if (in) { @@ -35,6 +40,9 @@ int sm4_cbc_padding_encrypt(const SM4_KEY *key, const uint8_t piv[16], } sm4_cbc_encrypt_blocks(key, iv, block, 1, out); *outlen = inlen - rem + 16; + + gmssl_secure_clear(iv, sizeof(iv)); + gmssl_secure_clear(block, sizeof(block)); return 1; } @@ -48,37 +56,47 @@ int sm4_cbc_padding_decrypt(const SM4_KEY *key, const uint8_t piv[16], int padding; int i; - memcpy(iv, piv, 16); - - if (inlen == 0) { - error_puts("warning: input lenght = 0"); - return 0; - } - if (inlen%16 != 0 || inlen < 16) { - error_puts("invalid cbc ciphertext length"); + if (!key || !piv || !in || !inlen || !out || !outlen) { + error_print(); return -1; } - if (inlen > 16) { - sm4_cbc_decrypt_blocks(key, iv, in, inlen/16 - 1, out); + if (inlen % 16 != 0 || inlen < 16) { + error_print(); + return -1; } + if (inlen/16 > 1) + memcpy(iv, in + inlen - 32, 16); + else memcpy(iv, piv, 16); + sm4_cbc_decrypt_blocks(key, iv, in + inlen - 16, 1, block); + gmssl_secure_clear(iv, sizeof(iv)); padding = block[15]; if (padding < 1 || padding > 16) { + gmssl_secure_clear(block, sizeof(block)); error_print(); return -1; } for (i = 16 - padding; i < 16; i++) { if (block[i] != padding) { + gmssl_secure_clear(block, sizeof(block)); error_print(); return -1; } } + if (inlen/16 > 1) { + memcpy(iv, piv, 16); + sm4_cbc_decrypt_blocks(key, iv, in, inlen/16 - 1, out); + gmssl_secure_clear(iv, sizeof(iv)); + } + len -= padding; memcpy(out + inlen - 16, block, len); *outlen = inlen - padding; + + gmssl_secure_clear(block, sizeof(block)); return 1; } @@ -103,19 +121,19 @@ int sm4_cbc_encrypt_update(SM4_CBC_CTX *ctx, size_t nblocks; size_t len; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { left = SM4_BLOCK_SIZE - ctx->block_nbytes; if (inlen < left) { @@ -147,14 +165,10 @@ int sm4_cbc_encrypt_update(SM4_CBC_CTX *ctx, int sm4_cbc_encrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen) { - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; @@ -183,22 +197,23 @@ int sm4_cbc_decrypt_init(SM4_CBC_CTX *ctx, int sm4_cbc_decrypt_update(SM4_CBC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { - size_t left, len, nblocks; + size_t left; + size_t len; + size_t nblocks; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->block_nbytes > SM4_BLOCK_SIZE) { error_print(); return -1; } *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { left = SM4_BLOCK_SIZE - ctx->block_nbytes; if (inlen <= left) { @@ -228,14 +243,10 @@ int sm4_cbc_decrypt_update(SM4_CBC_CTX *ctx, int sm4_cbc_decrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen) { - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; - return 1; - } if (ctx->block_nbytes != SM4_BLOCK_SIZE) { error_print(); return -1; diff --git a/src/sm4_cbc_mac.c b/src/sm4_cbc_mac.c index e754f41f..7349810a 100644 --- a/src/sm4_cbc_mac.c +++ b/src/sm4_cbc_mac.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 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. @@ -17,15 +17,31 @@ #include -void sm4_cbc_mac_init(SM4_CBC_MAC_CTX *ctx, const uint8_t key[16]) +int sm4_cbc_mac_init(SM4_CBC_MAC_CTX *ctx, const uint8_t key[16]) { + if (!ctx || !key) { + error_print(); + return -1; + } sm4_set_encrypt_key(&ctx->key, key); memset(ctx->iv, 0, 16); ctx->ivlen = 0; + return 1; } -void sm4_cbc_mac_update(SM4_CBC_MAC_CTX *ctx, const uint8_t *data, size_t datalen) +int sm4_cbc_mac_update(SM4_CBC_MAC_CTX *ctx, const uint8_t *data, size_t datalen) { + if (!ctx || (!data && datalen)) { + error_print(); + return -1; + } + if (ctx->ivlen >= 16) { + error_print(); + return -1; + } + if (!data || !datalen) { + return 1; + } while (datalen) { size_t ivleft = 16 - ctx->ivlen; size_t len = datalen < ivleft ? datalen : ivleft; @@ -38,12 +54,23 @@ void sm4_cbc_mac_update(SM4_CBC_MAC_CTX *ctx, const uint8_t *data, size_t datale data += len; datalen -= len; } + return 1; } -void sm4_cbc_mac_finish(SM4_CBC_MAC_CTX *ctx, uint8_t mac[16]) +int sm4_cbc_mac_finish(SM4_CBC_MAC_CTX *ctx, uint8_t mac[16]) { + if (!ctx || !mac) { + error_print(); + return -1; + } + if (ctx->ivlen >= 16) { + error_print(); + return -1; + } if (ctx->ivlen) { sm4_encrypt(&ctx->key, ctx->iv, ctx->iv); + ctx->ivlen = 0; } memcpy(mac, ctx->iv, 16); + return 1; } diff --git a/src/sm4_cbc_sm3_hmac.c b/src/sm4_cbc_sm3_hmac.c index 33f0129e..75c5347c 100644 --- a/src/sm4_cbc_sm3_hmac.c +++ b/src/sm4_cbc_sm3_hmac.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. @@ -38,10 +38,14 @@ int sm4_cbc_sm3_hmac_encrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, int sm4_cbc_sm3_hmac_encrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { - if (!ctx || !in || !out || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (sm4_cbc_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { error_print(); return -1; @@ -90,7 +94,7 @@ int sm4_cbc_sm3_hmac_decrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, const uint8_t *in { size_t len; - if (!ctx || !in || !out || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } @@ -99,6 +103,10 @@ int sm4_cbc_sm3_hmac_decrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, const uint8_t *in return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->maclen < SM3_HMAC_SIZE) { len = SM3_HMAC_SIZE - ctx->maclen; if (inlen <= len) { diff --git a/src/sm4_ccm.c b/src/sm4_ccm.c index 91438367..554ad2c8 100644 --- a/src/sm4_ccm.c +++ b/src/sm4_ccm.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. @@ -8,10 +8,10 @@ */ -#include #include -#include #include +#include +#include static void length_to_bytes(size_t len, size_t nbytes, uint8_t *out) @@ -60,11 +60,11 @@ int sm4_ccm_encrypt(const SM4_KEY *sm4_key, const uint8_t *iv, size_t ivlen, uint8_t mac[16]; size_t inlen_size; - if (ivlen < 7 || ivlen > 13) { + if (!sm4_key || !iv || (!aad && aadlen) || (!in && inlen) || !out || !tag) { error_print(); return -1; } - if (!aad && aadlen) { + if (ivlen < 7 || ivlen > 13) { error_print(); return -1; } @@ -109,7 +109,7 @@ int sm4_ccm_encrypt(const SM4_KEY *sm4_key, const uint8_t *iv, size_t ivlen, } sm4_cbc_mac_update(&mac_ctx, block, alen); sm4_cbc_mac_update(&mac_ctx, aad, aadlen); - if (alen + aadlen % 16) { + if ((alen + aadlen) % 16) { sm4_cbc_mac_update(&mac_ctx, zeros, 16 - (alen + aadlen)%16); } } @@ -145,11 +145,11 @@ int sm4_ccm_decrypt(const SM4_KEY *sm4_key, const uint8_t *iv, size_t ivlen, uint8_t mac[16]; size_t inlen_size; - if (ivlen < 7 || ivlen > 13) { + if (!sm4_key || !iv || (!aad && aadlen) || (!in && inlen) || !tag || !out) { error_print(); return -1; } - if (!aad && aadlen) { + if (ivlen < 7 || ivlen > 13) { error_print(); return -1; } @@ -194,7 +194,7 @@ int sm4_ccm_decrypt(const SM4_KEY *sm4_key, const uint8_t *iv, size_t ivlen, } sm4_cbc_mac_update(&mac_ctx, block, alen); sm4_cbc_mac_update(&mac_ctx, aad, aadlen); - if (alen + aadlen % 16) { + if ((alen + aadlen) % 16) { sm4_cbc_mac_update(&mac_ctx, zeros, 16 - (alen + aadlen)%16); } } diff --git a/src/sm4_cfb.c b/src/sm4_cfb.c index 6340b640..eba8819a 100644 --- a/src/sm4_cfb.c +++ b/src/sm4_cfb.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. @@ -91,19 +91,19 @@ int sm4_cfb_encrypt_update(SM4_CFB_CTX *ctx, size_t nblocks; size_t len; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->block_nbytes >= ctx->sbytes) { error_print(); return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { left = ctx->sbytes - ctx->block_nbytes; if (inlen < left) { @@ -135,19 +135,17 @@ int sm4_cfb_encrypt_update(SM4_CFB_CTX *ctx, int sm4_cfb_encrypt_finish(SM4_CFB_CTX *ctx, uint8_t *out, size_t *outlen) { - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; - return 1; - } if (ctx->block_nbytes >= ctx->sbytes) { error_print(); return -1; } - sm4_cfb_encrypt(&ctx->sm4_key, ctx->sbytes, ctx->iv, ctx->block, ctx->block_nbytes, out); + if (ctx->block_nbytes) { + sm4_cfb_encrypt(&ctx->sm4_key, ctx->sbytes, ctx->iv, ctx->block, ctx->block_nbytes, out); + } *outlen = ctx->block_nbytes; return 1; } @@ -178,22 +176,20 @@ int sm4_cfb_decrypt_update(SM4_CFB_CTX *ctx, size_t nblocks; size_t len; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->block_nbytes >= ctx->sbytes) { error_print(); return -1; } - *outlen = 0; - if (ctx->block_nbytes) { - error_print(); + *outlen = 0; + if (!in || !inlen) { + return 1; + } + if (ctx->block_nbytes) { left = ctx->sbytes - ctx->block_nbytes; if (inlen < left) { memcpy(ctx->block + ctx->block_nbytes, in, inlen); @@ -224,19 +220,17 @@ int sm4_cfb_decrypt_update(SM4_CFB_CTX *ctx, int sm4_cfb_decrypt_finish(SM4_CFB_CTX *ctx, uint8_t *out, size_t *outlen) { - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; - return 1; - } if (ctx->block_nbytes >= ctx->sbytes) { error_print(); return -1; } - sm4_cfb_decrypt(&ctx->sm4_key, ctx->sbytes, ctx->iv, ctx->block, ctx->block_nbytes, out); + if (ctx->block_nbytes) { + sm4_cfb_decrypt(&ctx->sm4_key, ctx->sbytes, ctx->iv, ctx->block, ctx->block_nbytes, out); + } *outlen = ctx->block_nbytes; return 1; } diff --git a/src/sm4_ctr.c b/src/sm4_ctr.c index e0a0f9fa..a43b9d44 100644 --- a/src/sm4_ctr.c +++ b/src/sm4_ctr.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. @@ -70,19 +70,19 @@ int sm4_ctr_encrypt_update(SM4_CTR_CTX *ctx, size_t nblocks; size_t len; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { left = SM4_BLOCK_SIZE - ctx->block_nbytes; if (inlen < left) { @@ -114,20 +114,19 @@ int sm4_ctr_encrypt_update(SM4_CTR_CTX *ctx, int sm4_ctr_encrypt_finish(SM4_CTR_CTX *ctx, uint8_t *out, size_t *outlen) { - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; } - sm4_ctr_encrypt_blocks(&ctx->sm4_key, ctx->ctr, ctx->block, 1, ctx->block); - memcpy(out, ctx->block, ctx->block_nbytes); + + if (ctx->block_nbytes) { + sm4_ctr_encrypt_blocks(&ctx->sm4_key, ctx->ctr, ctx->block, 1, ctx->block); + memcpy(out, ctx->block, ctx->block_nbytes); + } *outlen = ctx->block_nbytes; return 1; } @@ -153,19 +152,19 @@ int sm4_ctr32_encrypt_update(SM4_CTR_CTX *ctx, size_t nblocks; size_t len; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { left = SM4_BLOCK_SIZE - ctx->block_nbytes; if (inlen < left) { @@ -197,20 +196,19 @@ int sm4_ctr32_encrypt_update(SM4_CTR_CTX *ctx, int sm4_ctr32_encrypt_finish(SM4_CTR_CTX *ctx, uint8_t *out, size_t *outlen) { - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; } - sm4_ctr32_encrypt_blocks(&ctx->sm4_key, ctx->ctr, ctx->block, 1, ctx->block); - memcpy(out, ctx->block, ctx->block_nbytes); + + if (ctx->block_nbytes) { + sm4_ctr32_encrypt_blocks(&ctx->sm4_key, ctx->ctr, ctx->block, 1, ctx->block); + memcpy(out, ctx->block, ctx->block_nbytes); + } *outlen = ctx->block_nbytes; return 1; } diff --git a/src/sm4_ctr_sm3_hmac.c b/src/sm4_ctr_sm3_hmac.c index a1a1fe7a..fcbeac77 100644 --- a/src/sm4_ctr_sm3_hmac.c +++ b/src/sm4_ctr_sm3_hmac.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. @@ -38,10 +38,14 @@ int sm4_ctr_sm3_hmac_encrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, int sm4_ctr_sm3_hmac_encrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { - if (!ctx || !in || !out || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (sm4_ctr_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { error_print(); return -1; @@ -90,7 +94,7 @@ int sm4_ctr_sm3_hmac_decrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, const uint8_t *in { size_t len; - if (!ctx || !in || !out || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } @@ -99,6 +103,10 @@ int sm4_ctr_sm3_hmac_decrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, const uint8_t *in return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->maclen < SM3_HMAC_SIZE) { len = SM3_HMAC_SIZE - ctx->maclen; if (inlen <= len) { diff --git a/src/sm4_ecb.c b/src/sm4_ecb.c index 8762a4bc..72f15a7f 100644 --- a/src/sm4_ecb.c +++ b/src/sm4_ecb.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. @@ -32,19 +32,19 @@ int sm4_ecb_encrypt_update(SM4_ECB_CTX *ctx, size_t nblocks; size_t len; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { left = SM4_BLOCK_SIZE - ctx->block_nbytes; if (inlen < left) { @@ -76,14 +76,10 @@ int sm4_ecb_encrypt_update(SM4_ECB_CTX *ctx, int sm4_ecb_encrypt_finish(SM4_ECB_CTX *ctx, uint8_t *out, size_t *outlen) { - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; // anyway, caller should prepare a block buffer to support any length input - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; diff --git a/src/sm4_gcm.c b/src/sm4_gcm.c index 9dcf0843..6064fe46 100644 --- a/src/sm4_gcm.c +++ b/src/sm4_gcm.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. @@ -34,6 +34,10 @@ int sm4_gcm_encrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, uint8_t Y[16]; uint8_t T[16]; + if (!key || !iv || (!aad && aadlen) || (!in && inlen) || !out || !tag) { + error_print(); + return -1; + } if (ivlen < SM4_GCM_MIN_IV_SIZE || ivlen > SM4_GCM_MAX_IV_SIZE) { error_print(); return -1; @@ -76,6 +80,10 @@ int sm4_gcm_decrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, uint8_t Y[16]; uint8_t T[16]; + if (!key || !iv || (!aad && aadlen) || (!in && inlen) || !tag || !out) { + error_print(); + return -1; + } if (ivlen < SM4_GCM_MIN_IV_SIZE || ivlen > SM4_GCM_MAX_IV_SIZE) { error_print(); return -1; @@ -170,22 +178,24 @@ int sm4_gcm_encrypt_init(SM4_GCM_CTX *ctx, int sm4_gcm_encrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } + + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (inlen > INT_MAX) { error_print(); return -1; } - if (inlen > SM4_GCM_MAX_PLAINTEXT_SIZE - ctx->encedlen) { + if (ctx->encedlen > SM4_GCM_MAX_PLAINTEXT_SIZE + || inlen > SM4_GCM_MAX_PLAINTEXT_SIZE - ctx->encedlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (sm4_ctr32_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { error_print(); @@ -202,14 +212,10 @@ int sm4_gcm_encrypt_finish(SM4_GCM_CTX *ctx, uint8_t *out, size_t *outlen) { uint8_t mac[16]; - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE * 2; // GCM output extra mac tag - return 1; - } if (sm4_ctr32_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { error_print(); return -1; @@ -234,28 +240,36 @@ int sm4_gcm_decrypt_init(SM4_GCM_CTX *ctx, int sm4_gcm_decrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { size_t len; + size_t datalen = 0; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } + + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (inlen > INT_MAX) { error_print(); return -1; } - if (inlen > SM4_GCM_MAX_PLAINTEXT_SIZE - ctx->encedlen) { - error_print(); - return -1; - } - - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->maclen > ctx->taglen) { error_print(); return -1; } + if (ctx->encedlen > SM4_GCM_MAX_PLAINTEXT_SIZE) { + error_print(); + return -1; + } + if (inlen > ctx->taglen - ctx->maclen) { + datalen = inlen - (ctx->taglen - ctx->maclen); + if (datalen > SM4_GCM_MAX_PLAINTEXT_SIZE - ctx->encedlen) { + error_print(); + return -1; + } + } if (ctx->maclen < ctx->taglen) { len = ctx->taglen - ctx->maclen; @@ -300,7 +314,7 @@ int sm4_gcm_decrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, ui memcpy(ctx->mac, in + inlen, GHASH_SIZE); } - ctx->encedlen += inlen; + ctx->encedlen += datalen; return 1; } @@ -308,14 +322,10 @@ int sm4_gcm_decrypt_finish(SM4_GCM_CTX *ctx, uint8_t *out, size_t *outlen) { uint8_t mac[GHASH_SIZE]; - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; - return 1; - } if (ctx->maclen != ctx->taglen) { error_print(); return -1; diff --git a/src/sm4_ofb.c b/src/sm4_ofb.c index c483fd0e..73561275 100644 --- a/src/sm4_ofb.c +++ b/src/sm4_ofb.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. @@ -49,19 +49,19 @@ int sm4_ofb_encrypt_update(SM4_OFB_CTX *ctx, size_t nblocks; size_t len; - if (!ctx || !in || !outlen) { + if (!ctx || (!in && inlen) || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = 16 * ((inlen + 15)/16); - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; } + *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { left = SM4_BLOCK_SIZE - ctx->block_nbytes; if (inlen < left) { @@ -93,20 +93,17 @@ int sm4_ofb_encrypt_update(SM4_OFB_CTX *ctx, int sm4_ofb_encrypt_finish(SM4_OFB_CTX *ctx, uint8_t *out, size_t *outlen) { - if (!ctx || !outlen) { + if (!ctx || !out || !outlen) { error_print(); return -1; } - if (!out) { - *outlen = SM4_BLOCK_SIZE; - return 1; - } if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { error_print(); return -1; } - sm4_ofb_encrypt(&ctx->sm4_key, ctx->iv, ctx->block, ctx->block_nbytes, out); + if (ctx->block_nbytes) { + sm4_ofb_encrypt(&ctx->sm4_key, ctx->iv, ctx->block, ctx->block_nbytes, out); + } *outlen = ctx->block_nbytes; return 1; } - diff --git a/src/sm4_xts.c b/src/sm4_xts.c index ca884a37..dc0f9afe 100644 --- a/src/sm4_xts.c +++ b/src/sm4_xts.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. @@ -22,6 +22,10 @@ int sm4_xts_encrypt(const SM4_KEY *key1, const SM4_KEY *key2, const uint8_t twea size_t nblocks, i; gf128_t a; + if (!key1 || !key2 || !tweak || (!in && inlen) || !out) { + error_print(); + return -1; + } if (inlen < 16) { error_print(); return -1; @@ -83,6 +87,10 @@ int sm4_xts_decrypt(const SM4_KEY *key1, const SM4_KEY *key2, const uint8_t twea size_t nblocks, i; gf128_t a; + if (!key1 || !key2 || !tweak || (!in && inlen) || !out) { + error_print(); + return -1; + } if (inlen < 16) { error_print(); return -1; @@ -149,10 +157,11 @@ static void tweak_incr(uint8_t a[16]) int sm4_xts_encrypt_init(SM4_XTS_CTX *ctx, const uint8_t key[32], const uint8_t iv[16], size_t data_unit_size) { - if (data_unit_size < SM4_BLOCK_SIZE) { + if (!ctx || !key || !iv || data_unit_size < SM4_BLOCK_SIZE) { error_print(); return -1; } + memset(ctx, 0, sizeof(*ctx)); sm4_set_encrypt_key(&ctx->key1, key); sm4_set_encrypt_key(&ctx->key2, key + 16); memcpy(ctx->tweak, iv, 16); @@ -168,14 +177,26 @@ int sm4_xts_encrypt_init(SM4_XTS_CTX *ctx, const uint8_t key[32], const uint8_t int sm4_xts_encrypt_update(SM4_XTS_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { - size_t DATA_UNIT_SIZE = ctx->data_unit_size; + size_t DATA_UNIT_SIZE; size_t left; + if (!ctx || (!in && inlen) || !out || !outlen) { + error_print(); + return -1; + } + if (!ctx->block || ctx->data_unit_size < SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + DATA_UNIT_SIZE = ctx->data_unit_size; if (ctx->block_nbytes >= DATA_UNIT_SIZE) { error_print(); return -1; } *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { left = DATA_UNIT_SIZE - ctx->block_nbytes; if (inlen < left) { @@ -214,7 +235,16 @@ int sm4_xts_encrypt_update(SM4_XTS_CTX *ctx, int sm4_xts_encrypt_finish(SM4_XTS_CTX *ctx, uint8_t *out, size_t *outlen) { - size_t DATA_UNIT_SIZE = ctx->data_unit_size; + size_t DATA_UNIT_SIZE; + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (!ctx->block || ctx->data_unit_size < SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + DATA_UNIT_SIZE = ctx->data_unit_size; if (ctx->block_nbytes >= DATA_UNIT_SIZE) { error_print(); return -1; @@ -234,10 +264,11 @@ int sm4_xts_encrypt_finish(SM4_XTS_CTX *ctx, uint8_t *out, size_t *outlen) int sm4_xts_decrypt_init(SM4_XTS_CTX *ctx, const uint8_t key[32], const uint8_t iv[16], size_t data_unit_size) { - if (data_unit_size < SM4_BLOCK_SIZE) { + if (!ctx || !key || !iv || data_unit_size < SM4_BLOCK_SIZE) { error_print(); return -1; } + memset(ctx, 0, sizeof(*ctx)); sm4_set_decrypt_key(&ctx->key1, key); sm4_set_encrypt_key(&ctx->key2, key + 16); memcpy(ctx->tweak, iv, 16); @@ -253,16 +284,27 @@ int sm4_xts_decrypt_init(SM4_XTS_CTX *ctx, const uint8_t key[32], const uint8_t int sm4_xts_decrypt_update(SM4_XTS_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { - size_t DATA_UNIT_SIZE = ctx->data_unit_size; + size_t DATA_UNIT_SIZE; size_t left; + if (!ctx || (!in && inlen) || !out || !outlen) { + error_print(); + return -1; + } + if (!ctx->block || ctx->data_unit_size < SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + DATA_UNIT_SIZE = ctx->data_unit_size; if (ctx->block_nbytes >= DATA_UNIT_SIZE) { error_print(); return -1; } *outlen = 0; + if (!in || !inlen) { + return 1; + } if (ctx->block_nbytes) { - error_print(); left = DATA_UNIT_SIZE - ctx->block_nbytes; if (inlen < left) { memcpy(ctx->block + ctx->block_nbytes, in, inlen); @@ -300,7 +342,16 @@ int sm4_xts_decrypt_update(SM4_XTS_CTX *ctx, int sm4_xts_decrypt_finish(SM4_XTS_CTX *ctx, uint8_t *out, size_t *outlen) { - size_t DATA_UNIT_SIZE = ctx->data_unit_size; + size_t DATA_UNIT_SIZE; + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (!ctx->block || ctx->data_unit_size < SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + DATA_UNIT_SIZE = ctx->data_unit_size; if (ctx->block_nbytes >= DATA_UNIT_SIZE) { error_print(); return -1; diff --git a/tests/sm4_cbc_mactest.c b/tests/sm4_cbc_mactest.c index e9e258cd..23753a44 100644 --- a/tests/sm4_cbc_mactest.c +++ b/tests/sm4_cbc_mactest.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 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. @@ -39,18 +39,27 @@ static int test_sm4_cbc_mac(void) sm4_cbc_encrypt_blocks(&sm4_key, iv, m, sizeof(m)/16, c); memcpy(mac1, c + sizeof(m) - 16, 16); - sm4_cbc_mac_init(&ctx, key); + if (sm4_cbc_mac_init(&ctx, key) != 1) { + error_print(); + return -1; + } p = m; len = 0; left = sizeof(m); while (left) { len = left < len ? left : len; - sm4_cbc_mac_update(&ctx, p, len); + if (sm4_cbc_mac_update(&ctx, p, len) != 1) { + error_print(); + return -1; + } p += len; left -= len; len++; } - sm4_cbc_mac_finish(&ctx, mac2); + if (sm4_cbc_mac_finish(&ctx, mac2) != 1) { + error_print(); + return -1; + } if (memcmp(mac1, mac2, 16)) { error_print(); return -1; @@ -62,18 +71,27 @@ static int test_sm4_cbc_mac(void) sm4_cbc_encrypt_blocks(&sm4_key, iv, m, sizeof(m)/16, c); memcpy(mac1, c + sizeof(m) - 16, 16); - sm4_cbc_mac_init(&ctx, key); + if (sm4_cbc_mac_init(&ctx, key) != 1) { + error_print(); + return -1; + } p = m; len = 0; left = sizeof(m) - 1; while (left) { len = left < len ? left : len; - sm4_cbc_mac_update(&ctx, p, len); + if (sm4_cbc_mac_update(&ctx, p, len) != 1) { + error_print(); + return -1; + } p += len; left -= len; len++; } - sm4_cbc_mac_finish(&ctx, mac2); + if (sm4_cbc_mac_finish(&ctx, mac2) != 1) { + error_print(); + return -1; + } if (memcmp(mac1, mac2, 16)) { error_print(); return -1; @@ -83,8 +101,64 @@ static int test_sm4_cbc_mac(void) return 1; } +static int test_sm4_cbc_mac_args(void) +{ + SM4_CBC_MAC_CTX ctx; + uint8_t key[16] = {0}; + uint8_t data[16] = {0}; + uint8_t mac[16]; + + if (sm4_cbc_mac_init(NULL, key) != -1 + || sm4_cbc_mac_init(&ctx, NULL) != -1) { + error_print(); + return -1; + } + if (sm4_cbc_mac_init(&ctx, key) != 1 + || sm4_cbc_mac_update(NULL, data, sizeof(data)) != -1 + || sm4_cbc_mac_update(&ctx, NULL, sizeof(data)) != -1 + || sm4_cbc_mac_update(&ctx, NULL, 0) != 1 + || sm4_cbc_mac_finish(NULL, mac) != -1 + || sm4_cbc_mac_finish(&ctx, NULL) != -1) { + error_print(); + return -1; + } + + ctx.ivlen = 16; + if (sm4_cbc_mac_update(&ctx, data, sizeof(data)) != -1 + || sm4_cbc_mac_finish(&ctx, mac) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_cbc_mac_finish_repeat(void) +{ + SM4_CBC_MAC_CTX ctx; + uint8_t key[16] = {0}; + uint8_t data[15] = {0}; + uint8_t mac1[16]; + uint8_t mac2[16]; + + if (sm4_cbc_mac_init(&ctx, key) != 1 + || sm4_cbc_mac_update(&ctx, data, sizeof(data)) != 1 + || sm4_cbc_mac_finish(&ctx, mac1) != 1 + || sm4_cbc_mac_finish(&ctx, mac2) != 1 + || memcmp(mac1, mac2, sizeof(mac1)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + int main(void) { if (test_sm4_cbc_mac() != 1) { error_print(); return -1; } + if (test_sm4_cbc_mac_args() != 1) { error_print(); return -1; } + if (test_sm4_cbc_mac_finish_repeat() != 1) { error_print(); return -1; } return 0; } diff --git a/tests/sm4_cbctest.c b/tests/sm4_cbctest.c index 57725bdb..8bc53d7c 100644 --- a/tests/sm4_cbctest.c +++ b/tests/sm4_cbctest.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. @@ -209,6 +209,98 @@ static int test_sm4_cbc_padding(void) return 1; } +static int test_sm4_cbc_args(void) +{ + SM4_KEY enc_key; + SM4_KEY dec_key; + SM4_CBC_CTX ctx; + uint8_t key[16] = {0}; + uint8_t iv[16] = {0}; + uint8_t in[16] = {0}; + uint8_t out[32]; + size_t outlen; + + sm4_set_encrypt_key(&enc_key, key); + sm4_set_decrypt_key(&dec_key, key); + + if (sm4_cbc_padding_encrypt(NULL, iv, in, sizeof(in), out, &outlen) != -1 + || sm4_cbc_padding_encrypt(&enc_key, NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_cbc_padding_encrypt(&enc_key, iv, NULL, 1, out, &outlen) != -1 + || sm4_cbc_padding_encrypt(&enc_key, iv, in, sizeof(in), NULL, &outlen) != -1 + || sm4_cbc_padding_encrypt(&enc_key, iv, in, sizeof(in), out, NULL) != -1) { + error_print(); + return -1; + } + + outlen = 0; + if (sm4_cbc_padding_encrypt(&enc_key, iv, NULL, 0, out, &outlen) != 1 + || outlen != SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + + if (sm4_cbc_padding_encrypt(&enc_key, iv, in, sizeof(in), out, &outlen) != 1 + || outlen != 2 * SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + out[outlen - 1] ^= 1; + memset(in, 0xa5, sizeof(in)); + if (sm4_cbc_padding_decrypt(&dec_key, iv, out, outlen, in, &outlen) == 1) { + error_print(); + return -1; + } + for (outlen = 0; outlen < sizeof(in); outlen++) { + if (in[outlen] != 0xa5) { + error_print(); + return -1; + } + } + + outlen = 0; + if (sm4_cbc_padding_encrypt(&enc_key, iv, NULL, 0, out, &outlen) != 1 + || outlen != SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + + if (sm4_cbc_padding_decrypt(NULL, iv, out, outlen, in, &outlen) != -1 + || sm4_cbc_padding_decrypt(&dec_key, NULL, out, outlen, in, &outlen) != -1 + || sm4_cbc_padding_decrypt(&dec_key, iv, NULL, 1, in, &outlen) != -1 + || sm4_cbc_padding_decrypt(&dec_key, iv, out, outlen, NULL, &outlen) != -1 + || sm4_cbc_padding_decrypt(&dec_key, iv, out, outlen, in, NULL) != -1) { + error_print(); + return -1; + } + + outlen = 123; + if (sm4_cbc_padding_decrypt(&dec_key, iv, NULL, 0, in, &outlen) != -1) { + error_print(); + return -1; + } + + if (sm4_cbc_encrypt_init(&ctx, key, iv) != 1 + || sm4_cbc_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_cbc_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_cbc_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1) { + error_print(); + return -1; + } + + if (sm4_cbc_decrypt_init(&ctx, key, iv) != 1 + || sm4_cbc_decrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_cbc_decrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_cbc_decrypt_update(&ctx, NULL, 1, out, &outlen) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + static int test_sm4_cbc_padding_openssl(void) { size_t i; @@ -342,6 +434,20 @@ static int test_sm4_cbc_ctx(void) return -1; } + // check in-place decrypt + memcpy(pbuf, cbuf, clen); + if (sm4_cbc_decrypt_init(&dec_ctx, key, iv) != 1 + || sm4_cbc_decrypt_update(&dec_ctx, pbuf, clen, pbuf, &plen) != 1 + || sm4_cbc_decrypt_finish(&dec_ctx, pbuf + plen, &len) != 1) { + error_print(); + return -1; + } + plen += len; + if (plen != mlen || memcmp(pbuf, mbuf, mlen) != 0) { + error_print(); + return -1; + } + // second test @@ -423,6 +529,7 @@ int main(void) if (test_sm4_cbc() != 1) goto err; if (test_sm4_cbc_test_vectors() != 1) goto err; if (test_sm4_cbc_padding() != 1) goto err; + if (test_sm4_cbc_args() != 1) goto err; if (test_sm4_cbc_padding_openssl() != 1) goto err; if (test_sm4_cbc_ctx() != 1) goto err; printf("%s all tests passed\n", __FILE__); diff --git a/tests/sm4_ccmtest.c b/tests/sm4_ccmtest.c index 9b0d5d31..cf2152dd 100644 --- a/tests/sm4_ccmtest.c +++ b/tests/sm4_ccmtest.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. @@ -79,13 +79,22 @@ static int test_sm4_ccm_test_vectors(void) char *ciphertext; } tests[] = { { - "rfc8998", - "0123456789abcdeffedcba9876543210", - "00001234567800000000abcd", - "feedfacedeadbeeffeedfacedeadbeefabaddad2", - "16842d4fa186f56ab33256971fa110f4", - "aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddeeeeeeeeeeeeeeeeffffffffffffffffeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaa", - "48af93501fa62adbcd414cce6034d895dda1bf8f132f042098661572e7483094fd12e518ce062c98acee28d95df4416bed31a2f04476c18bb40c84a74b97dc5b", + "rfc8998", + "0123456789abcdeffedcba9876543210", + "00001234567800000000abcd", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "16842d4fa186f56ab33256971fa110f4", + "aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddeeeeeeeeeeeeeeeeffffffffffffffffeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaa", + "48af93501fa62adbcd414cce6034d895dda1bf8f132f042098661572e7483094fd12e518ce062c98acee28d95df4416bed31a2f04476c18bb40c84a74b97dc5b", + }, + { + "openssl-sm4-ccm-aad-padding-boundary", + "0123456789abcdeffedcba9876543210", + "000102030405060708090a0b", + "101112131415161718191a1b1c1d", + "7290e28b5fa29391036f06a0", + "202122232425262728292a2b2c2d2e", + "374bfae945b38c4082d62a0b4304a0", }, }; @@ -177,6 +186,66 @@ static int test_sm4_ccm_test_vectors(void) } +static int test_sm4_ccm_aad_padding_bug(void) +{ + const char *hex_key = "0123456789abcdeffedcba9876543210"; + const char *hex_iv = "000102030405060708090a0b"; + const char *hex_aad = "101112131415161718191a1b1c1d"; + const char *hex_msg = "202122232425262728292a2b2c2d2e"; + const char *hex_ct = "374bfae945b38c4082d62a0b4304a0"; + const char *hex_tag = "7290e28b5fa29391036f06a0"; + SM4_KEY sm4_key; + uint8_t key[16]; + uint8_t iv[16]; + uint8_t aad[16]; + uint8_t msg[16]; + uint8_t ct[16]; + uint8_t tag[16]; + uint8_t out[16]; + uint8_t dec[16]; + uint8_t mac[16]; + size_t keylen, ivlen, aadlen, msglen, ctlen, taglen; + + if (hex_to_bytes(hex_key, strlen(hex_key), key, &keylen) != 1 + || hex_to_bytes(hex_iv, strlen(hex_iv), iv, &ivlen) != 1 + || hex_to_bytes(hex_aad, strlen(hex_aad), aad, &aadlen) != 1 + || hex_to_bytes(hex_msg, strlen(hex_msg), msg, &msglen) != 1 + || hex_to_bytes(hex_ct, strlen(hex_ct), ct, &ctlen) != 1 + || hex_to_bytes(hex_tag, strlen(hex_tag), tag, &taglen) != 1) { + error_print(); + return -1; + } + /* + * Regression for `alen + aadlen % 16`. + * Short AAD uses alen = 2. Here aadlen = 14, so + * `(alen + aadlen) % 16` is 0 and no zero padding block is added. + */ + if (aadlen != 14 || (2 + aadlen) % 16 != 0) { + error_print(); + return -1; + } + + sm4_set_encrypt_key(&sm4_key, key); + if (sm4_ccm_encrypt(&sm4_key, iv, ivlen, aad, aadlen, + msg, msglen, out, taglen, mac) != 1 + || ctlen != msglen + || memcmp(out, ct, ctlen) != 0 + || memcmp(mac, tag, taglen) != 0) { + error_print(); + return -1; + } + if (sm4_ccm_decrypt(&sm4_key, iv, ivlen, aad, aadlen, + ct, ctlen, tag, taglen, dec) != 1 + || memcmp(dec, msg, msglen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + static int test_sm4_ccm_wycheproof(void) { size_t i; @@ -242,6 +311,59 @@ static int test_sm4_ccm_wycheproof(void) return 1; } +static int test_sm4_ccm_args(void) +{ + SM4_KEY sm4_key; + uint8_t key[16] = {0}; + uint8_t iv[12] = {0}; + uint8_t aad[16] = {0}; + uint8_t in[16] = {0}; + uint8_t out[16]; + uint8_t dec[16]; + uint8_t tag[16]; + + sm4_set_encrypt_key(&sm4_key, key); + + if (sm4_ccm_encrypt(&sm4_key, iv, sizeof(iv), NULL, 0, NULL, 0, out, 16, tag) != 1 + || sm4_ccm_decrypt(&sm4_key, iv, sizeof(iv), NULL, 0, NULL, 0, tag, 16, dec) != 1) { + error_print(); + return -1; + } + + if (sm4_ccm_encrypt(NULL, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, 16, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, NULL, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, 16, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, 6, aad, sizeof(aad), in, sizeof(in), out, 16, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, 14, aad, sizeof(aad), in, sizeof(in), out, 16, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, sizeof(iv), NULL, 1, in, sizeof(in), out, 16, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), NULL, 1, out, 16, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), NULL, 16, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, 16, NULL) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, 3, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, 17, tag) != -1 + || sm4_ccm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, 5, tag) != -1) { + error_print(); + return -1; + } + + if (sm4_ccm_decrypt(NULL, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, 16, out) != -1 + || sm4_ccm_decrypt(&sm4_key, NULL, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, 16, out) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, 6, aad, sizeof(aad), in, sizeof(in), tag, 16, out) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, 14, aad, sizeof(aad), in, sizeof(in), tag, 16, out) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, sizeof(iv), NULL, 1, in, sizeof(in), tag, 16, out) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), NULL, 1, tag, 16, out) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), NULL, 16, out) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, 16, NULL) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, 3, out) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, 17, out) != -1 + || sm4_ccm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, 5, out) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + static int speed_sm4_ccm_encrypt(void) { SM4_KEY sm4_key; @@ -275,7 +397,9 @@ int main(void) { if (test_sm4_ccm() != 1) goto err; if (test_sm4_ccm_test_vectors() != 1) goto err; + if (test_sm4_ccm_aad_padding_bug() != 1) goto err; if (test_sm4_ccm_wycheproof() != 1) goto err; + if (test_sm4_ccm_args() != 1) goto err; #if ENABLE_TEST_SPEED if (speed_sm4_ccm_encrypt() != 1) goto err; #endif diff --git a/tests/sm4_cfbtest.c b/tests/sm4_cfbtest.c index acd48110..419cd13d 100644 --- a/tests/sm4_cfbtest.c +++ b/tests/sm4_cfbtest.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. @@ -260,11 +260,69 @@ static int test_sm4_cfb_ctx(void) return 1; } +static int test_sm4_cfb_args(void) +{ + SM4_CFB_CTX ctx; + uint8_t key[16] = {0}; + uint8_t iv[16] = {0}; + uint8_t in[16] = {0}; + uint8_t out[16]; + size_t outlen; + + if (sm4_cfb_encrypt_init(NULL, SM4_CFB_128, key, iv) != -1 + || sm4_cfb_encrypt_init(&ctx, 0, key, iv) != -1 + || sm4_cfb_encrypt_init(&ctx, SM4_BLOCK_SIZE + 1, key, iv) != -1 + || sm4_cfb_encrypt_init(&ctx, SM4_CFB_128, NULL, iv) != -1 + || sm4_cfb_encrypt_init(&ctx, SM4_CFB_128, key, NULL) != -1 + || sm4_cfb_decrypt_init(NULL, SM4_CFB_128, key, iv) != -1 + || sm4_cfb_decrypt_init(&ctx, 0, key, iv) != -1 + || sm4_cfb_decrypt_init(&ctx, SM4_BLOCK_SIZE + 1, key, iv) != -1 + || sm4_cfb_decrypt_init(&ctx, SM4_CFB_128, NULL, iv) != -1 + || sm4_cfb_decrypt_init(&ctx, SM4_CFB_128, key, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_cfb_encrypt_init(&ctx, SM4_CFB_128, key, iv) != 1 + || sm4_cfb_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_cfb_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_cfb_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_cfb_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_cfb_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_cfb_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_cfb_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_cfb_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_cfb_encrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_cfb_decrypt_init(&ctx, SM4_CFB_128, key, iv) != 1 + || sm4_cfb_decrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_cfb_decrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_cfb_decrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_cfb_decrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_cfb_decrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_cfb_decrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_cfb_decrypt_finish(NULL, out, &outlen) != -1 + || sm4_cfb_decrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_cfb_decrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + int main(void) { if (test_sm4_cfb() != 1) goto err; if (test_sm4_cfb_test_vectors() != 1) goto err; if (test_sm4_cfb_ctx() != 1) goto err; + if (test_sm4_cfb_args() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; err: diff --git a/tests/sm4_ctrtest.c b/tests/sm4_ctrtest.c index 7f21ffea..05a474ee 100644 --- a/tests/sm4_ctrtest.c +++ b/tests/sm4_ctrtest.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. @@ -425,6 +425,96 @@ static int test_sm4_ctr_ctx_multi_updates(void) return 1; } +static int test_sm4_ctr_args(void) +{ + SM4_CTR_CTX ctx; + uint8_t key[16] = {0}; + uint8_t ctr[16] = {0}; + uint8_t in[16] = {0}; + uint8_t out[16]; + size_t outlen; + + if (sm4_ctr_encrypt_init(NULL, key, ctr) != -1 + || sm4_ctr_encrypt_init(&ctx, NULL, ctr) != -1 + || sm4_ctr_encrypt_init(&ctx, key, NULL) != -1 + || sm4_ctr32_encrypt_init(NULL, key, ctr) != -1 + || sm4_ctr32_encrypt_init(&ctx, NULL, ctr) != -1 + || sm4_ctr32_encrypt_init(&ctx, key, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_ctr_encrypt_init(&ctx, key, ctr) != 1 + || sm4_ctr_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_ctr_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_ctr_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_ctr_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_ctr_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_ctr_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_ctr_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_ctr_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_ctr_encrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_ctr32_encrypt_init(&ctx, key, ctr) != 1 + || sm4_ctr32_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_ctr32_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_ctr32_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_ctr32_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_ctr32_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_ctr32_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_ctr32_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_ctr32_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_ctr32_encrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_ctr_finish_no_extra_counter(void) +{ + SM4_CTR_CTX ctx; + uint8_t key[16] = {0}; + uint8_t ctr[16] = {0}; + uint8_t in[16] = {0}; + uint8_t out[16]; + uint8_t expected_ctr[16]; + size_t outlen; + + memcpy(expected_ctr, ctr, sizeof(expected_ctr)); + expected_ctr[15]++; + + if (sm4_ctr_encrypt_init(&ctx, key, ctr) != 1 + || sm4_ctr_encrypt_update(&ctx, in, sizeof(in), out, &outlen) != 1 + || outlen != sizeof(in) + || sm4_ctr_encrypt_finish(&ctx, out, &outlen) != 1 + || outlen != 0 + || memcmp(ctx.ctr, expected_ctr, sizeof(expected_ctr)) != 0) { + error_print(); + return -1; + } + + if (sm4_ctr32_encrypt_init(&ctx, key, ctr) != 1 + || sm4_ctr32_encrypt_update(&ctx, in, sizeof(in), out, &outlen) != 1 + || outlen != sizeof(in) + || sm4_ctr32_encrypt_finish(&ctx, out, &outlen) != 1 + || outlen != 0 + || memcmp(ctx.ctr, expected_ctr, sizeof(expected_ctr)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + int main(void) { if (test_sm4_ctr() != 1) goto err; @@ -433,6 +523,8 @@ int main(void) if (test_sm4_ctr_iv_overflow() != 1) goto err; if (test_sm4_ctr_ctx() != 1) goto err; if (test_sm4_ctr_ctx_multi_updates() != 1) goto err; + if (test_sm4_ctr_args() != 1) goto err; + if (test_sm4_ctr_finish_no_extra_counter() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; err: diff --git a/tests/sm4_ecbtest.c b/tests/sm4_ecbtest.c index e7b8d3c4..4406fe49 100644 --- a/tests/sm4_ecbtest.c +++ b/tests/sm4_ecbtest.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. @@ -180,11 +180,62 @@ static int test_sm4_ecb_ctx(void) return 1; } +static int test_sm4_ecb_args(void) +{ + SM4_ECB_CTX ctx; + uint8_t key[16] = {0}; + uint8_t in[16] = {0}; + uint8_t out[16]; + size_t outlen; + + if (sm4_ecb_encrypt_init(NULL, key) != -1 + || sm4_ecb_encrypt_init(&ctx, NULL) != -1 + || sm4_ecb_decrypt_init(NULL, key) != -1 + || sm4_ecb_decrypt_init(&ctx, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_ecb_encrypt_init(&ctx, key) != 1 + || sm4_ecb_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_ecb_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_ecb_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_ecb_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_ecb_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_ecb_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_ecb_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_ecb_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_ecb_encrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_ecb_decrypt_init(&ctx, key) != 1 + || sm4_ecb_decrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_ecb_decrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_ecb_decrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_ecb_decrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_ecb_decrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_ecb_decrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_ecb_decrypt_finish(NULL, out, &outlen) != -1 + || sm4_ecb_decrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_ecb_decrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + int main(void) { if (test_sm4_ecb() != 1) goto err; if (test_sm4_ecb_test_vectors() != 1) goto err; if (test_sm4_ecb_ctx() != 1) goto err; + if (test_sm4_ecb_args() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; err: diff --git a/tests/sm4_gcmtest.c b/tests/sm4_gcmtest.c index f3fbf121..cfbac6b3 100644 --- a/tests/sm4_gcmtest.c +++ b/tests/sm4_gcmtest.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 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. @@ -314,6 +314,146 @@ static int test_sm4_gcm_ctx(void) return 1; } +static int test_sm4_gcm_args(void) +{ + SM4_KEY sm4_key; + SM4_GCM_CTX ctx; + uint8_t key[16] = {0}; + uint8_t iv[12] = {0}; + uint8_t aad[16] = {0}; + uint8_t in[16] = {0}; + uint8_t out[64]; + uint8_t tag[16]; + size_t outlen; + + sm4_set_encrypt_key(&sm4_key, key); + + if (sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), NULL, 0, NULL, 0, out, sizeof(tag), tag) != 1 + || sm4_gcm_decrypt(&sm4_key, iv, sizeof(iv), NULL, 0, NULL, 0, tag, sizeof(tag), out) != 1) { + error_print(); + return -1; + } + + if (sm4_gcm_encrypt(NULL, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, sizeof(tag), tag) != -1 + || sm4_gcm_encrypt(&sm4_key, NULL, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, sizeof(tag), tag) != -1 + || sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), NULL, sizeof(aad), in, sizeof(in), out, sizeof(tag), tag) != -1 + || sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), NULL, sizeof(in), out, sizeof(tag), tag) != -1 + || sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), NULL, sizeof(tag), tag) != -1 + || sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, sizeof(tag), NULL) != -1 + || sm4_gcm_encrypt(&sm4_key, iv, 0, aad, sizeof(aad), in, sizeof(in), out, sizeof(tag), tag) != -1 + || sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, SM4_GCM_MIN_TAG_SIZE - 1, tag) != -1 + || sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, SM4_GCM_MAX_TAG_SIZE + 1, tag) != -1) { + error_print(); + return -1; + } + + if (sm4_gcm_decrypt(NULL, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, sizeof(tag), out) != -1 + || sm4_gcm_decrypt(&sm4_key, NULL, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, sizeof(tag), out) != -1 + || sm4_gcm_decrypt(&sm4_key, iv, sizeof(iv), NULL, sizeof(aad), in, sizeof(in), tag, sizeof(tag), out) != -1 + || sm4_gcm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), NULL, sizeof(in), tag, sizeof(tag), out) != -1 + || sm4_gcm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), NULL, sizeof(tag), out) != -1 + || sm4_gcm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, sizeof(tag), NULL) != -1 + || sm4_gcm_decrypt(&sm4_key, iv, 0, aad, sizeof(aad), in, sizeof(in), tag, sizeof(tag), out) != -1 + || sm4_gcm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, SM4_GCM_MIN_TAG_SIZE - 1, out) != -1 + || sm4_gcm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), tag, SM4_GCM_MAX_TAG_SIZE + 1, out) != -1) { + error_print(); + return -1; + } + + if (sm4_gcm_encrypt_init(NULL, key, sizeof(key), iv, sizeof(iv), NULL, 0, sizeof(tag)) != -1 + || sm4_gcm_encrypt_init(&ctx, NULL, sizeof(key), iv, sizeof(iv), NULL, 0, sizeof(tag)) != -1 + || sm4_gcm_encrypt_init(&ctx, key, sizeof(key), NULL, sizeof(iv), NULL, 0, sizeof(tag)) != -1 + || sm4_gcm_encrypt_init(&ctx, key, sizeof(key), iv, sizeof(iv), NULL, 1, sizeof(tag)) != -1 + || sm4_gcm_encrypt_init(&ctx, key, sizeof(key) - 1, iv, sizeof(iv), NULL, 0, sizeof(tag)) != -1 + || sm4_gcm_encrypt_init(&ctx, key, sizeof(key), iv, 0, NULL, 0, sizeof(tag)) != -1 + || sm4_gcm_encrypt_init(&ctx, key, sizeof(key), iv, sizeof(iv), NULL, 0, SM4_GCM_MIN_TAG_SIZE - 1) != -1 + || sm4_gcm_encrypt_init(&ctx, key, sizeof(key), iv, sizeof(iv), NULL, 0, SM4_GCM_MAX_TAG_SIZE + 1) != -1) { + error_print(); + return -1; + } + + if (sm4_gcm_encrypt_init(&ctx, key, sizeof(key), iv, sizeof(iv), NULL, 0, sizeof(tag)) != 1 + || sm4_gcm_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_gcm_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_gcm_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_gcm_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_gcm_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_gcm_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_gcm_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_gcm_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_gcm_encrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_gcm_decrypt_init(&ctx, key, sizeof(key), iv, sizeof(iv), NULL, 0, sizeof(tag)) != 1 + || sm4_gcm_decrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_gcm_decrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_gcm_decrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_gcm_decrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_gcm_decrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_gcm_decrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_gcm_decrypt_finish(NULL, out, &outlen) != -1 + || sm4_gcm_decrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_gcm_decrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_gcm_decrypt_encedlen_bug_vector(void) +{ + SM4_GCM_CTX ctx; + const char *hex_key = "00000000000000000000000000000000"; + const char *hex_iv = "000000000000000000000000"; + const char *hex_cipher = + "57c880553b3a32a8322c11cb95c147a3" + "af411d0d1bd4d64302520d5045e9215c" + "dfe541de43b9feb02b9f71be2b1aef91" + "d6149e9615aa16680e4c172cc72e5930"; + const char *hex_tag = "52be9a13d8a91889cf2aa124efee91f5"; + uint8_t key[16]; + uint8_t iv[12]; + uint8_t cipher[64]; + uint8_t tag[16]; + uint8_t in[80]; + uint8_t plain[64]; + uint8_t out[80]; + size_t len, keylen, ivlen, cipherlen, taglen, outlen, finlen; + + hex_to_bytes(hex_key, strlen(hex_key), key, &keylen); + hex_to_bytes(hex_iv, strlen(hex_iv), iv, &ivlen); + hex_to_bytes(hex_cipher, strlen(hex_cipher), cipher, &cipherlen); + hex_to_bytes(hex_tag, strlen(hex_tag), tag, &taglen); + memset(plain, 0x2a, sizeof(plain)); + memcpy(in, cipher, cipherlen); + memcpy(in + cipherlen, tag, taglen); + len = cipherlen + taglen; + + if (keylen != sizeof(key) + || ivlen != sizeof(iv) + || cipherlen != sizeof(plain) + || taglen != SM4_GCM_MAX_TAG_SIZE + || sm4_gcm_decrypt_init(&ctx, key, keylen, iv, ivlen, NULL, 0, taglen) != 1 + || sm4_gcm_decrypt_update(&ctx, in, len, out, &outlen) != 1 + || outlen != sizeof(plain) + || memcmp(out, plain, sizeof(plain)) != 0 + || ctx.encedlen != sizeof(plain) + || sm4_gcm_decrypt_finish(&ctx, out + outlen, &finlen) != 1 + || finlen != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + static int test_sm4_gcm_has_flag(const TEST_SM4_GCM_VECTOR *tv, const char *flag) { @@ -424,6 +564,8 @@ int main(void) if (test_sm4_gcm_gbt36624_1() != 1) goto err; if (test_sm4_gcm_gbt36624_2() != 1) goto err; if (test_sm4_gcm_ctx() != 1) goto err; + if (test_sm4_gcm_args() != 1) goto err; + if (test_sm4_gcm_decrypt_encedlen_bug_vector() != 1) goto err; if (test_sm4_gcm_wycheproof() != 1) goto err; #if ENABLE_TEST_SPEED if (speed_sm4_gcm_encrypt() != 1) goto err; diff --git a/tests/sm4_ofbtest.c b/tests/sm4_ofbtest.c index 4e1e5417..deb04130 100644 --- a/tests/sm4_ofbtest.c +++ b/tests/sm4_ofbtest.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. @@ -246,11 +246,47 @@ static int test_sm4_ofb_ctx(void) return 1; } +static int test_sm4_ofb_args(void) +{ + SM4_OFB_CTX ctx; + uint8_t key[16] = {0}; + uint8_t iv[16] = {0}; + uint8_t in[16] = {0}; + uint8_t out[16]; + size_t outlen; + + if (sm4_ofb_encrypt_init(NULL, key, iv) != -1 + || sm4_ofb_encrypt_init(&ctx, NULL, iv) != -1 + || sm4_ofb_encrypt_init(&ctx, key, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_ofb_encrypt_init(&ctx, key, iv) != 1 + || sm4_ofb_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_ofb_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_ofb_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_ofb_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_ofb_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_ofb_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_ofb_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_ofb_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_ofb_encrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + int main(void) { if (test_sm4_ofb() != 1) goto err; if (test_sm4_ofb_test_vectors() != 1) goto err; if (test_sm4_ofb_ctx() != 1) goto err; + if (test_sm4_ofb_args() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; err: diff --git a/tests/sm4_sm3_hmactest.c b/tests/sm4_sm3_hmactest.c index cfe4cd24..bf9d8ef9 100644 --- a/tests/sm4_sm3_hmactest.c +++ b/tests/sm4_sm3_hmactest.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. @@ -260,10 +260,140 @@ static int test_sm4_ctr_sm3_hmac(void) return 1; } +static int test_sm4_cbc_sm3_hmac_args(void) +{ + SM4_CBC_SM3_HMAC_CTX ctx; + uint8_t key[SM4_CBC_SM3_HMAC_KEY_SIZE] = {0}; + uint8_t iv[SM4_CBC_SM3_HMAC_IV_SIZE] = {0}; + uint8_t aad[16] = {0}; + uint8_t in[64] = {0}; + uint8_t out[128]; + size_t outlen; + + if (sm4_cbc_sm3_hmac_encrypt_init(NULL, key, iv, NULL, 0) != -1 + || sm4_cbc_sm3_hmac_encrypt_init(&ctx, NULL, iv, NULL, 0) != -1 + || sm4_cbc_sm3_hmac_encrypt_init(&ctx, key, NULL, NULL, 0) != -1 + || sm4_cbc_sm3_hmac_encrypt_init(&ctx, key, iv, NULL, sizeof(aad)) != -1 + || sm4_cbc_sm3_hmac_decrypt_init(NULL, key, iv, NULL, 0) != -1 + || sm4_cbc_sm3_hmac_decrypt_init(&ctx, NULL, iv, NULL, 0) != -1 + || sm4_cbc_sm3_hmac_decrypt_init(&ctx, key, NULL, NULL, 0) != -1 + || sm4_cbc_sm3_hmac_decrypt_init(&ctx, key, iv, NULL, sizeof(aad)) != -1) { + error_print(); + return -1; + } + + if (sm4_cbc_sm3_hmac_encrypt_init(&ctx, key, iv, NULL, 0) != 1 + || sm4_cbc_sm3_hmac_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_cbc_sm3_hmac_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_cbc_sm3_hmac_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_cbc_sm3_hmac_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_cbc_sm3_hmac_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_cbc_sm3_hmac_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_cbc_sm3_hmac_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_cbc_sm3_hmac_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_cbc_sm3_hmac_encrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_cbc_sm3_hmac_decrypt_init(&ctx, key, iv, NULL, 0) != 1 + || sm4_cbc_sm3_hmac_decrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_cbc_sm3_hmac_decrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_cbc_sm3_hmac_decrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_cbc_sm3_hmac_decrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_cbc_sm3_hmac_decrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_cbc_sm3_hmac_decrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_cbc_sm3_hmac_decrypt_finish(NULL, out, &outlen) != -1 + || sm4_cbc_sm3_hmac_decrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_cbc_sm3_hmac_decrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + outlen = 123; + if (sm4_cbc_sm3_hmac_decrypt_init(&ctx, key, iv, NULL, 0) != 1 + || sm4_cbc_sm3_hmac_decrypt_update(&ctx, in, 1, out, &outlen) != 1 + || outlen != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_ctr_sm3_hmac_args(void) +{ + SM4_CTR_SM3_HMAC_CTX ctx; + uint8_t key[SM4_CTR_SM3_HMAC_KEY_SIZE] = {0}; + uint8_t iv[SM4_CTR_SM3_HMAC_IV_SIZE] = {0}; + uint8_t aad[16] = {0}; + uint8_t in[64] = {0}; + uint8_t out[128]; + size_t outlen; + + if (sm4_ctr_sm3_hmac_encrypt_init(NULL, key, iv, NULL, 0) != -1 + || sm4_ctr_sm3_hmac_encrypt_init(&ctx, NULL, iv, NULL, 0) != -1 + || sm4_ctr_sm3_hmac_encrypt_init(&ctx, key, NULL, NULL, 0) != -1 + || sm4_ctr_sm3_hmac_encrypt_init(&ctx, key, iv, NULL, sizeof(aad)) != -1 + || sm4_ctr_sm3_hmac_decrypt_init(NULL, key, iv, NULL, 0) != -1 + || sm4_ctr_sm3_hmac_decrypt_init(&ctx, NULL, iv, NULL, 0) != -1 + || sm4_ctr_sm3_hmac_decrypt_init(&ctx, key, NULL, NULL, 0) != -1 + || sm4_ctr_sm3_hmac_decrypt_init(&ctx, key, iv, NULL, sizeof(aad)) != -1) { + error_print(); + return -1; + } + + if (sm4_ctr_sm3_hmac_encrypt_init(&ctx, key, iv, NULL, 0) != 1 + || sm4_ctr_sm3_hmac_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_ctr_sm3_hmac_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_ctr_sm3_hmac_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_ctr_sm3_hmac_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_ctr_sm3_hmac_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_ctr_sm3_hmac_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_ctr_sm3_hmac_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_ctr_sm3_hmac_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_ctr_sm3_hmac_encrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + if (sm4_ctr_sm3_hmac_decrypt_init(&ctx, key, iv, NULL, 0) != 1 + || sm4_ctr_sm3_hmac_decrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_ctr_sm3_hmac_decrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_ctr_sm3_hmac_decrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_ctr_sm3_hmac_decrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_ctr_sm3_hmac_decrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_ctr_sm3_hmac_decrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_ctr_sm3_hmac_decrypt_finish(NULL, out, &outlen) != -1 + || sm4_ctr_sm3_hmac_decrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_ctr_sm3_hmac_decrypt_finish(&ctx, out, NULL) != -1) { + error_print(); + return -1; + } + + outlen = 123; + if (sm4_ctr_sm3_hmac_decrypt_init(&ctx, key, iv, NULL, 0) != 1 + || sm4_ctr_sm3_hmac_decrypt_update(&ctx, in, 1, out, &outlen) != 1 + || outlen != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + int main(void) { if (test_sm4_cbc_sm3_hmac() != 1) goto err; if (test_sm4_ctr_sm3_hmac() != 1) goto err; + if (test_sm4_cbc_sm3_hmac_args() != 1) goto err; + if (test_sm4_ctr_sm3_hmac_args() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; err: diff --git a/tests/sm4_xtstest.c b/tests/sm4_xtstest.c index 2b84e322..b9c3baa7 100644 --- a/tests/sm4_xtstest.c +++ b/tests/sm4_xtstest.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. @@ -163,10 +163,176 @@ static int test_sm4_xts_test_vectors(void) return 1; } +static int test_sm4_xts_ctx(void) +{ + SM4_XTS_CTX ctx; + uint8_t key[32]; + uint8_t iv[16]; + uint8_t plaintext[64]; + uint8_t ciphertext[64]; + uint8_t decrypted[64]; + size_t outlen, total; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(plaintext, sizeof(plaintext)); + + if (sm4_xts_encrypt_init(&ctx, key, iv, 32) != 1 + || sm4_xts_encrypt_update(&ctx, plaintext, 7, ciphertext, &outlen) != 1 + || outlen != 0 + || sm4_xts_encrypt_update(&ctx, NULL, 0, ciphertext, &outlen) != 1 + || outlen != 0 + || sm4_xts_encrypt_update(&ctx, plaintext + 7, 25, ciphertext, &outlen) != 1 + || outlen != 32) { + error_print(); + return -1; + } + total = outlen; + if (sm4_xts_encrypt_update(&ctx, plaintext + 32, 32, ciphertext + total, &outlen) != 1 + || outlen != 32) { + error_print(); + return -1; + } + total += outlen; + if (sm4_xts_encrypt_finish(&ctx, ciphertext + total, &outlen) != 1 + || outlen != 0 + || total != sizeof(plaintext)) { + error_print(); + return -1; + } + + if (sm4_xts_decrypt_init(&ctx, key, iv, 32) != 1 + || sm4_xts_decrypt_update(&ctx, ciphertext, 5, decrypted, &outlen) != 1 + || outlen != 0 + || sm4_xts_decrypt_update(&ctx, NULL, 0, decrypted, &outlen) != 1 + || outlen != 0 + || sm4_xts_decrypt_update(&ctx, ciphertext + 5, 27, decrypted, &outlen) != 1 + || outlen != 32) { + error_print(); + return -1; + } + total = outlen; + if (sm4_xts_decrypt_update(&ctx, ciphertext + 32, 32, decrypted + total, &outlen) != 1 + || outlen != 32) { + error_print(); + return -1; + } + total += outlen; + if (sm4_xts_decrypt_finish(&ctx, decrypted + total, &outlen) != 1 + || outlen != 0 + || total != sizeof(plaintext) + || memcmp(decrypted, plaintext, sizeof(plaintext)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_xts_args(void) +{ + SM4_KEY key1; + SM4_KEY key2; + SM4_XTS_CTX ctx; + uint8_t key[32] = {0}; + uint8_t tweak[16] = {0}; + uint8_t in[32] = {0}; + uint8_t out[32]; + size_t outlen; + + sm4_set_encrypt_key(&key1, key); + sm4_set_encrypt_key(&key2, key + 16); + + if (sm4_xts_encrypt(NULL, &key2, tweak, in, sizeof(in), out) != -1 + || sm4_xts_encrypt(&key1, NULL, tweak, in, sizeof(in), out) != -1 + || sm4_xts_encrypt(&key1, &key2, NULL, in, sizeof(in), out) != -1 + || sm4_xts_encrypt(&key1, &key2, tweak, NULL, sizeof(in), out) != -1 + || sm4_xts_encrypt(&key1, &key2, tweak, in, sizeof(in), NULL) != -1 + || sm4_xts_encrypt(&key1, &key2, tweak, NULL, 0, out) != -1 + || sm4_xts_encrypt(&key1, &key2, tweak, in, SM4_BLOCK_SIZE - 1, out) != -1) { + error_print(); + return -1; + } + + sm4_set_decrypt_key(&key1, key); + if (sm4_xts_decrypt(NULL, &key2, tweak, in, sizeof(in), out) != -1 + || sm4_xts_decrypt(&key1, NULL, tweak, in, sizeof(in), out) != -1 + || sm4_xts_decrypt(&key1, &key2, NULL, in, sizeof(in), out) != -1 + || sm4_xts_decrypt(&key1, &key2, tweak, NULL, sizeof(in), out) != -1 + || sm4_xts_decrypt(&key1, &key2, tweak, in, sizeof(in), NULL) != -1 + || sm4_xts_decrypt(&key1, &key2, tweak, NULL, 0, out) != -1 + || sm4_xts_decrypt(&key1, &key2, tweak, in, SM4_BLOCK_SIZE - 1, out) != -1) { + error_print(); + return -1; + } + + if (sm4_xts_encrypt_init(NULL, key, tweak, 32) != -1 + || sm4_xts_encrypt_init(&ctx, NULL, tweak, 32) != -1 + || sm4_xts_encrypt_init(&ctx, key, NULL, 32) != -1 + || sm4_xts_encrypt_init(&ctx, key, tweak, SM4_BLOCK_SIZE - 1) != -1) { + error_print(); + return -1; + } + if (sm4_xts_encrypt_init(&ctx, key, tweak, 32) != 1 + || sm4_xts_encrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_xts_encrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_xts_encrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_xts_encrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_xts_encrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_xts_encrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_xts_encrypt_finish(NULL, out, &outlen) != -1 + || sm4_xts_encrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_xts_encrypt_finish(&ctx, out, NULL) != -1 + || sm4_xts_encrypt_finish(&ctx, out, &outlen) != 1 + || outlen != 0) { + error_print(); + return -1; + } + + if (sm4_xts_decrypt_init(NULL, key, tweak, 32) != -1 + || sm4_xts_decrypt_init(&ctx, NULL, tweak, 32) != -1 + || sm4_xts_decrypt_init(&ctx, key, NULL, 32) != -1 + || sm4_xts_decrypt_init(&ctx, key, tweak, SM4_BLOCK_SIZE - 1) != -1) { + error_print(); + return -1; + } + if (sm4_xts_decrypt_init(&ctx, key, tweak, 32) != 1 + || sm4_xts_decrypt_update(NULL, in, sizeof(in), out, &outlen) != -1 + || sm4_xts_decrypt_update(&ctx, NULL, 1, out, &outlen) != -1 + || sm4_xts_decrypt_update(&ctx, in, sizeof(in), NULL, &outlen) != -1 + || sm4_xts_decrypt_update(&ctx, in, sizeof(in), out, NULL) != -1 + || sm4_xts_decrypt_update(&ctx, NULL, 0, out, &outlen) != 1 + || outlen != 0 + || sm4_xts_decrypt_update(&ctx, NULL, 0, NULL, &outlen) != -1 + || sm4_xts_decrypt_finish(NULL, out, &outlen) != -1 + || sm4_xts_decrypt_finish(&ctx, NULL, &outlen) != -1 + || sm4_xts_decrypt_finish(&ctx, out, NULL) != -1 + || sm4_xts_decrypt_finish(&ctx, out, &outlen) != 1 + || outlen != 0) { + error_print(); + return -1; + } + + if (sm4_xts_encrypt_init(&ctx, key, tweak, 32) != 1 + || sm4_xts_encrypt_update(&ctx, in, 16, out, &outlen) != 1 + || outlen != 0 + || sm4_xts_encrypt_finish(&ctx, out, &outlen) != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + int main(void) { if (test_sm4_xts() != 1) goto err; if (test_sm4_xts_test_vectors() != 1) goto err; + if (test_sm4_xts_ctx() != 1) goto err; + if (test_sm4_xts_args() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; err: diff --git a/tools/sm4.c b/tools/sm4.c index 46daf11e..989dd6aa 100755 --- a/tools/sm4.c +++ b/tools/sm4.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2023 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. @@ -686,7 +686,7 @@ bad: case SM4_MODE_OFB: rv = sm4_ofb_encrypt_update(&sm4_ctx.ofb, inbuf, inlen, outbuf, &outlen); break; #endif #ifdef ENABLE_SM4_XTS - case SM4_MODE_XTS: rv = sm4_xts_encrypt_update(&sm4_ctx.xts, inbuf, inlen, outbuf, &outlen); break; + case SM4_MODE_XTS: rv = sm4_xts_decrypt_update(&sm4_ctx.xts, inbuf, inlen, outbuf, &outlen); break; #endif case SM4_MODE_GCM: rv = sm4_gcm_decrypt_update(&sm4_ctx.gcm, inbuf, inlen, outbuf, &outlen); break; case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_decrypt_update(&sm4_ctx.cbc_sm3_hmac, inbuf, inlen, outbuf, &outlen); break; diff --git a/tools/sm4_cbc_mac.c b/tools/sm4_cbc_mac.c index b1c350d2..005f0551 100644 --- a/tools/sm4_cbc_mac.c +++ b/tools/sm4_cbc_mac.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2023 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. @@ -84,7 +84,7 @@ int sm4_cbc_mac_main(int argc, char **argv) } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; keyhex = *(++argv); - if (strlen(keyhex) > sizeof(key) * 2) { + if (strlen(keyhex) != sizeof(key) * 2) { fprintf(stderr, "gmssl %s: key should be 16 bytes\n", prog); goto end; } @@ -142,43 +142,31 @@ bad: goto end; } - sm4_cbc_mac_init(&ctx, key); - /* if (sm4_cbc_mac_init(&ctx, key) != 1) { fprintf(stderr, "gmssl %s: inner error\n", prog); goto end; } - */ if (in_str) { - sm4_cbc_mac_update(&ctx, (uint8_t *)in_str, strlen(in_str)); - /* if (sm4_cbc_mac_update(&ctx, (uint8_t *)in_str, strlen(in_str)) != 1) { fprintf(stderr, "gmssl %s: inner error\n", prog); goto end; } - */ } else { uint8_t buf[4096]; size_t len; while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { - sm4_cbc_mac_update(&ctx, buf, len); - /* if (sm4_cbc_mac_update(&ctx, buf, len) != 1) { fprintf(stderr, "gmssl %s: inner error\n", prog); goto end; } - */ } memset(buf, 0, sizeof(buf)); } - sm4_cbc_mac_finish(&ctx, mac); - /* if (sm4_cbc_mac_finish(&ctx, mac) != 1) { fprintf(stderr, "gmssl %s: inner error\n", prog); goto end; } - */ if (outformat > 1) { if (fwrite(mac, 1, sizeof(mac), outfp) != sizeof(mac)) { diff --git a/tools/sm4_cbc_sm3_hmac.c b/tools/sm4_cbc_sm3_hmac.c index 5ff34723..47df8811 100755 --- a/tools/sm4_cbc_sm3_hmac.c +++ b/tools/sm4_cbc_sm3_hmac.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. @@ -99,7 +99,7 @@ int sm4_cbc_sm3_hmac_main(int argc, char **argv) goto end; } if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { - fprintf(stderr, "gmssl %s: invalid key hex digits, should be %d bytes\n", prog, SM4_CBC_SM3_HMAC_IV_SIZE); + fprintf(stderr, "gmssl %s: invalid key hex digits, should be %d bytes\n", prog, SM4_CBC_SM3_HMAC_KEY_SIZE); goto end; } } else if (!strcmp(*argv, "-iv")) { diff --git a/tools/sm4_ctr_sm3_hmac.c b/tools/sm4_ctr_sm3_hmac.c index 676c3424..9db3b13e 100755 --- a/tools/sm4_ctr_sm3_hmac.c +++ b/tools/sm4_ctr_sm3_hmac.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. @@ -99,7 +99,7 @@ int sm4_ctr_sm3_hmac_main(int argc, char **argv) goto end; } if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { - fprintf(stderr, "gmssl %s: invalid key hex digits, should be %d bytes\n", prog, SM4_CTR_SM3_HMAC_IV_SIZE); + fprintf(stderr, "gmssl %s: invalid key hex digits, should be %d bytes\n", prog, SM4_CTR_SM3_HMAC_KEY_SIZE); goto end; } } else if (!strcmp(*argv, "-iv")) { diff --git a/tools/sm4_xts.c b/tools/sm4_xts.c index a3333f88..cdf66e29 100755 --- a/tools/sm4_xts.c +++ b/tools/sm4_xts.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. @@ -56,7 +56,7 @@ int sm4_xts_main(int argc, char **argv) size_t ivlen; FILE *infp = stdin; FILE *outfp = stdout; - SM4_XTS_CTX ctx; + SM4_XTS_CTX ctx = {0}; uint8_t *buf = NULL; size_t buflen; size_t inlen; @@ -212,6 +212,7 @@ bad: ret = 0; end: + if (ctx.block) free(ctx.block); gmssl_secure_clear(key, sizeof(key)); gmssl_secure_clear(iv, sizeof(iv)); gmssl_secure_clear(&ctx, sizeof(ctx));