STM32上可用的的SM 2 3 4国密算法

可在STM32上使用的国密算法 SM 2 3 4


下面直接给出代码,有问题可评论,自己改动的,测试不到的地方可能有bug,欢迎指正。

SM2

由于SM2算法牵扯到一些较为复杂的数理计算,需要依靠数学运算库,在嵌入式设备上实现得到方法主要有两种:移植openssl或miracl库,再者就是使用硬件的加密芯片。
我使用的是移植了miracl库来实现,编译所需文件为lib库,在工程中引用。下面贴出主要代码:
sm2.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "miracl.h"
#include "sm2.h"
#include "sm3.h"
#include "global_variable.h" //这个头文件用于提供在滴答计时器中我的一个全局计数变量sysTick给
                            //irand使用产生随机数
 
#define SM2_PAD_ZERO TRUE
//#define SM2_PAD_ZERO FALSE
 
 
#define SM2_DEBUG   0
/*
#define QBITS 256
#define PBITS 3072
#define MAX_ECC_KEY_LEN		256
#define MAX_ECC_KEY_SIZE	(MAX_ECC_KEY_LEN/8)
*/
 
struct FPECC{
char *p;
char *a;
char *b;
char *n;
char *x;
char *y;
};
 
 
void PrintBuf(unsigned char *buf, int	buflen)
{
	int i;
	printf("\r\n");
	printf("len = %d\r\n", buflen);
	for(i=0; i<buflen; i++) {
  	if (i % 32 != 31)
  	  printf("%02x", buf[i]);
  	  else
  	  printf("%02x\r\n", buf[i]);
  }
  printf("\r\n");
  return;
}
 
void Printch(unsigned char *buf, int	buflen)
{
	int i;
	for (i = 0; i < buflen; i++) {
		if (i % 32 != 31)
			printf("%c", buf[i]);
		else
			printf("%c\n", buf[i]);
	}
	printf("\n");
	//return 0;
}
#if SM2_DEBUG
 
void PrintBig(big data)
{
 int len=0;
 unsigned char buf[10240];
 
 len=big_to_bytes(0,data,(char *)buf,0);
 PrintBuf(buf,len);
}
 
unsigned char radom[]  = {0x6C,0xB2,0x8D,0x99,0x38,0x5C,0x17,0x5C,0x94,0xF9,0x4E,0x93,0x48,0x17,0x66,0x3F,0xC1,0x76,0xD9,0x25,0xDD,0x72,0xB7,0x27,0x26,0x0D,0xBA,0xAE,0x1F,0xB2,0xF9,0x6F};
unsigned char radom1[] = {0x4C,0x62,0xEE,0xFD,0x6E,0xCF,0xC2,0xB9,0x5B,0x92,0xFD,0x6C,0x3D,0x95,0x75,0x14,0x8A,0xFA,0x17,0x42,0x55,0x46,0xD4,0x90,0x18,0xE5,0x38,0x8D,0x49,0xDD,0x7B,0x4F};
unsigned char randkey[] = {0x83,0xA2,0xC9,0xC8,0xB9,0x6E,0x5A,0xF7,0x0B,0xD4,0x80,0xB4,0x72,0x40,0x9A,0x9A,0x32,0x72,0x57,0xF1,0xEB,0xB7,0x3F,0x5B,0x07,0x33,0x54,0xB2,0x48,0x66,0x85,0x63};
unsigned char randkeyb[]= {0x33,0xFE,0x21,0x94,0x03,0x42,0x16,0x1C,0x55,0x61,0x9C,0x4A,0x0C,0x06,0x02,0x93,0xD5,0x43,0xC8,0x0A,0xF1,0x97,0x48,0xCE,0x17,0x6D,0x83,0x47,0x7D,0xE7,0x1C,0x80};
 
struct FPECC Ecc256={
"8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3",
"787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498",
"63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A",
"8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7",
"421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D",
"0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2",
};
unsigned char sm2_par_dig[128] = {
0x78,0x79,0x68,0xB4,0xFA,0x32,0xC3,0xFD,0x24,0x17,0x84,0x2E,0x73,0xBB,0xFE,0xFF,
0x2F,0x3C,0x84,0x8B,0x68,0x31,0xD7,0xE0,0xEC,0x65,0x22,0x8B,0x39,0x37,0xE4,0x98,
0x63,0xE4,0xC6,0xD3,0xB2,0x3B,0x0C,0x84,0x9C,0xF8,0x42,0x41,0x48,0x4B,0xFE,0x48,
0xF6,0x1D,0x59,0xA5,0xB1,0x6B,0xA0,0x6E,0x6E,0x12,0xD1,0xDA,0x27,0xC5,0x24,0x9A,
0x42,0x1D,0xEB,0xD6,0x1B,0x62,0xEA,0xB6,0x74,0x64,0x34,0xEB,0xC3,0xCC,0x31,0x5E,
0x32,0x22,0x0B,0x3B,0xAD,0xD5,0x0B,0xDC,0x4C,0x4E,0x6C,0x14,0x7F,0xED,0xD4,0x3D,
0x06,0x80,0x51,0x2B,0xCB,0xB4,0x2C,0x07,0xD4,0x73,0x49,0xD2,0x15,0x3B,0x70,0xC4,
0xE5,0xD7,0xFD,0xFC,0xBF,0xA3,0x6E,0xA1,0xA8,0x58,0x41,0xB9,0xE4,0x6E,0x09,0xA2,
};
 
#else
/*SM2*/
struct FPECC Ecc256={
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
};

unsigned char sm2_par_dig[128] = {
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,
0x28,0xE9,0xFA,0x9E,0x9D,0x9F,0x5E,0x34,0x4D,0x5A,0x9E,0x4B,0xCF,0x65,0x09,0xA7,
0xF3,0x97,0x89,0xF5,0x15,0xAB,0x8F,0x92,0xDD,0xBC,0xBD,0x41,0x4D,0x94,0x0E,0x93,
0x32,0xC4,0xAE,0x2C,0x1F,0x19,0x81,0x19,0x5F,0x99,0x04,0x46,0x6A,0x39,0xC9,0x94,
0x8F,0xE3,0x0B,0xBF,0xF2,0x66,0x0B,0xE1,0x71,0x5A,0x45,0x89,0x33,0x4C,0x74,0xC7,
0xBC,0x37,0x36,0xA2,0xF4,0xF6,0x77,0x9C,0x59,0xBD,0xCE,0xE3,0x6B,0x69,0x21,0x53,
0xD0,0xA9,0x87,0x7C,0xC6,0x2A,0x47,0x40,0x02,0xDF,0x32,0xE5,0x21,0x39,0xF0,0xA0,
};
 
