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

@@ -7,13 +7,13 @@
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <gmssl/ff1.h>
#include <gmssl/sm4.h>
#include <string.h>
#include <gmssl/endian.h>
#include <gmssl/error.h>
static const uint32_t ff1_radix10_mod[] = {
static const uint32_t sm4_ff1_radix10_mod[] = {
1,
10,
100,
@@ -26,33 +26,26 @@ static const uint32_t ff1_radix10_mod[] = {
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,
};
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) {
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) {
if (!key || !raw_key) {
error_print();
return -1;
}
sm4_set_encrypt_key(key, raw_key);
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;
size_t i;
if (!digits || !num || ndigits > FF1_MAX_DIGITS/2) {
if (!digits || !num || ndigits > SM4_FF1_MAX_DIGITS/2) {
error_print();
return -1;
}
@@ -67,9 +60,9 @@ static int ff1_digits_to_num(const char *digits, size_t ndigits, uint32_t *num)
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();
return -1;
}
@@ -80,24 +73,20 @@ static int ff1_num_to_digits(uint32_t num, size_t ndigits, char *digits)
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)
{
size_t i;
if (!key || !key->cipher || !in || !out || (!tweak && tweaklen)) {
if (!key || !in || !out || (!tweak && tweaklen)) {
error_print();
return -1;
}
if (key->cipher->block_size != BLOCK_CIPHER_BLOCK_SIZE) {
if (inlen < SM4_FF1_MIN_DIGITS || inlen > SM4_FF1_MAX_DIGITS) {
error_print();
return -1;
}
if (inlen < FF1_MIN_DIGITS || inlen > FF1_MAX_DIGITS) {
error_print();
return -1;
}
if (tweaklen < FF1_MIN_TWEAK_SIZE || tweaklen > FF1_MAX_TWEAK_SIZE) {
if (tweaklen < SM4_FF1_MIN_TWEAK_SIZE || tweaklen > SM4_FF1_MAX_TWEAK_SIZE) {
error_print();
return -1;
}
@@ -110,27 +99,24 @@ static int ff1_check_args(const BLOCK_CIPHER_KEY *key, const char *in, size_t in
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)
{
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,
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;
PUTU32(pblock + 8, (uint32_t)n);
PUTU32(pblock + 12, (uint32_t)tweaklen);
if (block_cipher_encrypt(key, pblock, pblock) != 1) {
error_print();
return -1;
}
sm4_encrypt(key, pblock, pblock);
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)
{
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++) {
block[i] = pblock[i] ^ qblock[i];
}
if (block_cipher_encrypt(key, block, block) != 1) {
error_print();
return -1;
}
sm4_encrypt(key, block, block);
for (offset = 16; offset < qlen; offset += 16) {
for (i = 0; i < sizeof(block); i++) {
block[i] ^= qblock[offset + i];
}
if (block_cipher_encrypt(key, block, block) != 1) {
error_print();
return -1;
}
sm4_encrypt(key, block, block);
}
*y = GETU64(block);
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)
{
size_t u;
@@ -199,7 +179,7 @@ int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
size_t bsize;
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();
return -1;
}
@@ -207,25 +187,25 @@ int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
u = inlen / 2;
v = inlen - u;
if (ff1_digits_to_num(in, u, &a) != 1
|| ff1_digits_to_num(in + u, v, &b) != 1
|| ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) {
if (sm4_ff1_digits_to_num(in, u, &a) != 1
|| sm4_ff1_digits_to_num(in + u, v, &b) != 1
|| sm4_ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) {
error_print();
return -1;
}
alen = u;
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;
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();
return -1;
}
ymod = (uint32_t)(y % ff1_radix10_mod[m]);
c = (a + ymod) % ff1_radix10_mod[m];
ymod = (uint32_t)(y % sm4_ff1_radix10_mod[m]);
c = (a + ymod) % sm4_ff1_radix10_mod[m];
a = b;
alen = blen;
b = c;
@@ -236,15 +216,15 @@ int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
error_print();
return -1;
}
if (ff1_num_to_digits(a, alen, out) != 1
|| ff1_num_to_digits(b, blen, out + alen) != 1) {
if (sm4_ff1_num_to_digits(a, alen, out) != 1
|| sm4_ff1_num_to_digits(b, blen, out + alen) != 1) {
error_print();
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)
{
size_t u;
@@ -260,7 +240,7 @@ int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
size_t bsize;
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();
return -1;
}
@@ -268,30 +248,30 @@ int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
u = inlen / 2;
v = inlen - u;
if (ff1_digits_to_num(in, u, &a) != 1
|| ff1_digits_to_num(in + u, v, &b) != 1
|| ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) {
if (sm4_ff1_digits_to_num(in, u, &a) != 1
|| sm4_ff1_digits_to_num(in + u, v, &b) != 1
|| sm4_ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) {
error_print();
return -1;
}
alen = u;
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;
c = b;
b = a;
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();
return -1;
}
ymod = (uint32_t)(y % ff1_radix10_mod[m]);
ymod = (uint32_t)(y % sm4_ff1_radix10_mod[m]);
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;
}
@@ -299,8 +279,8 @@ int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
error_print();
return -1;
}
if (ff1_num_to_digits(a, alen, out) != 1
|| ff1_num_to_digits(b, blen, out + alen) != 1) {
if (sm4_ff1_num_to_digits(a, alen, out) != 1
|| sm4_ff1_num_to_digits(b, blen, out + alen) != 1) {
error_print();
return -1;
}