Fix SM4 API bugs and change behavior

This commit is contained in:
Zhi Guan
2026-06-13 22:14:56 +08:00
parent 8fded4abc7
commit c12edeb7b1
29 changed files with 1281 additions and 212 deletions

View File

@@ -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;

View File

@@ -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 <gmssl/sm4_cbc_mac.h>
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;
}

View File

@@ -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) {

View File

@@ -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 <gmssl/sm4.h>
#include <gmssl/mem.h>
#include <gmssl/sm4_cbc_mac.h>
#include <gmssl/error.h>
#include <gmssl/sm4.h>
#include <gmssl/sm4_cbc_mac.h>
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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;