unsigned char enkey[32] = {
0xB1,0x6B,0xA0,0xDA,0x27,0xC5,0x24,0x9A,0xF6,0x1D,0x6E,0x6E,0x12,0xD1,0x59,0xA5,
0xB6,0x74,0x64,0x34,0xEB,0xD6,0x1B,0x62,0xEA,0xEB,0xC3,0xCC,0x31,0x5E,0x42,0x1D,
};
#endif
 
 
#define SEED_CONST 0x1BD8C95A

/**
	* @brief 生成SM2公私钥对
	* @param wx:         公钥的X坐标,不足32字节在前面加0x00
	* @param wxlen:       wx的字节数,32
	* @param wy:         公钥的Y坐标,不足32字节在前面加0x00
	* @param wylen:       wy的字节数,32
	* @param privkey:    私钥,不足32字节在前面加0x00
	* @param privkeylen: privkey的字节数,32
  * @retval void
  */
void sm2_keygen(unsigned char *wx, int *wxlen, unsigned char *wy, \
	              int *wylen, unsigned char *privkey, int *privkeylen)
{
	struct FPECC *cfig = &Ecc256;
	epoint *g;
	big a,b,p,n,x,y,key1;
	
	miracl instance;
	miracl *mip = &instance;

	char mem[MR_BIG_RESERVE(7)];
	memset(mem, 0, MR_BIG_RESERVE(7));
	
	mip = mirsys(mip, 20, 0);   /* Use Hex Internally */
	mip->IOBASE = 16;

	p = mirvar_mem(mip, mem, 0);
	a = mirvar_mem(mip, mem, 1);
	b = mirvar_mem(mip, mem, 2);
	n = mirvar_mem(mip, mem, 3);
	x = mirvar_mem(mip, mem, 4);
	y = mirvar_mem(mip, mem, 5);
	key1 = mirvar_mem(mip, mem, 6);

	cinstr(mip, p, cfig->p);
	cinstr(mip, a, cfig->a);
	cinstr(mip, b, cfig->b);
	cinstr(mip, n, cfig->n);
	cinstr(mip, x, cfig->x);
	cinstr(mip, y, cfig->y);

	ecurve_init(mip, a, b, p, MR_PROJECTIVE);

	char mem1[MR_ECP_RESERVE(1)]; 
	memset(mem1 ,0, MR_ECP_RESERVE(1));
	
  g = epoint_init_mem(mip, mem1, 0);
	epoint_set(mip, x, y, 0, g);
	
	irand(mip, sysTick);
	
	/* generate public/private keys */
	bigrand(mip, n, key1);
	
	ecurve_mult(mip, key1,g,g);
	epoint_get(mip, g,x,y); /* compress point */
	
	*wxlen = big_to_bytes(mip, 32, x, (char *)wx, TRUE);
	*wylen = big_to_bytes(mip, 32, y, (char *)wy, TRUE);
	*privkeylen = big_to_bytes(mip, 32, key1, (char *)privkey, TRUE);

	/* clear all memory used */
  memset(mem,0,MR_BIG_RESERVE(7));
  memset(mem1,0,MR_ECP_RESERVE(1));
	mirexit(mip);
}

/**
  * @brief  密钥派生函数
  * @param  zl  要处理的数据——list(x)
  * @param  zr  要处理的数据——row(y)
  * @param  keylen  需要派生得到的长度
  * @param  kbuf    计算后返回的内容(二进制值),分配空间至少为需要keylen
  * @retval 0:成功 其他失败
  */
int kdf(unsigned char *zl, unsigned char *zr, int klen, unsigned char *kbuf)
{

	unsigned char buf[70];
	unsigned char digest[32];
	unsigned int ct = 0x00000001; //初始化一个32比特构成的计数器ct=0x00000001
	int i, m, n;
	unsigned char *p;
	
	memcpy(buf, zl, 32);
	memcpy(buf+32, zr, 32);
	m = klen / 32;
	n = klen % 32;
	p = kbuf;
	for(i = 0; i < m; i++)
	{
		buf[64] = (ct >> 24) & 0xFF;
		buf[65] = (ct >> 16) & 0xFF;
		buf[66] = (ct >> 8) & 0xFF;
		buf[67] = ct & 0xFF;
		SM3Calc(buf, 68, p);
		p += 32;
		ct++;
	}
	
	if(n != 0)
	{
		buf[64] = (ct >> 24) & 0xFF;
		buf[65] = (ct >> 16) & 0xFF;
		buf[66] = (ct >> 8) & 0xFF;
		buf[67] = ct & 0xFF;
		SM3Calc(buf, 68, digest);
	}
	
	memcpy(p, digest, n);

	for(i = 0; i < klen; i++)
	{
		if(kbuf[i] != 0)
			break;
	}
 
	if(i < klen)
		return 1;
	else
		return 0;
}

/**
  * @brief  SM2加密
  * @param  msg:    要加密的明文数据
  * @param  msglen: 明文数据长度
  * @param  wx:     公钥的x坐标
  * @param  wxlen:  公钥的x坐标长度,不超过32
  * @param  wy:     公钥的y坐标
  * @param  wylen:  公钥的y坐标长度,不超过32
  * @param  outmsg: 加密后密文 长度为明文 + 96
  * @retval -1:失败 msglen + 96:成功
  */
