Files
se-algo/zuc256_c/src/zuc256.c
2025-09-03 15:40:10 +08:00

618 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2025. Institute of Information Engineering, CAS
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file: zuc256.c
* @brief: zuc256 的纯c代码
* @author: QZH <qinzhenghui@iie.ac.cn>
* @version: 1.0.0
* @date: 2025-09-01
*
* @note: 无
*
* Change Logs:
* Date Author Notes
* 2025-08-04 QZH 创建文件
*/
#include <stdlib.h>
#include <string.h>
#include "zuc256.h"
// S盒定义
static const uint8_t S0[256] = {
0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38,
0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b,
0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c,
0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad,
0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8,
0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56,
0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe,
0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d,
0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23,
0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1,
0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f,
0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65,
0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60,
};
static const uint8_t S1[256] = {
0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48,
0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87,
0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb,
0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09,
0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9,
0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9,
0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89,
0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4,
0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde,
0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21,
0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34,
0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28,
0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2,
};
// 常量数组D
#define F_(X1,X2) \
W1 = R1 + X1; \
W2 = R2 ^ X2; \
U = L1((W1 << 16) | (W2 >> 16)); \
V = L2((W2 << 16) | (W1 >> 16)); \
R1 = MAKEU32( S0[U >> 24], \
S1[(U >> 16) & 0xFF], \
S0[(U >> 8) & 0xFF], \
S1[U & 0xFF]); \
R2 = MAKEU32( S0[V >> 24], \
S1[(V >> 16) & 0xFF], \
S0[(V >> 8) & 0xFF], \
S1[V & 0xFF])
#define F(X0,X1,X2) \
((X0 ^ R1) + R2); \
F_(X1, X2)
#define ADD31(a,b) a += (b); a = (a & 0x7fffffff) + (a >> 31)
#define ROT31(a,k) ((((a) << (k)) | ((a) >> (31 - (k)))) & 0x7FFFFFFF)
#define ROT32(a,k) (((a) << (k)) | ((a) >> (32 - (k))))
#define L1(X) \
((X) ^ \
ROT32((X), 2) ^ \
ROT32((X), 10) ^ \
ROT32((X), 18) ^ \
ROT32((X), 24))
#define L2(X) \
((X) ^ \
ROT32((X), 8) ^ \
ROT32((X), 14) ^ \
ROT32((X), 22) ^ \
ROT32((X), 30))
#define LFSRWithInitialisationMode(u) \
V = LFSR[0]; \
ADD31(V, ROT31(LFSR[ 0], 8)); \
ADD31(V, ROT31(LFSR[ 4], 20)); \
ADD31(V, ROT31(LFSR[10], 21)); \
ADD31(V, ROT31(LFSR[13], 17)); \
ADD31(V, ROT31(LFSR[15], 15)); \
ADD31(V, (u)); \
{int j; for (j=0; j<15;j++) LFSR[j]=LFSR[j+1];} \
LFSR[15] = V
#define LFSRWithWorkMode() \
{ \
int j; \
uint64_t a = LFSR[0]; \
a += ((uint64_t)LFSR[ 0]) << 8; \
a += ((uint64_t)LFSR[ 4]) << 20; \
a += ((uint64_t)LFSR[10]) << 21; \
a += ((uint64_t)LFSR[13]) << 17; \
a += ((uint64_t)LFSR[15]) << 15; \
a = (a & 0x7fffffff) + (a >> 31); \
V = (uint32_t)((a & 0x7fffffff) + (a >> 31)); \
for (j = 0; j < 15; j++) \
LFSR[j] = LFSR[j+1]; \
LFSR[15] = V; \
}
#define BitReconstruction2(X1,X2) \
X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >> 15); \
X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >> 15)
#define BitReconstruction3(X0,X1,X2) \
X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF); \
BitReconstruction2(X1,X2)
#define BitReconstruction4(X0,X1,X2,X3) \
BitReconstruction3(X0,X1,X2); \
X3 = ((LFSR[2] & 0xFFFF) << 16) | (LFSR[0] >> 15)
#define MAKEU32(a, b, c, d) \
(((uint32_t)(a) << 24) | \
((uint32_t)(b) << 16) | \
((uint32_t)(c) << 8) | \
((uint32_t)(d)))
#define ZUC256_MAKEU31(a,b,c,d) \
(((uint32_t)(a) << 23) | \
((uint32_t)(b) << 16) | \
((uint32_t)(c) << 8) | \
(uint32_t)(d)) & 0x7FFFFFFF /* 确保31位 */
// 辅助函数:字节序转换
static inline uint32_t GETU32(const uint8_t *p) {
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
((uint32_t)p[2] << 8) | (uint32_t)p[3];
}
static inline void PUTU32(uint8_t *p, uint32_t v) {
p[0] = (uint8_t)(v >> 24);
p[1] = (uint8_t)(v >> 16);
p[2] = (uint8_t)(v >> 8);
p[3] = (uint8_t)v;
}
static const ZUC_UINT7 ZUC256_D[][16] = {
{0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
};
static void zuc256_set_mac_key(ZUC_STATE *key, const uint8_t K[32],
const uint8_t IV[23], int macbits)
{
ZUC_UINT31 *LFSR = key->LFSR;
uint32_t R1, R2;
uint32_t X0, X1, X2;
uint32_t W, W1, W2, U, V;
const ZUC_UINT7 *D;
int i;
ZUC_UINT6 IV17 = IV[17] >> 2;
ZUC_UINT6 IV18 = ((IV[17] & 0x3) << 4) | (IV[18] >> 4);
ZUC_UINT6 IV19 = ((IV[18] & 0xf) << 2) | (IV[19] >> 6);
ZUC_UINT6 IV20 = IV[19] & 0x3f;
ZUC_UINT6 IV21 = IV[20] >> 2;
ZUC_UINT6 IV22 = ((IV[20] & 0x3) << 4) | (IV[21] >> 4);
ZUC_UINT6 IV23 = ((IV[21] & 0xf) << 2) | (IV[22] >> 6);
ZUC_UINT6 IV24 = IV[22] & 0x3f;
D = macbits/32 < 3 ? ZUC256_D[macbits/32] : ZUC256_D[3];
LFSR[0] = ZUC256_MAKEU31(K[0], D[0], K[21], K[16]);
LFSR[1] = ZUC256_MAKEU31(K[1], D[1], K[22], K[17]);
LFSR[2] = ZUC256_MAKEU31(K[2], D[2], K[23], K[18]);
LFSR[3] = ZUC256_MAKEU31(K[3], D[3], K[24], K[19]);
LFSR[4] = ZUC256_MAKEU31(K[4], D[4], K[25], K[20]);
LFSR[5] = ZUC256_MAKEU31(IV[0], (D[5] | IV17), K[5], K[26]);
LFSR[6] = ZUC256_MAKEU31(IV[1], (D[6] | IV18), K[6], K[27]);
LFSR[7] = ZUC256_MAKEU31(IV[10], (D[7] | IV19), K[7], IV[2]);
LFSR[8] = ZUC256_MAKEU31(K[8], (D[8] | IV20), IV[3], IV[11]);
LFSR[9] = ZUC256_MAKEU31(K[9], (D[9] | IV21), IV[12], IV[4]);
LFSR[10] = ZUC256_MAKEU31(IV[5], (D[10] | IV22), K[10], K[28]);
LFSR[11] = ZUC256_MAKEU31(K[11], (D[11] | IV23), IV[6], IV[13]);
LFSR[12] = ZUC256_MAKEU31(K[12], (D[12] | IV24), IV[7], IV[14]);
LFSR[13] = ZUC256_MAKEU31(K[13], D[13], IV[15], IV[8]);
LFSR[14] = ZUC256_MAKEU31(K[14], (D[14] | (K[31] >> 4)), IV[16], IV[9]);
LFSR[15] = ZUC256_MAKEU31(K[15], (D[15] | (K[31] & 0x0F)), K[30], K[29]);
R1 = 0;
R2 = 0;
for (i = 0; i < 32; i++) {
BitReconstruction3(X0, X1, X2);
W = F(X0, X1, X2);
LFSRWithInitialisationMode(W >> 1);
}
BitReconstruction2(X1, X2);
F_(X1, X2);
LFSRWithWorkMode();
key->R1 = R1;
key->R2 = R2;
}
// 初始化ZUC256状态
void zuc256_init(ZUC_STATE *key, const uint8_t K[32],
const uint8_t IV[23])
{
if (!key || !K || !IV) return;
zuc256_set_mac_key(key, K, IV, 0);
}
// 生成单个密钥字
uint32_t zuc256_generate_keyword(ZUC_STATE *state) {
ZUC_UINT31 *LFSR = state->LFSR;
uint32_t R1 = state->R1;
uint32_t R2 = state->R2;
uint32_t X0, X1, X2, X3;
uint32_t W1, W2, U, V;
uint32_t Z;
BitReconstruction4(X0, X1, X2, X3);
Z = X3 ^ F(X0, X1, X2);
LFSRWithWorkMode();
state->R1 = R1;
state->R2 = R2;
return Z;
}
void zuc256_generate_keystream(ZUC_STATE *state, size_t nwords, uint32_t *keystream) {
ZUC_UINT31 *LFSR = state->LFSR;
uint32_t R1 = state->R1;
uint32_t R2 = state->R2;
uint32_t X0, X1, X2, X3;
uint32_t W1, W2, U, V;
size_t i;
for (i = 0; i < nwords; i ++) {
/*
BitReconstruction4(X0, X1, X2, X3);
keystream[i] = X3 ^ F(X0, X1, X2);
LFSRWithWorkMode();
*/
uint32_t T0, T1, T2, T3, T4, T5, T6, T7;
uint64_t a;
int j;
// expand BitReconstruction4(X0, X1, X2, X3)
X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF);
X1 = ((LFSR[11] & 0x0000FFFF) << 16) | (LFSR[ 9] >> 15);
X2 = ((LFSR[ 7] & 0x0000FFFF) << 16) | (LFSR[ 5] >> 15);
X3 = ((LFSR[ 2] & 0x0000FFFF) << 16) | (LFSR[ 0] >> 15);
//keystream[i] = X3 ^ F(X0, X1, X2);
keystream[i] = X3 ^ ((X0 ^ R1) + R2);
W1 = R1 + X1;
W2 = R2 ^ X2;
U = L1((W1 << 16) | (W2 >> 16));
V = L2((W2 << 16) | (W1 >> 16));
// table lookup together makes 10% faster
T0 = S0[(U >> 24) ];
T2 = S0[(U >> 8) & 0xFF];
T4 = S0[(V >> 24) ];
T6 = S0[(V >> 8) & 0xFF];
T1 = S1[(U >> 16) & 0xFF];
T3 = S1[(U ) & 0xFF];
T5 = S1[(V >> 16) & 0xFF];
T7 = S1[(V ) & 0xFF];
R1 = MAKEU32(T0, T1, T2, T3);
R2 = MAKEU32(T4, T5, T6, T7);
// expand LFSRWithWorkMode()
a = LFSR[0];
a += ((uint64_t)LFSR[ 0]) << 8;
a += ((uint64_t)LFSR[ 4]) << 20;
a += ((uint64_t)LFSR[10]) << 21;
a += ((uint64_t)LFSR[13]) << 17;
a += ((uint64_t)LFSR[15]) << 15;
a = (a & 0x7fffffff) + (a >> 31);
V = (uint32_t)((a & 0x7fffffff) + (a >> 31));
for (j = 0; j < 15; j++) {
LFSR[j] = LFSR[j+1];
}
LFSR[15] = V;
}
state->R1 = R1;
state->R2 = R2;
}
// 初始化加密上下文
void zuc256_encrypt_init(ZUC256_ENCRYPT_CTX *ctx, const uint8_t K[32], const uint8_t IV[23]) {
if (!ctx) return;
memset(ctx, 0, sizeof(*ctx));
zuc256_init(&ctx->state, K, IV);
}
// 分阶段处理加密数据(支持流式输入)
void zuc256_encrypt_update(ZUC256_ENCRYPT_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out) {
if (!ctx || !in || !out || inlen == 0) return;
// 先处理缓冲区中剩余的非4字节数据
if (ctx->buflen > 0) {
size_t need = 4 - ctx->buflen;
size_t copy = (inlen < need) ? inlen : need;
memcpy(ctx->buf + ctx->buflen, in, copy);
ctx->buflen += copy;
in += copy;
inlen -= copy;
// 缓冲区已满处理一个完整的4字节块
if (ctx->buflen == 4) {
uint32_t keystream = zuc256_generate_keyword(&ctx->state);
uint32_t plain = GETU32(ctx->buf);
PUTU32(out, plain ^ keystream);
ctx->buflen = 0;
memset(ctx->buf, 0, 4); // 清空缓冲区
out += 4;
}
}
// 处理完整的4字节块
size_t full_blocks = inlen / 4;
if (full_blocks > 0) {
size_t keystream_len = full_blocks;
uint32_t *keystream = (uint32_t*)malloc(keystream_len * sizeof(uint32_t));
if (keystream) {
zuc256_generate_keystream(&ctx->state, keystream_len, keystream);
// 逐块异或加密
for (size_t i = 0; i < full_blocks; i++) {
uint32_t plain = GETU32(in + i*4);
PUTU32(out + i*4, plain ^ keystream[i]);
}
free(keystream);
in += full_blocks * 4;
inlen -= full_blocks * 4;
out += full_blocks * 4;
}
}
// 缓存剩余不足4字节的数据
if (inlen > 0) {
memcpy(ctx->buf, in, inlen);
ctx->buflen = inlen;
}
}
// 完成加密处理(处理剩余数据并清理上下文)
void zuc256_encrypt_finish(ZUC256_ENCRYPT_CTX *ctx, uint8_t *out) {
if (!ctx || !out) return;
// 处理缓冲区中剩余的不足4字节数据
if (ctx->buflen > 0) {
uint32_t keystream = zuc256_generate_keyword(&ctx->state);
uint8_t keystream_bytes[4];
PUTU32(keystream_bytes, keystream);
// 逐字节异或
for (size_t i = 0; i < ctx->buflen; i++) {
out[i] = ctx->buf[i] ^ keystream_bytes[i];
}
}
// 清理上下文(安全考虑)
memset(ctx, 0, sizeof(*ctx));
}
// 一次性加密函数(ZUC加密和解密相同)
void zuc256_crypt(ZUC_STATE *state, const uint8_t *in, size_t inlen, uint8_t *out) {
if (!state || !in || !out) return;
ZUC256_ENCRYPT_CTX ctx;
// 修复1:初始化ctx内存(仅清空不调用zuc256_encrypt_init)
memset(&ctx, 0, sizeof(ZUC256_ENCRYPT_CTX));
// 修复2:将传入的合法state复制到ctx->state复用已有状态(含K/IV对应的初始化结果)
memcpy(&ctx.state, state, sizeof(ZUC_STATE));
// 正常执行加解密(使用复用的state)
zuc256_encrypt_update(&ctx, in, inlen, out);
// 计算剩余数据的偏移:(inlen / 4)*4 是完整4字节块的长度剩余数据从这里开始
size_t remaining_offset = (inlen / 4) * 4;
zuc256_encrypt_finish(&ctx, out + remaining_offset);
// 修复3:将ctx->state的最新状态回写到传入的state(确保后续连续加解密的状态正确)
memcpy(state, &ctx.state, sizeof(ZUC_STATE));
}
void extract_iv(const uint8_t *input_25byte, uint8_t *output_23byte) {
if (!input_25byte || !output_23byte) return;
for (int i = 0; i < 17; i++) {
output_23byte[i] = input_25byte[i];
}
uint8_t src[8];
for (int i = 0; i < 8; i++) {
src[i] = input_25byte[17 + i] & 0x3F;
}
output_23byte[17] = (src[0] << 2) | (src[1] >> 4);
output_23byte[18] = ((src[1] & 0x0F) << 4) | (src[2] >> 2);
output_23byte[19] = ((src[2] & 0x03) << 6) | src[3];
output_23byte[20] = (src[4] << 2) | (src[5] >> 4);
output_23byte[21] = ((src[5] & 0x0F) << 4) | (src[6] >> 2);
output_23byte[22] = ((src[6] & 0x03) << 6) | src[7];
}
/**
* @brief 初始化ZUC256 MAC上下文
* @param ctx:MAC上下文指针(输出)
* @param key:256位密钥(32字节输入)
* @param iv:23字节初始向量(输入)
* @param macbits:期望MAC输出位数(32/64/128自动调整范围:<32→32>128→128)
*/
void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const uint8_t key[32],
const uint8_t iv[23], int macbits)
{
if (macbits < 32)
macbits = 32;
else if (macbits > 64)
macbits = 128;
memset(ctx, 0, sizeof(*ctx));
zuc256_set_mac_key((ZUC256_STATE *)ctx, key, iv, macbits);
zuc256_generate_keystream((ZUC256_STATE *)ctx, macbits/32, ctx->T);
zuc256_generate_keystream((ZUC256_STATE *)ctx, macbits/32, ctx->K0);
ctx->macbits = (macbits/32) * 32;
}
/**
* @brief 更新ZUC256 MAC待认证数据(支持分块输入)
* @param ctx:已初始化的MAC上下文(输入/输出)
* @param data:待认证数据块(输入可NULL)
* @param len:待认证数据长度(字节输入0则无操作)
*/
void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const uint8_t *data, size_t len)
{
ZUC_UINT32 K1, M;
size_t n = ctx->macbits / 32;
size_t i, j;
if (!data || !len) {
return;
}
if (ctx->buflen) {
size_t num = sizeof(ctx->buf) - ctx->buflen;
if (len < num) {
memcpy(ctx->buf + ctx->buflen, data, len);
ctx->buflen += len;
return;
}
memcpy(ctx->buf + ctx->buflen, data, num);
M = GETU32(ctx->buf);
ctx->buflen = 0;
K1 = zuc256_generate_keyword((ZUC_STATE *)ctx);
for (i = 0; i < 32; i++) {
if (M & 0x80000000) {
for (j = 0; j < n; j++) {
ctx->T[j] ^= ctx->K0[j];
}
}
M <<= 1;
for (j = 0; j < n - 1; j++) {
ctx->K0[j] = (ctx->K0[j] << 1) | (ctx->K0[j + 1] >> 31);
}
ctx->K0[j] = (ctx->K0[j] << 1) | (K1 >> 31);
K1 <<= 1;
}
data += num;
len -= num;
}
while (len >= 4) {
M = GETU32(data);
K1 = zuc256_generate_keyword((ZUC_STATE *)ctx);
for (i = 0; i < 32; i++) {
if (M & 0x80000000) {
for (j = 0; j < n; j++) {
ctx->T[j] ^= ctx->K0[j];
}
}
M <<= 1;
for (j = 0; j < n - 1; j++) {
ctx->K0[j] = (ctx->K0[j] << 1) | (ctx->K0[j + 1] >> 31);
}
ctx->K0[j] = (ctx->K0[j] << 1) | (K1 >> 31);
K1 <<= 1;
}
data += 4;
len -= 4;
}
if (len) {
memcpy(ctx->buf, data, len);
ctx->buflen = len;
}
}
/**
* @brief 完成ZUC256 MAC计算输出最终认证码
* @param ctx:已更新数据的MAC上下文(输入/输出,调用后清空)
* @param data:最后一块待认证数据(可NULL若需补充不足1字节的比特)
* @param nbits:最后一块数据的额外比特数(0~7仅当data非NULL时有效)
* @param mac:MAC输出缓冲区(需提前分配至少 ctx->macbits/8 字节空间)
*/
void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const uint8_t *data, size_t nbits, uint8_t *mac)
{
ZUC_UINT32 K1, M;
size_t n = ctx->macbits/32;
size_t i, j;
if (!data)
nbits = 0;
if (nbits >= 8) {
zuc256_mac_update(ctx, data, nbits/8);
data += nbits/8;
nbits %= 8;
}
if (nbits)
ctx->buf[ctx->buflen] = *data;
if (ctx->buflen || nbits) {
M = GETU32(ctx->buf);
K1 = zuc256_generate_keyword((ZUC_STATE *)ctx);
for (i = 0; i < ctx->buflen * 8 + nbits; i++) {
if (M & 0x80000000) {
for (j = 0; j < n; j++) {
ctx->T[j] ^= ctx->K0[j];
}
}
M <<= 1;
for (j = 0; j < n - 1; j++) {
ctx->K0[j] = (ctx->K0[j] << 1) | (ctx->K0[j + 1] >> 31);
}
ctx->K0[j] = (ctx->K0[j] << 1) | (K1 >> 31);
K1 <<= 1;
}
}
for (j = 0; j < n; j++) {
ctx->T[j] ^= ctx->K0[j];
PUTU32(mac, ctx->T[j]);
mac += 4;
}
memset(ctx, 0, sizeof(*ctx));
}
/**
* @brief 一次性ZUC256 MAC计算(简化接口,适用于非流式数据
* @param K:256位密钥(32字节输入)
* @param IV:23字节初始向量(输入)
* @param data:待认证数据(输入可NULL)
* @param len:待认证数据长度(字节,输入)
* @param macbits:MAC输出位数(32/64/128输入)
* @param mac:MAC输出缓冲区(输出,需提前分配空间)
*/
void zuc256_mac(const uint8_t K[32], const uint8_t IV[23], const uint8_t *data, size_t len, int macbits, uint8_t *mac) {
ZUC256_MAC_CTX ctx;
zuc256_mac_init(&ctx, K, IV, macbits);
if (data && len > 0) {
zuc256_mac_update(&ctx, data, len);
}
zuc256_mac_finish(&ctx, NULL, 0, mac);
}