Update sm4_ff1

This commit is contained in:
Zhi Guan
2026-06-26 23:06:02 +08:00
parent e77378558c
commit 52f0f1619e
9 changed files with 250 additions and 419 deletions

View File

@@ -487,9 +487,9 @@ endif()
if (ENABLE_SM4_FF1) if (ENABLE_SM4_FF1)
message(STATUS "ENABLE_SM4_FF1 is ON") message(STATUS "ENABLE_SM4_FF1 is ON")
add_definitions(-DENABLE_SM4_FF1) add_definitions(-DENABLE_SM4_FF1)
list(APPEND src src/ff1.c) list(APPEND src src/sm4_ff1.c)
list(APPEND tools tools/sm4_ff1.c) list(APPEND tools tools/sm4_ff1.c)
list(APPEND tests ff1) list(APPEND tests sm4_ff1)
endif() endif()
@@ -1025,7 +1025,7 @@ endif()
# #
set(CPACK_PACKAGE_NAME "GmSSL") set(CPACK_PACKAGE_NAME "GmSSL")
set(CPACK_PACKAGE_VENDOR "GmSSL develop team") set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1179") set(CPACK_PACKAGE_VERSION "3.3.0-dev.1180")
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
set(CPACK_NSIS_MODIFY_PATH ON) set(CPACK_NSIS_MODIFY_PATH ON)
include(CPack) include(CPack)

View File