int sm2_encrypt(unsigned char *msg,int msglen, unsigned char *wx,int wxlen, \
	              unsigned char *wy,int wylen, unsigned char *outmsg)
{
 
	struct FPECC *cfig = &Ecc256;
	big x2, y2, c1, c2, k;
	big a,b,p,n,x,y;
	epoint *g, *w;
	int ret = -1;
	int i;
	unsigned char zl[32], zr[32];
	unsigned char *tmp;
	
	miracl instance;
  miracl *mip = &instance;

	tmp = malloc(msglen+64);
	if(tmp == NULL)
		return -1;
	
	mip = mirsys(mip, 20, 0);   /* Use Hex Internally */
	mip->IOBASE = 16;
	
	char mem[MR_BIG_RESERVE(11)];
  memset(mem, 0, MR_BIG_RESERVE(11));
	
	p= mirvar_mem(mip, mem, 0);
	a=mirvar_mem(mip, mem, 1);
	b=mirvar_mem(mip, mem, 2);
	n=mirvar_mem(mip, mem, 3);
	x=mirvar_mem(mip, mem, 4);
	y=mirvar_mem(mip, mem, 5);
	k=mirvar_mem(mip, mem, 6);
	x2=mirvar_mem(mip, mem, 7);
	y2=mirvar_mem(mip, mem, 8);
	c1=mirvar_mem(mip, mem, 9);
	c2=mirvar_mem(mip, mem, 10);
	
	cinstr(mip, p,cfig->p);
	cinstr(mip, a,cfig->a);
	cinstr(mip, b,cfig->b);
	cinstr(mip, n,cfig->n);
	cinstr(mip, x,cfig->x);
	cinstr(mip, y,cfig->y);
	
	ecurve_init(mip, a,b,p,MR_PROJECTIVE);

	char mem1[MR_ECP_RESERVE(2)]; 
	memset(mem1 ,0, MR_ECP_RESERVE(2));

	g = epoint_init_mem(mip, mem1,0);
	w = epoint_init_mem(mip, mem1,1);
	 
  epoint_set(mip, x,y,0,g);
	bytes_to_big(mip, wxlen,(char *)wx,x);
	bytes_to_big(mip, wylen,(char *)wy,y);
	epoint_set(mip, x,y,0,w);
	
	irand(mip, sysTick);
sm2_encrypt_again:
#if SM2_DEBUG
	bytes_to_big(32, (char *)radom1, k);
#else
	do
	{
		bigrand(mip, n, k);
	} 
	while (k->len == 0);
#endif
	ecurve_mult(mip, k, g, g);
	epoint_get(mip, g, c1, c2);
	big_to_bytes(mip, 32, c1, (char *)outmsg, TRUE);
	big_to_bytes(mip, 32, c2, (char *)outmsg+32, TRUE);
	//计算椭圆曲线点C1
	if(point_at_infinity(w))
		goto exit_sm2_encrypt;
	//计算椭圆曲线点S
	ecurve_mult(mip, k, w, w);
	epoint_get(mip, w, x2, y2);
	big_to_bytes(mip, 32, x2, (char *)zl, TRUE);
	big_to_bytes(mip, 32, y2, (char *)zr, TRUE);
	//计算椭圆曲线点[k]PB
	if (kdf(zl, zr, msglen, outmsg+64) == 0)
		goto sm2_encrypt_again;
	//计算t = KDF,如果t全零,返回A1
	for(i = 0; i < msglen; i++)
	{
		outmsg[64+i] ^= msg[i];
	}
	//计算C2
	memcpy(tmp, zl, 32);
	memcpy(tmp+32, msg, msglen);
	memcpy(tmp+32+msglen, zr, 32);
	SM3Calc(tmp, 64+msglen, &outmsg[64+msglen]);
	//计算C3
	ret = msglen+64+32;
	
exit_sm2_encrypt:

	memset(mem,0,MR_BIG_RESERVE(11));
	memset(mem1,0,MR_ECP_RESERVE(2));
	mirexit(mip);
	free(tmp);
	return ret;
}
 
/**
* @brief  SM2解密
* @param  msg:        要解密的密文数据
* @param  msglen:     密文数据长度
* @param  privkey:    私钥
* @param  privkeylen: 私钥长度
* @param  outmsg: 解密后的明文 长度为明文 - 96
* @retval -1:失败 msglen - 96:成功
*/
int sm2_decrypt(unsigned char *msg,int msglen, unsigned char *privkey, \
	              int privkeylen, unsigned char *outmsg)
{
 
	struct FPECC *cfig = &Ecc256;
	big x2, y2, c, k;
	big a,b,p,n,x,y,key1;
	epoint *g;
	unsigned char c3[32];
	unsigned char zl[32], zr[32];
	int i, ret = -1;
	unsigned char *tmp;
	
	miracl instance;
	miracl *mip = &instance;
	
	if(msglen < 96)
		return 0;
	msglen -= 96;
	tmp = malloc(msglen+64);
	if(tmp == NULL)
		return 0;
	
	mip = mirsys(mip, 20, 0);   /* Use Hex Internally */
	mip->IOBASE = 16;
 
	char mem[MR_BIG_RESERVE(11)];
  memset(mem, 0, MR_BIG_RESERVE(11));
 
	x2 = mirvar_mem(mip, mem, 0);
	y2 = mirvar_mem(mip, mem, 1);
	c = mirvar_mem(mip, mem, 2);
	k = mirvar_mem(mip, mem, 3);
	p = mirvar_mem(mip, mem, 4);
	a = mirvar_mem(mip, mem, 5);
	b = mirvar_mem(mip, mem, 6);
	n = mirvar_mem(mip, mem, 7);
	x = mirvar_mem(mip, mem, 8);
	y = mirvar_mem(mip, mem, 9);
	key1 = mirvar_mem(mip, mem, 10);
	
	bytes_to_big(mip, privkeylen,(char *)privkey,key1);
	
	cinstr(mip, p,cfig->p);
	cinstr(mip, a,cfig->a);
	cinstr(mip, b,cfig->b);
	cinstr(mip, n,cfig->n);
	cinstr(mip, x,cfig->x);
	cinstr(mip, y,cfig->y);
	
	ecurve_init(mip, a,b,p,MR_PROJECTIVE);

	char mem1[MR_ECP_RESERVE(1)]; 
	memset(mem1 ,0, MR_ECP_RESERVE(1));

	g = epoint_init_mem(mip, mem1,0);

	bytes_to_big(mip, 32, (char *)msg, x);
	bytes_to_big(mip, 32, (char *)msg+32, y);
	
  if(!epoint_set(mip, x,y,0,g))
		goto exit_sm2_decrypt;  //检验是否为椭圆曲线
	if(point_at_infinity(g))
		goto exit_sm2_decrypt;  //计算S
	
	ecurve_mult(mip, key1, g, g);
	epoint_get(mip, g, x2, y2);	
	
	big_to_bytes(mip, 32, x2, (char *)zl, TRUE);
	big_to_bytes(mip, 32, y2, (char *)zr, TRUE); //计算[db]c1
	
	if (kdf(zl, zr, msglen, outmsg) == 0)
		goto exit_sm2_decrypt;    //计算t
	
	for(i = 0; i < msglen; i++)
	{
		outmsg[i] ^= msg[i+64];
	}   //计算M到outsmg
	
	memcpy(tmp, zl, 32);
	memcpy(tmp+32, outmsg, msglen);
	memcpy(tmp+32+msglen, zr, 32);
	
	SM3Calc(tmp, 64+msglen, c3);//计算u
	if(memcmp(c3, msg+64+msglen, 32) != 0)
	{
		goto exit_sm2_decrypt;
	}
	
	ret =  msglen;
exit_sm2_decrypt:
	memset(mem,0,MR_BIG_RESERVE(11));
	memset(mem1,0,MR_ECP_RESERVE(1));
	mirexit(mip);
	free(tmp);
	return ret;
}

