You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
5.9 KiB
197 lines
5.9 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "sm4_core.h"
|
|
|
|
static void rk_left_shift(int len, unsigned char* add, unsigned char*des)
|
|
{
|
|
int i;
|
|
for (i = 0; i < len - 1; i++)
|
|
{
|
|
des[i] = (add[i] << 1) + (add[i + 1] >= 0x80?1:0);
|
|
}
|
|
des[len - 1] = add[len - 1] << 1;
|
|
}
|
|
|
|
static void rk_array_xor(int len, unsigned char*a1, unsigned char*a2, unsigned char*des)
|
|
{
|
|
int i;
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
des[i] = a1[i] ^ a2[i];
|
|
}
|
|
}
|
|
|
|
static void rk_derive_mac_key(sm4_context *key, unsigned char *k1, unsigned char *k2)
|
|
{
|
|
unsigned char plain[SM4_BLOCK_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
unsigned char Rb[SM4_BLOCK_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 };
|
|
unsigned char c0[SM4_BLOCK_SIZE];
|
|
|
|
rk_sm4_crypt_ecb(key, plain, c0);
|
|
if (c0[0]<0x80) //generate k1
|
|
{
|
|
rk_left_shift(SM4_BLOCK_SIZE, c0, k1);
|
|
}
|
|
else
|
|
{
|
|
rk_left_shift(SM4_BLOCK_SIZE, c0, k1);
|
|
rk_array_xor(SM4_BLOCK_SIZE, k1, Rb, k1);
|
|
}
|
|
|
|
if (k1[0] < 0x80) //generate k2
|
|
{
|
|
rk_left_shift(SM4_BLOCK_SIZE, k1, k2);
|
|
}
|
|
else
|
|
{
|
|
rk_left_shift(SM4_BLOCK_SIZE, k1, k2);
|
|
rk_array_xor(SM4_BLOCK_SIZE, k2, Rb, k2);
|
|
}
|
|
}
|
|
|
|
int rk_sm4_genarate_cmac(unsigned char *key, unsigned int key_len, unsigned char *msg, unsigned int msg_len, unsigned char *macvalue)
|
|
{
|
|
int i,block;
|
|
unsigned char IVtemp[SM4_BLOCK_SIZE];
|
|
unsigned char Blocktemp[SM4_BLOCK_SIZE];
|
|
unsigned char k1[SM4_BLOCK_SIZE], k2[SM4_BLOCK_SIZE];
|
|
sm4_context ctx;
|
|
|
|
memset(IVtemp, 0x00, sizeof(IVtemp));
|
|
memset(Blocktemp, 0x00, sizeof(Blocktemp));
|
|
memset(k1, 0x00, sizeof(k1));
|
|
memset(k2, 0x00, sizeof(k2));
|
|
|
|
rk_sm4_setkey_enc(&ctx, key);
|
|
|
|
rk_derive_mac_key(&ctx, k1, k2);
|
|
if (msg_len % SM4_BLOCK_SIZE == 0 && msg_len!=0)
|
|
{
|
|
block = msg_len / SM4_BLOCK_SIZE;
|
|
for (i = 0; i < block-1; i++)
|
|
{
|
|
rk_array_xor(16, &msg[i * SM4_BLOCK_SIZE], IVtemp, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, IVtemp);
|
|
}
|
|
rk_array_xor(16, &msg[(block-1)*SM4_BLOCK_SIZE], IVtemp, Blocktemp);
|
|
rk_array_xor(16, Blocktemp, k1, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, macvalue);
|
|
}
|
|
else
|
|
{
|
|
if (msg_len==0)
|
|
{
|
|
block = 1;
|
|
Blocktemp[0] = 0x80;//padding the first bit with 1
|
|
rk_array_xor(16, Blocktemp, k2, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, macvalue);
|
|
}
|
|
else
|
|
{
|
|
unsigned char remain = msg_len % SM4_BLOCK_SIZE;
|
|
block = msg_len / SM4_BLOCK_SIZE + 1;
|
|
for (i = 0; i < block - 1; i++)
|
|
{
|
|
rk_array_xor(SM4_BLOCK_SIZE, &msg[i * SM4_BLOCK_SIZE], IVtemp, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, IVtemp);
|
|
}
|
|
// the last block padding
|
|
for (i = 0; i < remain; i++)
|
|
{
|
|
Blocktemp[i] = msg[(block - 1) * SM4_BLOCK_SIZE + i];
|
|
}
|
|
Blocktemp[remain] = 0x80;
|
|
for (i = remain + 1; i < SM4_BLOCK_SIZE; i++)
|
|
{
|
|
Blocktemp[i] = 0;
|
|
}
|
|
// end of the last block padding
|
|
|
|
rk_array_xor(SM4_BLOCK_SIZE, Blocktemp, k2, Blocktemp);
|
|
rk_array_xor(SM4_BLOCK_SIZE, Blocktemp, IVtemp, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, macvalue);
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int rk_sm4_verify_cmac(unsigned char *key, unsigned int key_len, unsigned char *msg, unsigned int msg_len, unsigned char *macvalue)
|
|
{
|
|
int i, block;
|
|
int result=-1;
|
|
unsigned char IVtemp[SM4_BLOCK_SIZE];
|
|
unsigned char Blocktemp[SM4_BLOCK_SIZE];
|
|
unsigned char k1[SM4_BLOCK_SIZE], k2[SM4_BLOCK_SIZE];
|
|
unsigned char tmp_macvalue[SM4_BLOCK_SIZE];
|
|
sm4_context ctx;
|
|
|
|
memset(IVtemp, 0x00, sizeof(IVtemp));
|
|
memset(Blocktemp, 0x00, sizeof(Blocktemp));
|
|
memset(k1, 0x00, sizeof(k1));
|
|
memset(k2, 0x00, sizeof(k2));
|
|
|
|
rk_sm4_setkey_enc(&ctx, key);
|
|
|
|
rk_derive_mac_key(&ctx, k1, k2);
|
|
if (msg_len % SM4_BLOCK_SIZE == 0 && msg_len != 0)
|
|
{
|
|
block = msg_len / SM4_BLOCK_SIZE;
|
|
for (i = 0; i < block - 1; i++)
|
|
{
|
|
rk_array_xor(SM4_BLOCK_SIZE, &msg[i * SM4_BLOCK_SIZE], IVtemp, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, IVtemp);
|
|
}
|
|
rk_array_xor(SM4_BLOCK_SIZE, &msg[(block - 1) * SM4_BLOCK_SIZE], IVtemp, Blocktemp);
|
|
rk_array_xor(SM4_BLOCK_SIZE, Blocktemp, k1, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, tmp_macvalue);
|
|
}
|
|
else
|
|
{
|
|
if (msg_len == 0)
|
|
{
|
|
block = 1;
|
|
Blocktemp[0] = 0x80;//padding the first bit with 1
|
|
rk_array_xor(SM4_BLOCK_SIZE, Blocktemp, k2, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, tmp_macvalue);
|
|
}
|
|
else
|
|
{
|
|
unsigned char remain = msg_len % SM4_BLOCK_SIZE;
|
|
block = msg_len / SM4_BLOCK_SIZE + 1;
|
|
for (i = 0; i < block - 1; i++)
|
|
{
|
|
rk_array_xor(SM4_BLOCK_SIZE, &msg[i * SM4_BLOCK_SIZE], IVtemp, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, IVtemp);
|
|
}
|
|
// the last block padding
|
|
for (i = 0; i < remain; i++)
|
|
{
|
|
Blocktemp[i] = msg[(block - 1) * SM4_BLOCK_SIZE + i];
|
|
}
|
|
Blocktemp[remain] = 0x80;
|
|
for (i = remain + 1; i < SM4_BLOCK_SIZE; i++)
|
|
{
|
|
Blocktemp[i] = 0;
|
|
}
|
|
// end of the last block padding
|
|
|
|
rk_array_xor(SM4_BLOCK_SIZE, Blocktemp, k2, Blocktemp);
|
|
rk_array_xor(SM4_BLOCK_SIZE, Blocktemp, IVtemp, Blocktemp);
|
|
rk_sm4_crypt_ecb(&ctx, Blocktemp, tmp_macvalue);
|
|
}
|
|
|
|
}
|
|
result = -1;
|
|
for (i = 0; i < SM4_BLOCK_SIZE; i++)
|
|
{
|
|
if (tmp_macvalue[i] != macvalue[i])
|
|
{
|
|
return(result);
|
|
}
|
|
}
|
|
result = 0;
|
|
return(result);
|
|
}
|