@@ -40,40 +40,22 @@ gmssl_run(sm4_cbc -decrypt -pkcs7_padding -key ${SM4_KEY} -iv ${SM4_IV}
-in tool_sm4_cbc_pkcs7_kat.cipher -out tool_sm4_cbc_pkcs7_kat.decrypt) -in tool_sm4_cbc_pkcs7_kat.cipher -out tool_sm4_cbc_pkcs7_kat.decrypt)
gmssl_files_equal(tool_sm4_cbc_pkcs7_kat.plain tool_sm4_cbc_pkcs7_kat.decrypt) gmssl_files_equal(tool_sm4_cbc_pkcs7_kat.plain tool_sm4_cbc_pkcs7_kat.decrypt)
file(WRITE tool_sm4_unified_cbc_kat.plain "0123456789abcdef")
gmssl_run(sm4 -cbc -encrypt -key ${SM4_KEY} -iv ${SM4_IV}
-in tool_sm4_unified_cbc_kat.plain -out tool_sm4_unified_cbc_kat.cipher)
gmssl_expect_file_hex(tool_sm4_unified_cbc_kat.cipher
"e6887b77dbabb572ffa07fed7548b192ceaace11f2b90b94c2b7a4d9382e471e")
gmssl_run(sm4 -cbc -decrypt -key ${SM4_KEY} -iv ${SM4_IV}
-in tool_sm4_unified_cbc_kat.cipher -out tool_sm4_unified_cbc_kat.decrypt)
gmssl_files_equal(tool_sm4_unified_cbc_kat.plain tool_sm4_unified_cbc_kat.decrypt)
gmssl_symmetric_roundtrip(tool_sm4_cbc sm4_cbc -key ${SM4_KEY} -iv ${SM4_IV}) gmssl_symmetric_roundtrip(tool_sm4_cbc sm4_cbc -key ${SM4_KEY} -iv ${SM4_IV})
gmssl_symmetric_roundtrip(tool_sm4_cbc_pkcs7 sm4_cbc -pkcs7_padding -key ${SM4_KEY} -iv ${SM4_IV}) gmssl_symmetric_roundtrip(tool_sm4_cbc_pkcs7 sm4_cbc -pkcs7_padding -key ${SM4_KEY} -iv ${SM4_IV})
gmssl_symmetric_roundtrip(tool_sm4_ctr sm4_ctr -key ${SM4_KEY} -iv ${SM4_IV}) gmssl_symmetric_roundtrip(tool_sm4_ctr sm4_ctr -key ${SM4_KEY} -iv ${SM4_IV})
gmssl_symmetric_roundtrip(tool_sm4_gcm sm4_gcm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16) gmssl_symmetric_roundtrip(tool_sm4_gcm sm4_gcm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
gmssl_symmetric_roundtrip(tool_sm4_unified_cbc sm4 -cbc -key ${SM4_KEY} -iv ${SM4_IV})
gmssl_symmetric_roundtrip(tool_sm4_unified_ctr sm4 -ctr -key ${SM4_KEY} -iv ${SM4_IV})
gmssl_symmetric_roundtrip(tool_sm4_unified_gcm sm4 -gcm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
if(ENABLE_SM4_ECB) if(ENABLE_SM4_ECB)
gmssl_symmetric_roundtrip(tool_sm4_ecb sm4_ecb -key ${SM4_KEY}) gmssl_symmetric_roundtrip(tool_sm4_ecb sm4_ecb -key ${SM4_KEY})
gmssl_symmetric_roundtrip(tool_sm4_unified_ecb sm4 -ecb -key ${SM4_KEY})
endif() endif()
if(ENABLE_SM4_CFB) if(ENABLE_SM4_CFB)
gmssl_symmetric_roundtrip(tool_sm4_cfb sm4_cfb -sbytes 16 -key ${SM4_KEY} -iv ${SM4_IV}) gmssl_symmetric_roundtrip(tool_sm4_cfb sm4_cfb -sbytes 16 -key ${SM4_KEY} -iv ${SM4_IV})
gmssl_symmetric_roundtrip(tool_sm4_unified_cfb sm4 -cfb -sbytes 16 -key ${SM4_KEY} -iv ${SM4_IV})
gmssl_symmetric_roundtrip(tool_sm4_unified_cfb8 sm4 -cfb -sbytes 1 -key ${SM4_KEY} -iv ${SM4_IV})
endif() endif()
if(ENABLE_SM4_OFB) if(ENABLE_SM4_OFB)
gmssl_symmetric_roundtrip(tool_sm4_ofb sm4_ofb -key ${SM4_KEY} -iv ${SM4_IV}) gmssl_symmetric_roundtrip(tool_sm4_ofb sm4_ofb -key ${SM4_KEY} -iv ${SM4_IV})
gmssl_symmetric_roundtrip(tool_sm4_unified_ofb sm4 -ofb -key ${SM4_KEY} -iv ${SM4_IV})
endif() endif()
if(ENABLE_SM4_CCM) if(ENABLE_SM4_CCM)
gmssl_symmetric_roundtrip(tool_sm4_ccm sm4_ccm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16) gmssl_symmetric_roundtrip(tool_sm4_ccm sm4_ccm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
gmssl_symmetric_roundtrip(tool_sm4_unified_ccm sm4 -ccm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
endif() endif()
if(ENABLE_SM4_XTS) if(ENABLE_SM4_XTS)
file(WRITE tool_sm4_xts.plain "0123456789abcdef0123456789abcdef") file(WRITE tool_sm4_xts.plain "0123456789abcdef0123456789abcdef")
@@ -82,12 +64,6 @@ if(ENABLE_SM4_XTS)
gmssl_run(sm4_xts -decrypt -key ${SM4_XTS_KEY} -iv ${SM4_IV} -data_unit_size 32 gmssl_run(sm4_xts -decrypt -key ${SM4_XTS_KEY} -iv ${SM4_IV} -data_unit_size 32
-in tool_sm4_xts.cipher -out tool_sm4_xts.decrypt) -in tool_sm4_xts.cipher -out tool_sm4_xts.decrypt)
gmssl_files_equal(tool_sm4_xts.plain tool_sm4_xts.decrypt) gmssl_files_equal(tool_sm4_xts.plain tool_sm4_xts.decrypt)
file(WRITE tool_sm4_unified_xts.plain "0123456789abcdef0123456789abcdef")
gmssl_run(sm4 -xts -encrypt -key ${SM4_XTS_KEY} -iv ${SM4_IV} -data_unit_size 32
-in tool_sm4_unified_xts.plain -out tool_sm4_unified_xts.cipher)
gmssl_run(sm4 -xts -decrypt -key ${SM4_XTS_KEY} -iv ${SM4_IV} -data_unit_size 32
-in tool_sm4_unified_xts.cipher -out tool_sm4_unified_xts.decrypt)
gmssl_files_equal(tool_sm4_unified_xts.plain tool_sm4_unified_xts.decrypt)
endif() endif()
if(ENABLE_SM4_FF1) if(ENABLE_SM4_FF1)
gmssl_expect_stdout("2326982895499381\n" gmssl_expect_stdout("2326982895499381\n"

View File

@@ -1,41 +0,0 @@
/*
* 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef GMSSL_FF1_H
#define GMSSL_FF1_H
#include <stdint.h>
#include <stddef.h>
#include <gmssl/block_cipher.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FF1_MIN_DIGITS 8
#define FF1_MAX_DIGITS 18
#define FF1_MIN_TWEAK_SIZE 0
#define FF1_MAX_TWEAK_SIZE 11
#define FF1_NUM_ROUNDS 10
int ff1_init(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher, const uint8_t *raw_key);
int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
const uint8_t *tweak, size_t tweaklen, char *out);
int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
const uint8_t *tweak, size_t tweaklen, char *out);
#ifdef __cplusplus
}
#endif
#endif

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 * Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License. * not use this file except in compliance with the License.
@@ -259,6 +259,21 @@ int sm4_xts_decrypt_finish(SM4_XTS_CTX *ctx, uint8_t *out, size_t *outlen);
#endif // ENABLE_SM4_XTS #endif // ENABLE_SM4_XTS
#ifdef ENABLE_SM4_FF1
#define SM4_FF1_MIN_DIGITS 8
#define SM4_FF1_MAX_DIGITS 18
#define SM4_FF1_MIN_TWEAK_SIZE 0
#define SM4_FF1_MAX_TWEAK_SIZE 11
#define SM4_FF1_NUM_ROUNDS 10
int sm4_ff1_init(SM4_KEY *key, const uint8_t raw_key[SM4_KEY_SIZE]);
int sm4_ff1_encrypt(const SM4_KEY *key, const char *in, size_t inlen,
const uint8_t *tweak, size_t tweaklen, char *out);
int sm4_ff1_decrypt(const SM4_KEY *key, const char *in, size_t inlen,
const uint8_t *tweak, size_t tweaklen, char *out);
#endif // ENABLE_SM4_FF1
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -18,7 +18,7 @@ extern "C" {
#define GMSSL_VERSION_NUM 30300 #define GMSSL_VERSION_NUM 30300
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1179" #define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1180"
int gmssl_version_num(void); int gmssl_version_num(void);
const char *gmssl_version_str(void); const char *gmssl_version_str(void);

View File

@@ -7,13 +7,13 @@
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
*/ */
#include <gmssl/ff1.h> #include <gmssl/sm4.h>
#include <string.h> #include <string.h>
#include <gmssl/endian.h> #include <gmssl/endian.h>
#include <gmssl/error.h> #include <gmssl/error.h>
static const uint32_t ff1_radix10_mod[] = { static const uint32_t sm4_ff1_radix10_mod[] = {
1, 1,
10, 10,
100, 100,
@@ -26,33 +26,26 @@ static const uint32_t ff1_radix10_mod[] = {
1000000000, 1000000000,
}; };
static const size_t ff1_radix10_b[] = { static const size_t sm4_ff1_radix10_b[] = {
0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4,
}; };
int ff1_init(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher, const uint8_t *raw_key) int sm4_ff1_init(SM4_KEY *key, const uint8_t raw_key[SM4_KEY_SIZE])
{ {
if (!key || !cipher || !raw_key) { if (!key || !raw_key) {
error_print();
return -1;
}
if (cipher->block_size != BLOCK_CIPHER_BLOCK_SIZE) {
error_print();
return -1;
}
if (block_cipher_set_encrypt_key(key, cipher, raw_key) != 1) {
error_print(); error_print();
return -1; return -1;
} }
sm4_set_encrypt_key(key, raw_key);
return 1; return 1;
} }
static int ff1_digits_to_num(const char *digits, size_t ndigits, uint32_t *num) static int sm4_ff1_digits_to_num(const char *digits, size_t ndigits, uint32_t *num)
{ {
uint32_t value = 0; uint32_t value = 0;
size_t i; size_t i;
if (!digits || !num || ndigits > FF1_MAX_DIGITS/2) { if (!digits || !num || ndigits > SM4_FF1_MAX_DIGITS/2) {
error_print(); error_print();
return -1; return -1;
} }
@@ -67,9 +60,9 @@ static int ff1_digits_to_num(const char *digits, size_t ndigits, uint32_t *num)
return 1; return 1;
} }
static int ff1_num_to_digits(uint32_t num, size_t ndigits, char *digits) static int sm4_ff1_num_to_digits(uint32_t num, size_t ndigits, char *digits)
{ {
if (!digits || ndigits > FF1_MAX_DIGITS/2 || num >= ff1_radix10_mod[ndigits]) { if (!digits || ndigits > SM4_FF1_MAX_DIGITS/2 || num >= sm4_ff1_radix10_mod[ndigits]) {
error_print(); error_print();
return -1; return -1;
} }
@@ -80,24 +73,20 @@ static int ff1_num_to_digits(uint32_t num, size_t ndigits, char *digits)
return 1; return 1;
} }
static int ff1_check_args(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen, static int sm4_ff1_check_args(const SM4_KEY *key, const char *in, size_t inlen,
const uint8_t *tweak, size_t tweaklen, char *out) const uint8_t *tweak, size_t tweaklen, char *out)
{ {
size_t i; size_t i;
if (!key || !key->cipher || !in || !out || (!tweak && tweaklen)) { if (!key || !in || !out || (!tweak && tweaklen)) {
error_print(); error_print();
return -1; return -1;
} }
if (key->cipher->block_size != BLOCK_CIPHER_BLOCK_SIZE) { if (inlen < SM4_FF1_MIN_DIGITS || inlen > SM4_FF1_MAX_DIGITS) {
error_print(); error_print();
return -1; return -1;
} }
if (inlen < FF1_MIN_DIGITS || inlen > FF1_MAX_DIGITS) { if (tweaklen < SM4_FF1_MIN_TWEAK_SIZE || tweaklen > SM4_FF1_MAX_TWEAK_SIZE) {
error_print();
return -1;
}
if (tweaklen < FF1_MIN_TWEAK_SIZE || tweaklen > FF1_MAX_TWEAK_SIZE) {
error_print(); error_print();
return -1; return -1;
} }
@@ -110,27 +99,24 @@ static int ff1_check_args(const BLOCK_CIPHER_KEY *key, const char *in, size_t in
return 1; return 1;
} }
static int ff1_init_pblock(const BLOCK_CIPHER_KEY *key, uint8_t pblock[16], static int sm4_ff1_init_pblock(const SM4_KEY *key, uint8_t pblock[16],
size_t u, size_t n, size_t tweaklen) size_t u, size_t n, size_t tweaklen)
{ {
static const uint8_t ff1_radix10_pblock[16] = { static const uint8_t sm4_ff1_radix10_pblock[16] = {
0x01, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x0a, 0xff, 0x01, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x0a, 0xff,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
}; };
memcpy(pblock, ff1_radix10_pblock, 16); memcpy(pblock, sm4_ff1_radix10_pblock, 16);
pblock[7] = (uint8_t)u; pblock[7] = (uint8_t)u;
PUTU32(pblock + 8, (uint32_t)n); PUTU32(pblock + 8, (uint32_t)n);
PUTU32(pblock + 12, (uint32_t)tweaklen); PUTU32(pblock + 12, (uint32_t)tweaklen);
if (block_cipher_encrypt(key, pblock, pblock) != 1) { sm4_encrypt(key, pblock, pblock);
error_print();
return -1;
}
return 1; return 1;
} }
static int ff1_round(const BLOCK_CIPHER_KEY *key, const uint8_t pblock[16], static int sm4_ff1_round(const SM4_KEY *key, const uint8_t pblock[16],
const uint8_t *tweak, size_t tweaklen, size_t bsize, int round, uint32_t num, uint64_t *y) const uint8_t *tweak, size_t tweaklen, size_t bsize, int round, uint32_t num, uint64_t *y)
{ {
uint8_t qblock[32] = {0}; uint8_t qblock[32] = {0};
@@ -165,25 +151,19 @@ static int ff1_round(const BLOCK_CIPHER_KEY *key, const uint8_t pblock[16],
for (i = 0; i < sizeof(block); i++) { for (i = 0; i < sizeof(block); i++) {
block[i] = pblock[i] ^ qblock[i]; block[i] = pblock[i] ^ qblock[i];
} }
if (block_cipher_encrypt(key, block, block) != 1) { sm4_encrypt(key, block, block);
error_print();
return -1;
}
for (offset = 16; offset < qlen; offset += 16) { for (offset = 16; offset < qlen; offset += 16) {
for (i = 0; i < sizeof(block); i++) { for (i = 0; i < sizeof(block); i++) {
block[i] ^= qblock[offset + i]; block[i] ^= qblock[offset + i];
} }
if (block_cipher_encrypt(key, block, block) != 1) { sm4_encrypt(key, block, block);
error_print();
return -1;
}
} }
*y = GETU64(block); *y = GETU64(block);
return 1; return 1;
} }
int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen, int sm4_ff1_encrypt(const SM4_KEY *key, const char *in, size_t inlen,
const uint8_t *tweak, size_t tweaklen, char *out) const uint8_t *tweak, size_t tweaklen, char *out)
{ {
size_t u; size_t u;
@@ -199,7 +179,7 @@ int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
size_t bsize; size_t bsize;
int i; int i;
if (ff1_check_args(key, in, inlen, tweak, tweaklen, out) != 1) { if (sm4_ff1_check_args(key, in, inlen, tweak, tweaklen, out) != 1) {
error_print(); error_print();
return -1; return -1;
} }
@@ -207,25 +187,25 @@ int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
u = inlen / 2; u = inlen / 2;
v = inlen - u; v = inlen - u;
if (ff1_digits_to_num(in, u, &a) != 1 if (sm4_ff1_digits_to_num(in, u, &a) != 1
|| ff1_digits_to_num(in + u, v, &b) != 1 || sm4_ff1_digits_to_num(in + u, v, &b) != 1
|| ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) { || sm4_ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) {
error_print(); error_print();
return -1; return -1;
} }
alen = u; alen = u;
blen = v; blen = v;
bsize = ff1_radix10_b[v]; bsize = sm4_ff1_radix10_b[v];
for (i = 0; i < FF1_NUM_ROUNDS; i++) { for (i = 0; i < SM4_FF1_NUM_ROUNDS; i++) {
size_t m = (i & 1) ? v : u; size_t m = (i & 1) ? v : u;
if (ff1_round(key, pblock, tweak, tweaklen, bsize, i, b, &y) != 1) { if (sm4_ff1_round(key, pblock, tweak, tweaklen, bsize, i, b, &y) != 1) {
error_print(); error_print();
return -1; return -1;
} }
ymod = (uint32_t)(y % ff1_radix10_mod[m]); ymod = (uint32_t)(y % sm4_ff1_radix10_mod[m]);
c = (a + ymod) % ff1_radix10_mod[m]; c = (a + ymod) % sm4_ff1_radix10_mod[m];
a = b; a = b;
alen = blen; alen = blen;
b = c; b = c;
@@ -236,15 +216,15 @@ int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
error_print(); error_print();
return -1; return -1;
} }
if (ff1_num_to_digits(a, alen, out) != 1 if (sm4_ff1_num_to_digits(a, alen, out) != 1
|| ff1_num_to_digits(b, blen, out + alen) != 1) { || sm4_ff1_num_to_digits(b, blen, out + alen) != 1) {
error_print(); error_print();
return -1; return -1;
} }
return 1; return 1;
} }
int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen, int sm4_ff1_decrypt(const SM4_KEY *key, const char *in, size_t inlen,
const uint8_t *tweak, size_t tweaklen, char *out) const uint8_t *tweak, size_t tweaklen, char *out)
{ {
size_t u; size_t u;
@@ -260,7 +240,7 @@ int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
size_t bsize; size_t bsize;
int i; int i;
if (ff1_check_args(key, in, inlen, tweak, tweaklen, out) != 1) { if (sm4_ff1_check_args(key, in, inlen, tweak, tweaklen, out) != 1) {
error_print(); error_print();
return -1; return -1;
} }
@@ -268,30 +248,30 @@ int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
u = inlen / 2; u = inlen / 2;
v = inlen - u; v = inlen - u;
if (ff1_digits_to_num(in, u, &a) != 1 if (sm4_ff1_digits_to_num(in, u, &a) != 1
|| ff1_digits_to_num(in + u, v, &b) != 1 || sm4_ff1_digits_to_num(in + u, v, &b) != 1
|| ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) { || sm4_ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) {
error_print(); error_print();
return -1; return -1;
} }
alen = u; alen = u;
blen = v; blen = v;
bsize = ff1_radix10_b[v]; bsize = sm4_ff1_radix10_b[v];
for (i = FF1_NUM_ROUNDS - 1; i >= 0; i--) { for (i = SM4_FF1_NUM_ROUNDS - 1; i >= 0; i--) {
size_t m = (i & 1) ? v : u; size_t m = (i & 1) ? v : u;
c = b; c = b;
b = a; b = a;
blen = alen; blen = alen;
if (ff1_round(key, pblock, tweak, tweaklen, bsize, i, b, &y) != 1) { if (sm4_ff1_round(key, pblock, tweak, tweaklen, bsize, i, b, &y) != 1) {
error_print(); error_print();
return -1; return -1;
} }
ymod = (uint32_t)(y % ff1_radix10_mod[m]); ymod = (uint32_t)(y % sm4_ff1_radix10_mod[m]);
a = c; a = c;
a = (a >= ymod) ? a - ymod : a + ff1_radix10_mod[m] - ymod; a = (a >= ymod) ? a - ymod : a + sm4_ff1_radix10_mod[m] - ymod;
alen = m; alen = m;
} }
@@ -299,8 +279,8 @@ int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
error_print(); error_print();
return -1; return -1;
} }
if (ff1_num_to_digits(a, alen, out) != 1 if (sm4_ff1_num_to_digits(a, alen, out) != 1
|| ff1_num_to_digits(b, blen, out + alen) != 1) { || sm4_ff1_num_to_digits(b, blen, out + alen) != 1) {
error_print(); error_print();
return -1; return -1;
} }

View File

@@ -1,273 +0,0 @@
/*
* 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <stdio.h>
#include <string.h>
#include <gmssl/ff1.h>
#include <gmssl/error.h>
typedef struct {
const uint8_t key[16];
const char *plaintext;
const uint8_t *tweak;
size_t tweaklen;
const char *ciphertext;
} FF1_TEST;
static const uint8_t ff1_sm4_tweak1[] = {
0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
0x31, 0x30,
};
static const uint8_t ff1_sm4_tweak2[] = {
0x37, 0x38, 0x39, 0x36, 0x70, 0x71, 0x72, 0x73,
0x74, 0x75, 0x76,
};
static const FF1_TEST ff1_sm4_tests[] = {
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"6226090102675688",
ff1_sm4_tweak1,
sizeof(ff1_sm4_tweak1),
"2326982895499381",
},
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"110107197203192876",
ff1_sm4_tweak2,
sizeof(ff1_sm4_tweak2),
"755842115213533405",
},
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"13687260594",
NULL,
0,
"37914960556",
},
};
#ifdef ENABLE_AES
static const uint8_t ff1_aes128_tweak1[] = {
0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
0x31, 0x30,
};
static const uint8_t ff1_aes128_tweak4[] = {
0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
};
static const FF1_TEST ff1_aes128_tests[] = {
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"0123456789",
ff1_aes128_tweak1,
sizeof(ff1_aes128_tweak1),
"6124200773",
},
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"0123456789",
NULL,
0,
"2433477484",
},
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"999999999",
ff1_aes128_tweak4,
sizeof(ff1_aes128_tweak4),
"658229573",
},
};
#endif
static int test_ff1_sm4(void)
{
const char *plaintext = "99999999999999999";
size_t plaintext_len = strlen(plaintext);
const char sentinel = '#';
const uint8_t key[16] = {0};
const uint8_t tweak[8] = {
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
};
BLOCK_CIPHER_KEY block_key;
char ciphertext[FF1_MAX_DIGITS + 1];
char decrypted[FF1_MAX_DIGITS + 1];
if (ff1_init(&block_key, BLOCK_CIPHER_sm4(), key) != 1) {
error_print();
return -1;
}
ciphertext[plaintext_len] = sentinel;
if (ff1_encrypt(&block_key, plaintext, plaintext_len,
tweak, sizeof(tweak), ciphertext) != 1) {
error_print();
return -1;
}
if (ciphertext[plaintext_len] != sentinel) {
error_print();
return -1;
}
ciphertext[plaintext_len] = '\0';
decrypted[plaintext_len] = sentinel;
if (ff1_decrypt(&block_key, ciphertext, plaintext_len,
tweak, sizeof(tweak), decrypted) != 1) {
error_print();
return -1;
}
if (decrypted[plaintext_len] != sentinel) {
error_print();
return -1;
}
decrypted[plaintext_len] = '\0';
if (strcmp(plaintext, decrypted) != 0) {
error_print();
return -1;
}
printf("ff1-sm4-encrypt(\"%s\") = \"%s\"\n", plaintext, ciphertext);
printf("%s() ok\n", __FUNCTION__);
return 1;
}
static int test_ff1_sm4_vectors(void)
{
BLOCK_CIPHER_KEY block_key;
char ciphertext[FF1_MAX_DIGITS + 1];
char decrypted[FF1_MAX_DIGITS + 1];
size_t i;
int err = 0;
for (i = 0; i < sizeof(ff1_sm4_tests)/sizeof(ff1_sm4_tests[0]); i++) {
const FF1_TEST *test = &ff1_sm4_tests[i];
if (ff1_init(&block_key, BLOCK_CIPHER_sm4(), test->key) != 1) {
error_print();
return -1;
}
if (ff1_encrypt(&block_key, test->plaintext, strlen(test->plaintext),
test->tweak, test->tweaklen, ciphertext) != 1) {
error_print();
return -1;
}
ciphertext[strlen(test->plaintext)] = '\0';
if (strcmp(ciphertext, test->ciphertext) != 0) {
fprintf(stderr, "test %zu: got %s, expected %s\n",
i + 1, ciphertext, test->ciphertext);
error_print();
err++;
continue;
}
if (ff1_decrypt(&block_key, test->ciphertext, strlen(test->ciphertext),
test->tweak, test->tweaklen, decrypted) != 1) {
error_print();
return -1;
}
decrypted[strlen(test->ciphertext)] = '\0';
if (strcmp(decrypted, test->plaintext) != 0) {
error_print();
return -1;
}
}
if (err) {
return -1;
}
printf("%s() ok\n", __FUNCTION__);
return 1;
}
#ifdef ENABLE_AES
static int test_ff1_aes128_vectors(void)
{
BLOCK_CIPHER_KEY block_key;
char ciphertext[FF1_MAX_DIGITS + 1];
char decrypted[FF1_MAX_DIGITS + 1];
size_t i;
int err = 0;
for (i = 0; i < sizeof(ff1_aes128_tests)/sizeof(ff1_aes128_tests[0]); i++) {
const FF1_TEST *test = &ff1_aes128_tests[i];
if (ff1_init(&block_key, BLOCK_CIPHER_aes128(), test->key) != 1) {
error_print();
return -1;
}
if (ff1_encrypt(&block_key, test->plaintext, strlen(test->plaintext),
test->tweak, test->tweaklen, ciphertext) != 1) {
error_print();
return -1;
}
ciphertext[strlen(test->plaintext)] = '\0';
if (strcmp(ciphertext, test->ciphertext) != 0) {
fprintf(stderr, "AES-128 test %zu: got %s, expected %s\n",
i + 1, ciphertext, test->ciphertext);
error_print();
err++;
continue;
}
if (ff1_decrypt(&block_key, test->ciphertext, strlen(test->ciphertext),
test->tweak, test->tweaklen, decrypted) != 1) {
error_print();
return -1;
}
decrypted[strlen(test->ciphertext)] = '\0';
if (strcmp(decrypted, test->plaintext) != 0) {
error_print();
return -1;
}
}
if (err) {
return -1;
}
printf("%s() ok\n", __FUNCTION__);
return 1;
}
#endif
int main(void)
{
int err = 0;
if (test_ff1_sm4() != 1) {
err++;
}
if (test_ff1_sm4_vectors() != 1) {
err++;
}
#ifdef ENABLE_AES
if (test_ff1_aes128_vectors() != 1) {
err++;
}
#endif
return err;
}

175
tests/sm4_ff1test.c Normal file
View File

@@ -0,0 +1,175 @@
/*
* 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <stdio.h>
#include <string.h>
#include <gmssl/sm4.h>
#include <gmssl/error.h>
typedef struct {
const uint8_t key[16];
const char *plaintext;
const uint8_t *tweak;
size_t tweaklen;
const char *ciphertext;
} SM4_FF1_TEST;
static const uint8_t sm4_ff1_sm4_tweak1[] = {
0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
0x31, 0x30,
};
static const uint8_t sm4_ff1_sm4_tweak2[] = {
0x37, 0x38, 0x39, 0x36, 0x70, 0x71, 0x72, 0x73,
0x74, 0x75, 0x76,
};
static const SM4_FF1_TEST sm4_ff1_sm4_tests[] = {
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"6226090102675688",
sm4_ff1_sm4_tweak1,
sizeof(sm4_ff1_sm4_tweak1),
"2326982895499381",
},
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"110107197203192876",
sm4_ff1_sm4_tweak2,
sizeof(sm4_ff1_sm4_tweak2),
"755842115213533405",
},
{
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
},
"13687260594",
NULL,
0,
"37914960556",
},
};
static int test_sm4_ff1(void)
{
const char *plaintext = "99999999999999999";
size_t plaintext_len = strlen(plaintext);
const char sentinel = '#';
const uint8_t key[16] = {0};
const uint8_t tweak[8] = {
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
};
SM4_KEY sm4_key;
char ciphertext[SM4_FF1_MAX_DIGITS + 1];
char decrypted[SM4_FF1_MAX_DIGITS + 1];
if (sm4_ff1_init(&sm4_key, key) != 1) {
error_print();
return -1;
}
ciphertext[plaintext_len] = sentinel;
if (sm4_ff1_encrypt(&sm4_key, plaintext, plaintext_len,
tweak, sizeof(tweak), ciphertext) != 1) {
error_print();
return -1;
}
if (ciphertext[plaintext_len] != sentinel) {
error_print();
return -1;
}
ciphertext[plaintext_len] = '\0';
decrypted[plaintext_len] = sentinel;
if (sm4_ff1_decrypt(&sm4_key, ciphertext, plaintext_len,
tweak, sizeof(tweak), decrypted) != 1) {
error_print();
return -1;
}
if (decrypted[plaintext_len] != sentinel) {
error_print();
return -1;
}
decrypted[plaintext_len] = '\0';
if (strcmp(plaintext, decrypted) != 0) {
error_print();
return -1;
}
printf("sm4_ff1_encrypt(\"%s\") = \"%s\"\n", plaintext, ciphertext);
printf("%s() ok\n", __FUNCTION__);
return 1;
}
static int test_sm4_ff1_vectors(void)
{
SM4_KEY sm4_key;
char ciphertext[SM4_FF1_MAX_DIGITS + 1];
char decrypted[SM4_FF1_MAX_DIGITS + 1];
size_t i;
int err = 0;
for (i = 0; i < sizeof(sm4_ff1_sm4_tests)/sizeof(sm4_ff1_sm4_tests[0]); i++) {
const SM4_FF1_TEST *test = &sm4_ff1_sm4_tests[i];
if (sm4_ff1_init(&sm4_key, test->key) != 1) {
error_print();
return -1;
}
if (sm4_ff1_encrypt(&sm4_key, test->plaintext, strlen(test->plaintext),
test->tweak, test->tweaklen, ciphertext) != 1) {
error_print();
return -1;
}
ciphertext[strlen(test->plaintext)] = '\0';
if (strcmp(ciphertext, test->ciphertext) != 0) {
fprintf(stderr, "test %zu: got %s, expected %s\n",
i + 1, ciphertext, test->ciphertext);
error_print();
err++;
continue;
}
if (sm4_ff1_decrypt(&sm4_key, test->ciphertext, strlen(test->ciphertext),
test->tweak, test->tweaklen, decrypted) != 1) {
error_print();
return -1;
}
decrypted[strlen(test->ciphertext)] = '\0';
if (strcmp(decrypted, test->plaintext) != 0) {
error_print();
return -1;
}
}
if (err) {
return -1;
}
printf("%s() ok\n", __FUNCTION__);
return 1;
}
int main(void)
{
int err = 0;
if (test_sm4_ff1() != 1) {
err++;
}
if (test_sm4_ff1_vectors() != 1) {
err++;
}
return err;
}

View File

@@ -12,13 +12,12 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <gmssl/ff1.h> #include <gmssl/sm4.h>
#include <gmssl/hex.h> #include <gmssl/hex.h>
#include <gmssl/mem.h> #include <gmssl/mem.h>
#include <gmssl/error.h> #include <gmssl/error.h>
#define SM4_FF1_MAX_TWEAK_SIZE FF1_MAX_TWEAK_SIZE
#define ID_CARD_DIGITS 18 #define ID_CARD_DIGITS 18
#define ID_CARD_BODY_DIGITS 17 #define ID_CARD_BODY_DIGITS 17
@@ -152,7 +151,7 @@ static int bankcard_check(const char *s, size_t len)
{ {
int ch; int ch;
if (!s || len < FF1_MIN_DIGITS + 1 || len > FF1_MAX_DIGITS + 1 || !is_digits(s, len)) { if (!s || len < SM4_FF1_MIN_DIGITS + 1 || len > SM4_FF1_MAX_DIGITS + 1 || !is_digits(s, len)) {
return -1; return -1;
} }
ch = luhn_check_digit(s, len - 1); ch = luhn_check_digit(s, len - 1);
@@ -179,9 +178,9 @@ int sm4_ff1_main(int argc, char **argv)
uint8_t *inbuf = NULL; uint8_t *inbuf = NULL;
int inbuf_alloc = 0; int inbuf_alloc = 0;
size_t inlen; size_t inlen;
char outbuf[FF1_MAX_DIGITS + 2]; char outbuf[SM4_FF1_MAX_DIGITS + 2];
size_t bodylen; size_t bodylen;
BLOCK_CIPHER_KEY block_key; SM4_KEY sm4_key;
argc--; argc--;
argv++; argv++;
@@ -272,7 +271,7 @@ bad:
fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); fprintf(stderr, "gmssl %s: option `-key` missing\n", prog);
goto end; goto end;
} }
if (tweakhex && tweaklen > FF1_MAX_TWEAK_SIZE) { if (tweakhex && tweaklen > SM4_FF1_MAX_TWEAK_SIZE) {
fprintf(stderr, "gmssl %s: invalid tweak length\n", prog); fprintf(stderr, "gmssl %s: invalid tweak length\n", prog);
goto end; goto end;
} }
@@ -303,24 +302,24 @@ bad:
} }
bodylen = inlen - 1; bodylen = inlen - 1;
} else { } else {
if (inlen < FF1_MIN_DIGITS || inlen > FF1_MAX_DIGITS || !is_digits((char *)inbuf, inlen)) { if (inlen < SM4_FF1_MIN_DIGITS || inlen > SM4_FF1_MAX_DIGITS || !is_digits((char *)inbuf, inlen)) {
fprintf(stderr, "gmssl %s: invalid input digits\n", prog); fprintf(stderr, "gmssl %s: invalid input digits\n", prog);
goto end; goto end;
} }
bodylen = inlen; bodylen = inlen;
} }
if (ff1_init(&block_key, BLOCK_CIPHER_sm4(), key) != 1) { if (sm4_ff1_init(&sm4_key, key) != 1) {
error_print(); error_print();
goto end; goto end;
} }
if (enc) { if (enc) {
if (ff1_encrypt(&block_key, (char *)inbuf, bodylen, tweak, tweaklen, outbuf) != 1) { if (sm4_ff1_encrypt(&sm4_key, (char *)inbuf, bodylen, tweak, tweaklen, outbuf) != 1) {
error_print(); error_print();
goto end; goto end;
} }
} else { } else {
if (ff1_decrypt(&block_key, (char *)inbuf, bodylen, tweak, tweaklen, outbuf) != 1) { if (sm4_ff1_decrypt(&sm4_key, (char *)inbuf, bodylen, tweak, tweaklen, outbuf) != 1) {
error_print(); error_print();
goto end; goto end;
} }
@@ -361,6 +360,6 @@ end:
if (inbuf_alloc) free(inbuf); if (inbuf_alloc) free(inbuf);
gmssl_secure_clear(key, sizeof(key)); gmssl_secure_clear(key, sizeof(key));
gmssl_secure_clear(tweak, sizeof(tweak)); gmssl_secure_clear(tweak, sizeof(tweak));
gmssl_secure_clear(&block_key, sizeof(block_key)); gmssl_secure_clear(&sm4_key, sizeof(sm4_key));
return ret; return ret;
} }