int sm2_encrypt_test(void)
{	
	unsigned char dB[] = { 0x16,0x49,0xAB,0x77,0xA0,0x06,0x37,0xBD,0x5E,0x2E,0xFE,0x28,0x3F,0xBF,0x35,0x35,0x34,0xAA,0x7F,0x7C,0xB8,0x94,0x63,0xF2,0x08,0xDD,0xBC,0x29,0x20,0xBB,0x0D,0xA0 };
	unsigned char xB[] = { 0x43,0x5B,0x39,0xCC,0xA8,0xF3,0xB5,0x08,0xC1,0x48,0x8A,0xFC,0x67,0xBE,0x49,0x1A,0x0F,0x7B,0xA0,0x7E,0x58,0x1A,0x0E,0x48,0x49,0xA5,0xCF,0x70,0x62,0x8A,0x7E,0x0A };
	unsigned char yB[] = { 0x75,0xDD,0xBA,0x78,0xF1,0x5F,0xEE,0xCB,0x4C,0x78,0x95,0xE2,0xC1,0xCD,0xF5,0xFE,0x01,0xDE,0xBB,0x2C,0xDB,0xAD,0xF4,0x53,0x99,0xCC,0xF7,0x7B,0xBA,0x07,0x6A,0x42 };
	unsigned char tx[25] = {0x16,0x49,0xAB,0x77,0xA0,0x06,0x37,0xBD,0x5E,0x2E,0x16,0x49,0xAB,0x77,0xA0,0x06,0x37,0xBD,0x5E,0x2E};
	unsigned char etx[256];
	unsigned char mtx[256];
	int wxlen, wylen, privkeylen,len,ret;

	sm2_keygen(xB, &wxlen, yB, &wylen, dB, &privkeylen);
	printf("dB: ");
	PrintBuf(dB, 32);
	printf("xB: ");
	PrintBuf(xB, 32);
	printf("yB: ");
	PrintBuf(yB, 32);

	len = 20;
		
	printf("\n``````````````````before encrypt```````````````````\n");
	PrintBuf(tx, len);

	printf("\n``````````````````this is encrypt```````````````````\n");
	sm2_encrypt(tx,len,xB,32,yB,32,etx);
	PrintBuf(etx, 64 +len + 32);

	printf("\n``````````````````this is decrypt```````````````````\n");
	ret = sm2_decrypt(etx,64+len+32,dB,32,mtx);
	if( ret < 0)
		printf("sm2_decrypt error!\n");
	else
	{
		PrintBuf(mtx, len);
	}	
 
	return 0;
}
int sm2_encrypt_test(void)
{	
	unsigned char dB[] = { 0x16,0x49,0xAB,0x77,0xA0,0x06,0x37,0xBD,0x5E,0x2E,0xFE,0x28,0x3F,0xBF,0x35,0x35,0x34,0xAA,0x7F,0x7C,0xB8,0x94,0x63,0xF2,0x08,0xDD,0xBC,0x29,0x20,0xBB,0x0D,0xA0 };
	unsigned char xB[] = { 0x43,0x5B,0x39,0xCC,0xA8,0xF3,0xB5,0x08,0xC1,0x48,0x8A,0xFC,0x67,0xBE,0x49,0x1A,0x0F,0x7B,0xA0,0x7E,0x58,0x1A,0x0E,0x48,0x49,0xA5,0xCF,0x70,0x62,0x8A,0x7E,0x0A };
	unsigned char yB[] = { 0x75,0xDD,0xBA,0x78,0xF1,0x5F,0xEE,0xCB,0x4C,0x78,0x95,0xE2,0xC1,0xCD,0xF5,0xFE,0x01,0xDE,0xBB,0x2C,0xDB,0xAD,0xF4,0x53,0x99,0xCC,0xF7,0x7B,0xBA,0x07,0x6A,0x42 };
	unsigned char tx[25] = {0x16,0x49,0xAB,0x77,0xA0,0x06,0x37,0xBD,0x5E,0x2E,0x16,0x49,0xAB,0x77,0xA0,0x06,0x37,0xBD,0x5E,0x2E};
	unsigned char etx[256];
	unsigned char mtx[256];
	int wxlen, wylen, privkeylen,len,ret;

	sm2_keygen(xB, &wxlen, yB, &wylen, dB, &privkeylen);
	printf("dB: ");
	PrintBuf(dB, 32);
	printf("xB: ");
	PrintBuf(xB, 32);
	printf("yB: ");
	PrintBuf(yB, 32);

	len = 20;
		
	printf("\n``````````````````before encrypt```````````````````\n");
	PrintBuf(tx, len);

	printf("\n``````````````````this is encrypt```````````````````\n");
	sm2_encrypt(tx,len,xB,32,yB,32,etx);
	PrintBuf(etx, 64 +len + 32);

	printf("\n``````````````````this is decrypt```````````````````\n");
	ret = sm2_decrypt(etx,64+len+32,dB,32,mtx);
	if( ret < 0)
		printf("sm2_decrypt error!\n");
	else
	{
		PrintBuf(mtx, len);
	}	
 
	return 0;
}

很重要的头文件:mirdef.h 用于编译产生适合于stm32的lib库

/* 
 *   MIRACL compiler/hardware definitions - mirdef.h
 *   This version suitable for use with most 32-bit computers
 *   e.g. 80386+ PC, VAX, ARM etc. Assembly language versions of muldiv,
 *   muldvm, muldvd and muldvd2 will be necessary. See mrmuldv.any 
 *
 *   Also suitable for DJGPP GNU C Compiler
 *   ... but change __int64 to long long
 */


/*
 *   MIRACL compiler/hardware definitions - mirdef.h
 */


#define MIRACL 32
#define MR_LITTLE_ENDIAN      

/* or possibly 
#define MR_BIG_ENDIAN      
*/

#define mr_utype int
#define MR_IBITS 32
#define mr_dltype __int64
#define mr_unsign32 unsigned int
#define mr_unsign64 unsigned __int64
#define MAXBASE ((mr_small)1<<(MIRACL-1))
#define MR_STATIC 20
#define MR_GENERIC_MT
#define MR_NOASM

其中关于sm3的算法SM3Calc()在sm3部分给出。
和其他平台的区别可行比较琢磨。
给出直接编译好的lib库:https://download.csdn.net/download/weixin_44522056/12483974

SM3

直接给出代码,和其他平台的区别自行比较学习
sm3.c

/*
* sm3.c
*/
#include <stdio.h>
#include "string.h"
#include "sm3.h"
 
/*
* 判断运行环境是否为小端
*/
static const int endianTest = 1;
#define IsLittleEndian() (*(char *)&endianTest == 1)
 
/*
* 向左循环移位
*/
//#define LeftRotate(word, bits) ( (word) << (bits) | (word) >> (32 - (bits)) )
 
#define SHL(x,n) (((x) & 0xFFFFFFFF) << n%32)
#define LeftRotate(x,n) (SHL((x),n) | ((x) >> (32 - n%32)))
/*
* 反转四字节整型字节序
*/
unsigned int *ReverseWord(unsigned int *word)
{
	unsigned char *byte, temp;
 
	byte = (unsigned char *)word;
	temp = byte[0];
	byte[0] = byte[3];
	byte[3] = temp;
 
	temp = byte[1];
	byte[1] = byte[2];
	byte[2] = temp;
	return word;
}
 
/*
* T
*/
unsigned int T(int i)
{
	if (i >= 0 && i <= 15)
		return 0x79CC4519;
	else if (i >= 16 && i <= 63)
		return 0x7A879D8A;
	else
		return 0;
}
 
/*
* FF
*/
unsigned int FF(unsigned int X, unsigned int Y, unsigned int Z, int i)
{
	if (i >= 0 && i <= 15)
		return X ^ Y ^ Z;
	else if (i >= 16 && i <= 63)
		return (X & Y) | (X & Z) | (Y & Z);
	else
		return 0;
}
 
/*
* GG
*/
unsigned int GG(unsigned int X, unsigned int Y, unsigned int Z, int i)
{
	if (i >= 0 && i <= 15)
		return X ^ Y ^ Z;
	else if (i >= 16 && i <= 63)
		return (X & Y) | (~X & Z);
	else
		return 0;
}
 
/*
* P0
*/
unsigned int P0(unsigned int X)
{
	return X ^ LeftRotate(X, 9) ^ LeftRotate(X, 17);
}
 
/*
* P1
*/
unsigned int P1(unsigned int X)
{
	return X ^ LeftRotate(X, 15) ^ LeftRotate(X, 23);
}
 
/*
* 初始化函数
*/
void SM3Init(SM3Context *context)
{
	context->intermediateHash[0] = 0x7380166F;
	context->intermediateHash[1] = 0x4914B2B9;
	context->intermediateHash[2] = 0x172442D7;
	context->intermediateHash[3] = 0xDA8A0600;
	context->intermediateHash[4] = 0xA96F30BC;
	context->intermediateHash[5] = 0x163138AA;
	context->intermediateHash[6] = 0xE38DEE4D;
	context->intermediateHash[7] = 0xB0FB0E4E;
}
 
/*
* 处理消息块
*/
void SM3ProcessMessageBlock(SM3Context *context)
{
	int i;
	unsigned int W[68];
	unsigned int W_[64];
	unsigned int A, B, C, D, E, F, G, H, SS1, SS2, TT1, TT2;
 
	/* 消息扩展 */
	for (i = 0; i < 16; i++)
	{
		W[i] = *(unsigned int *)(context->messageBlock + i * 4);
		if (IsLittleEndian())
			ReverseWord(W + i);
		//printf("%d: %x\n", i, W[i]);    
	}
	for (i = 16; i < 68; i++)
	{
		W[i] = P1(W[i - 16] ^ W[i - 9] ^ LeftRotate(W[i - 3], 15))
			^ LeftRotate(W[i - 13], 7)
			^ W[i - 6];
		//printf("%d: %x\n", i, W[i]);    
	}
	for (i = 0; i < 64; i++)
	{
		W_[i] = W[i] ^ W[i + 4];
		//printf("%d: %x\n", i, W_[i]);    
	}
 
	/* 消息压缩 */
	A = context->intermediateHash[0];
	B = context->intermediateHash[1];
	C = context->intermediateHash[2];
	D = context->intermediateHash[3];
	E = context->intermediateHash[4];
	F = context->intermediateHash[5];
	G = context->intermediateHash[6];
	H = context->intermediateHash[7];
	for (i = 0; i < 64; i++)
	{
		SS1 = LeftRotate((LeftRotate(A, 12) + E + LeftRotate(T(i), i)), 7);
		SS2 = SS1 ^ LeftRotate(A, 12);
		TT1 = FF(A, B, C, i) + D + SS2 + W_[i];
		TT2 = GG(E, F, G, i) + H + SS1 + W[i];
		D = C;
		C = LeftRotate(B, 9);
		B = A;
		A = TT1;
		H = G;
		G = LeftRotate(F, 19);
		F = E;
		E = P0(TT2);
	}
	context->intermediateHash[0] ^= A;
	context->intermediateHash[1] ^= B;
	context->intermediateHash[2] ^= C;
	context->intermediateHash[3] ^= D;
	context->intermediateHash[4] ^= E;
	context->intermediateHash[5] ^= F;
	context->intermediateHash[6] ^= G;
	context->intermediateHash[7] ^= H;
}
 
/*
* SM3算法主函数
*/
unsigned char *SM3Calc(const unsigned char *message,
	unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE])
{
	SM3Context context;
	unsigned int i, remainder, bitLen;
 
	/* 初始化上下文 */
	SM3Init(&context);
 
	/* 对前面的消息分组进行处理 */
	for (i = 0; i < messageLen / 64; i++)
	{
		memcpy(context.messageBlock, message + i * 64, 64);
		SM3ProcessMessageBlock(&context);
	}
 
	/* 填充消息分组,并处理 */
	bitLen = messageLen * 8;
	if (IsLittleEndian())
		ReverseWord(&bitLen);
	remainder = messageLen % 64;
	memcpy(context.messageBlock, message + i * 64, remainder);
	context.messageBlock[remainder] = 0x80;
	if (remainder <= 55)
	{
		/* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
		* 故将高 4 个字节赋为 0 。*/
		memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1 - 8 + 4);
		memcpy(context.messageBlock + 64 - 4, &bitLen, 4);
		SM3ProcessMessageBlock(&context);
	}
	else
	{
		memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1);
		SM3ProcessMessageBlock(&context);
		/* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
		* 故将高 4 个字节赋为 0 。*/
		memset(context.messageBlock, 0, 64 - 4);
		memcpy(context.messageBlock + 64 - 4, &bitLen, 4);
		SM3ProcessMessageBlock(&context);
	}
 
	/* 返回结果 */
	if (IsLittleEndian())
	for (i = 0; i < 8; i++)
		ReverseWord(context.intermediateHash + i);
	memcpy(digest, context.intermediateHash, SM3_HASH_SIZE);
 
	return digest;
}

sm3.h

/*
* sm3.h
*
* 为使此算法兼容32位、64位下Linux或Windows系统,
* 选择 int 来表示 32 位整数。
* 消息长度最大限定为 2**32 - 1(单位:比特),
* 且为 8 的倍数(消息的最小单元为字节)。
*/
#ifndef _SM3_H_
#define _SM3_H_
 
/*
* SM3算法产生的哈希值大小(单位:字节)
*/
#define SM3_HASH_SIZE 32 
 
/*
* SM3上下文
*/
typedef struct SM3Context
{
	unsigned int intermediateHash[SM3_HASH_SIZE / 4];
	unsigned char messageBlock[64];
} SM3Context;
 
/*
* SM3计算函数
*/
unsigned char *SM3Calc(const unsigned char *message,
	unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]);
 
#endif // _SM3_H_

SM4

sm4.c
加解密函数函数名_old的为基本加解密函数,不带的为封装了pkcs7填充函数后的加解密函数

/*
 * SM4 Encryption alogrithm (SMS4 algorithm)
 * GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/ 
 * thanks to Xyssl
 * thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html
 * author:goldboar
 * email:goldboar@163.com
 * 2012-4-20
 */

// Test vector 1
// plain: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
// key:   01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
// 	   round key and temp computing result:
// 	   rk[ 0] = f12186f9 X[ 0] = 27fad345
// 		   rk[ 1] = 41662b61 X[ 1] = a18b4cb2
// 		   rk[ 2] = 5a6ab19a X[ 2] = 11c1e22a
// 		   rk[ 3] = 7ba92077 X[ 3] = cc13e2ee
// 		   rk[ 4] = 367360f4 X[ 4] = f87c5bd5
// 		   rk[ 5] = 776a0c61 X[ 5] = 33220757
// 		   rk[ 6] = b6bb89b3 X[ 6] = 77f4c297
// 		   rk[ 7] = 24763151 X[ 7] = 7a96f2eb
// 		   rk[ 8] = a520307c X[ 8] = 27dac07f
// 		   rk[ 9] = b7584dbd X[ 9] = 42dd0f19
// 		   rk[10] = c30753ed X[10] = b8a5da02
// 		   rk[11] = 7ee55b57 X[11] = 907127fa
// 		   rk[12] = 6988608c X[12] = 8b952b83
// 		   rk[13] = 30d895b7 X[13] = d42b7c59
// 		   rk[14] = 44ba14af X[14] = 2ffc5831
// 		   rk[15] = 104495a1 X[15] = f69e6888
// 		   rk[16] = d120b428 X[16] = af2432c4
// 		   rk[17] = 73b55fa3 X[17] = ed1ec85e
// 		   rk[18] = cc874966 X[18] = 55a3ba22
// 		   rk[19] = 92244439 X[19] = 124b18aa
// 		   rk[20] = e89e641f X[20] = 6ae7725f
// 		   rk[21] = 98ca015a X[21] = f4cba1f9
// 		   rk[22] = c7159060 X[22] = 1dcdfa10
// 		   rk[23] = 99e1fd2e X[23] = 2ff60603
// 		   rk[24] = b79bd80c X[24] = eff24fdc
// 		   rk[25] = 1d2115b0 X[25] = 6fe46b75
// 		   rk[26] = 0e228aeb X[26] = 893450ad
// 		   rk[27] = f1780c81 X[27] = 7b938f4c
// 		   rk[28] = 428d3654 X[28] = 536e4246
// 		   rk[29] = 62293496 X[29] = 86b3e94f
// 		   rk[30] = 01cf72e5 X[30] = d206965e
// 		   rk[31] = 9124a012 X[31] = 681edf34
// cypher: 68 1e df 34 d2 06 96 5e 86 b3 e9 4f 53 6e 42 46
// 		
// test vector 2
// the same key and plain 1000000 times coumpting 
// plain:  01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
// key:    01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
// cypher: 59 52 98 c7 c6 fd 27 1f 04 02 f8 04 c3 3d 3f 66

#include "sm4.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/*
 * 32-bit integer manipulation macros (big endian)
 */
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i)                             \
{                                                       \
    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
        | ( (unsigned long) (b)[(i) + 3]       );       \
}
#endif

#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i)                             \
{                                                       \
    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
}
#endif

/*
 *rotate shift left marco definition
 *
 */
#define  SHL(x,n) (((x) & 0xFFFFFFFF) << n%32) 
#define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n%32)))

#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
/*
 * Expanded SM4 S-boxes
 * Sbox table: 8bits input convert to 8 bits output*/
 
static const unsigned char SboxTable[16][16] = 
{
{0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05},
{0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99},
{0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62},
{0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6},
{0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8},
{0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35},
{0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87},
{0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e},
{0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1},
{0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3},
{0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f},
{0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51},
{0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8},
{0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0},
{0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84},
{0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48}
};

/* System parameter */
static const unsigned long FK[4] = {0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc};

/* fixed parameter */
static const unsigned long CK[32] =
{
0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
0x10171e25,0x2c333a41,0x484f565d,0x646b7279
};


/*
 * private function:
 * look up in SboxTable and get the related value.
 * args:    [in] inch: 0x00~0xFF (8 bits unsigned value).
 */
static unsigned char sm4Sbox(unsigned char inch)
{
    unsigned char *pTable = (unsigned char *)SboxTable;
    unsigned char retVal = (unsigned char)(pTable[inch]);
    return retVal;
}

/*
 * private F(Lt) function:
 * "T algorithm" == "L algorithm" + "t algorithm".
 * args:    [in] a: a is a 32 bits unsigned value;
 * return: c: c is calculated with line algorithm "L" and nonline algorithm "t"
 */
static unsigned long sm4Lt(unsigned long ka)
{
    unsigned long bb = 0;
    unsigned long c = 0;
    unsigned char a[4];
	unsigned char b[4];
    PUT_ULONG_BE(ka,a,0)
    b[0] = sm4Sbox(a[0]);
    b[1] = sm4Sbox(a[1]);
    b[2] = sm4Sbox(a[2]);
    b[3] = sm4Sbox(a[3]);
	GET_ULONG_BE(bb,b,0)
    c =bb^(ROTL(bb, 2))^(ROTL(bb, 10))^(ROTL(bb, 18))^(ROTL(bb, 24));
    return c;
}

/*
 * private F function:
 * Calculating and getting encryption/decryption contents.
 * args:    [in] x0: original contents;
 * args:    [in] x1: original contents;
 * args:    [in] x2: original contents;
 * args:    [in] x3: original contents;
 * args:    [in] rk: encryption/decryption key;
 * return the contents of encryption/decryption contents.
 */
static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk)
{
    return (x0^sm4Lt(x1^x2^x3^rk));
}


/* private function:
 * Calculating round encryption key.
 * args:    [in] a: a is a 32 bits unsigned value;
 * return: sk[i]: i{0,1,2,3,...31}.
 */
static unsigned long sm4CalciRK(unsigned long ka)
{
    unsigned long bb = 0;
    unsigned long rk = 0;
    unsigned char a[4];
    unsigned char b[4];
    PUT_ULONG_BE(ka,a,0)
    b[0] = sm4Sbox(a[0]);
    b[1] = sm4Sbox(a[1]);
    b[2] = sm4Sbox(a[2]);
    b[3] = sm4Sbox(a[3]);
	GET_ULONG_BE(bb,b,0)
    rk = bb^(ROTL(bb, 13))^(ROTL(bb, 23));
    return rk;
}

static void sm4_setkey( unsigned long SK[32], unsigned char key[16] )
{
    unsigned long MK[4];
    unsigned long k[36];
    unsigned long i = 0;

    GET_ULONG_BE( MK[0], key, 0 );
    GET_ULONG_BE( MK[1], key, 4 );
    GET_ULONG_BE( MK[2], key, 8 );
    GET_ULONG_BE( MK[3], key, 12 );
    k[0] = MK[0]^FK[0];
    k[1] = MK[1]^FK[1];
    k[2] = MK[2]^FK[2];
    k[3] = MK[3]^FK[3];
    for(; i<32; i++)
    {
        k[i+4] = k[i] ^ (sm4CalciRK(k[i+1]^k[i+2]^k[i+3]^CK[i]));
        SK[i] = k[i+4];
	}

}

/*
 * SM4 standard one round processing
 *
 */
static void sm4_one_round( unsigned long sk[32],
                    unsigned char input[16],
                    unsigned char output[16] )
{
    unsigned long i = 0;
    unsigned long ulbuf[36];

    memset(ulbuf, 0, sizeof(ulbuf));
    GET_ULONG_BE( ulbuf[0], input, 0 )
    GET_ULONG_BE( ulbuf[1], input, 4 )
    GET_ULONG_BE( ulbuf[2], input, 8 )
    GET_ULONG_BE( ulbuf[3], input, 12 )
    while(i<32)
    {
        ulbuf[i+4] = sm4F(ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3], sk[i]);
// #ifdef _DEBUG
//        	printf("rk(%02d) = 0x%08x,  X(%02d) = 0x%08x \n",i,sk[i], i, ulbuf[i+4] );
// #endif
	    i++;
    }
	PUT_ULONG_BE(ulbuf[35],output,0);
	PUT_ULONG_BE(ulbuf[34],output,4);
	PUT_ULONG_BE(ulbuf[33],output,8);
	PUT_ULONG_BE(ulbuf[32],output,12);
}

/*
 * SM4 key schedule (128-bit, encryption)
 */
void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] )
{
  ctx->mode = SM4_ENCRYPT;
	sm4_setkey( ctx->sk, key );
}

/*
 * SM4 key schedule (128-bit, decryption)
 */
void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] )
{
	int i;
	ctx->mode = SM4_DECRYPT;
	sm4_setkey( ctx->sk, key );
	for( i = 0; i < 16; i ++ )
	{
			SWAP( ctx->sk[ i ], ctx->sk[ 31-i] );
	}
}


/*
 * SM4-ECB block encryption/decryption
 */

void sm4_crypt_ecb_old( sm4_context *ctx,
				   int mode,
				   int length,
				   unsigned char *input,
           unsigned char *output)
{
    while( length > 0 )
    {
        sm4_one_round( ctx->sk, input, output );
        input  += 16;
        output += 16;
        length -= 16;
    }

}

/*
 * SM4-CBC buffer encryption/decryption
 */
void sm4_crypt_cbc_old( sm4_context *ctx,
                    int mode,
                    int length,
                    unsigned char iv[16],
                    unsigned char *input,
                    unsigned char *output )
{
    int i;
    unsigned char temp[16];

    if( mode == SM4_ENCRYPT )
    {
        while( length > 0 )
        {
            for( i = 0; i < 16; i++ )
            output[i] = (unsigned char)( input[i] ^ iv[i] );

            sm4_one_round( ctx->sk, output, output );
            memcpy( iv, output, 16 );

            input  += 16;
            output += 16;
            length -= 16;
        }
    }
    else /* SM4_DECRYPT */
    {
        while( length > 0 )
        {
            memcpy( temp, input, 16 );
            sm4_one_round( ctx->sk, input, output );

            for( i = 0; i < 16; i++ )
                output[i] = (unsigned char)( output[i] ^ iv[i] );

            memcpy( iv, temp, 16 );

            input  += 16;
            output += 16;
            length -= 16;
        }
    }
}

/**
  * @brief SM4-ECB + PKCS7算法
	* @param ctx:      SM4结构体,主要是包含初始秘钥(对于ECB模式的加密来说,
										 不同之处就在于它的初始化时秘钥的初始方法不同,加密操作
										 都是一样的)
	* @param mode:     加密:SM4_ENCRYPT 解密:SM4_DECRYPT
	* @param length:   需要处理的数据长度指针
	* @param input:    需要处理的数据
	* @param output:   处理完的数据
	* @attention:     1、length参数类型为指针,在此函数内部,该参数会
										 被修改为加解密后数据的实际长度。
										 2、对于input参数,要求其必须富裕出最少16字节的空间以供
										填充数据。
										 3、对于解密的output,并未真正去除掉填充的数据,只是
										对数据长度进行去填充长度操作,请按length长度取值
  * @retval void
  */
void sm4_crypt_ecb( sm4_context *ctx, int mode, unsigned int *length, \
										unsigned char *input, unsigned char *output)
{
	/* 填充长度及填充值 */
	int padding_value;

	if(mode == SM4_ENCRYPT)
	{	
		padding_value = 16 - (*length % 16);
		
		/* 填充 */
		memset(input + *length, padding_value, padding_value);
		
		/* 填充后长度 */
		*length += padding_value;
		
		/* 加密 */
		sm4_crypt_ecb_old(ctx, mode, *length, input, output);
	}
	else //SM4_DECRYPT
	{
		sm4_crypt_ecb_old(ctx, mode, *length, input, output);	
		
		/* 去掉填充长度 */
		*length -= output[*length - 1];
	}
}

/**
	* @brief          SM4-CBC + PKCS7算法
	* @param ctx      SM4 context
	* @param mode     加密:SM4_ENCRYPT 解密:SM4_DECRYPT
	* @param length   需要处理的数据长度指针
	* @param iv       初始化向量(使用后更新)
	* @param input:   需要处理的数据
	* @param output:  处理完的数据
	* @attention:    1、length参数类型为指针,在此函数内部,该参数会
										被修改为加解密后数据的实际长度。
										2、对于input参数,要求其必须富裕出最少16字节的空间以供
										填充数据。
										3、对于解密的output,并未真正去除掉填充的数据,只是
										对数据长度进行去填充长度操作,请按length长度取值
  * @retval void
 */
void sm4_crypt_cbc( sm4_context *ctx, int mode, int *length, unsigned char iv[16], \
                    unsigned char *input, unsigned char *output )
{
	/* 填充长度及填充值 */
	int padding_value;
	
	if(mode == SM4_ENCRYPT)
	{
		padding_value = 16 - (*length % 16);
		
		/* 填充 */
		memset(input + *length, padding_value, padding_value);
		*length += padding_value;

		sm4_crypt_cbc_old(ctx, mode, *length, iv, input, output);
	}
	else //SM4_DECRYPT
	{
		sm4_crypt_cbc_old(ctx, mode, *length, iv, input, output);

		*length -= output[*length - 1];
	}
}
/**
 * \file sm4.h
 */
#ifndef XYSSL_SM4_H
#define XYSSL_SM4_H

#define SM4_ENCRYPT     1
#define SM4_DECRYPT     0


/**
 * \brief          SM4 context structure
 */
typedef struct
{
    int mode;                   /*!<  encrypt/decrypt   */
    unsigned long sk[32];       /*!<  SM4 subkeys       */
}
sm4_context;


#ifdef __cplusplus
extern "C" {
#endif

/**
 * \brief          SM4 key schedule (128-bit, encryption)
 *
 * \param ctx      SM4 context to be initialized
 * \param key      16-byte secret key
 */
void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] );

/**
 * \brief          SM4 key schedule (128-bit, decryption)
 *
 * \param ctx      SM4 context to be initialized
 * \param key      16-byte secret key
 */
void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] );

/**
  * @brief SM4 + PKCS7算法
	* @param ctx:      SM4结构体,主要是包含初始秘钥(对于ECB模式的加密来说,
										 不同之处就在于它的初始化时秘钥的初始方法不同,加密操作
										 都是一样的)
	* @param mode:     加密:SM4_ENCRYPT 解密:SM4_DECRYPT
	* @param length:   需要处理的数据长度指针
	* @param input:    需要处理的数据
	* @param output:   处理完的数据
	* @attention:     1、length参数类型为指针,在此函数内部,该参数会
										 被修改为加解密后数据的实际长度。
										 2、对于input参数,要求其必须富裕出至少16字节的空间以供
										填充数据。
										 3、对于解密的output,并未真正去除掉填充的数据,只是
										对数据长度进行去填充长度操作,请按length长度取值
  * @retval void
  */
void sm4_crypt_ecb( sm4_context *ctx, int mode, unsigned int *length, \
										unsigned char *input, unsigned char *output);


/**
	* @brief          SM4-CBC + PKCS7算法
	* @param ctx      SM4 context
	* @param mode     加密:SM4_ENCRYPT 解密:SM4_DECRYPT
	* @param length   需要处理的数据长度指针
	* @param iv       初始化向量(使用后更新)
	* @param input:   需要处理的数据
	* @param output:  处理完的数据
	* @attention:    1、length参数类型为指针,在此函数内部,该参数会
										 被修改为加解密后数据的实际长度。
										2、对于input参数,要求其必须富裕出至少16字节的空间以供
										填充数据。
										3、对于解密的output,并未真正去除掉填充的数据,只是
										对数据长度进行去填充长度操作,请按length长度取值
  * @retval void
 */
void sm4_crypt_cbc( sm4_context *ctx,int mode,int *length, unsigned char iv[16], \
                    unsigned char *input,unsigned char *output );
 
#ifdef __cplusplus
}
#endif

#endif /* sm4.h */

  • 4
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 34
    评论
评论 34
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值