Files
intel-linux-sgx/SampleCode/SampleEnclaveGMIPP/Enclave/Enclave.cpp
Li, Xun a53adeaab7 Linux 2.24 Open Source Gold Release
Upgraded to OpenSSL 3.0.13.
Upgraded to Intel(R) Integrated Performance Primitives (IPP) Cryptography library
  version 2021.11.
Upgraded to Protobuf 3.23.2.
Upgraded MbedTLS to 3.5.2.
Upgraded Intel DCAP Ring3 Abstraction Layer (R3AAL) library to support ConfigFS-TSM
  as communication channel between host and guest for TDX remote attestation.
Upgraded Intel DCAP Quote Verification Enclave to integrate OpenSSL/SgxSSL 3.0.13.
Upgraded new TDX attestation result “TD_RELAUNCH_ADVISED” in Intel DCAP Quote
  Verification Library (QVL) and Appraisal Engine.
Fixed bugs.

Signed-off-by: Li, Xun <xun.li@intel.com>
2024-04-26 15:24:15 +08:00

1540 lines
42 KiB
C++

/*
* Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "Enclave.h"
#include "Enclave_t.h" /* print_string */
#include <stdarg.h>
#include <stdio.h> /* vsnprintf */
#include <string.h>
#include "sgx_trts.h"
#include "mbusafecrt.h"
#include <ippcp.h> /* ipp library */
#ifndef SAFE_FREE_HEAP
#define SAFE_FREE_HEAP(ptr, size) do {if (NULL != (ptr)) {memset_s(ptr, size, 0, size); free(ptr); (ptr)=NULL;}} while(0);
#endif
#ifndef SAFE_FREE_STACK
#define SAFE_FREE_STACK(ptr, size) do {if (NULL != (ptr)) {memset_s(ptr, size, 0, size);}} while(0);
#endif
const unsigned int order[] = {0x39D54123, 0x53BBF409, 0x21C6052B, 0x7203DF6B, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE};
const int ordSize = sizeof(order) / sizeof(unsigned int);
/*
* printf:
* Invokes OCALL to display the enclave buffer to the terminal.
*/
int printf(const char* fmt, ...)
{
char buf[BUFSIZ] = { '\0' };
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, BUFSIZ, fmt, ap);
va_end(ap);
ocall_print_string(buf);
return (int)strnlen(buf, BUFSIZ - 1) + 1;
}
/* Define EC over GF(p) context for SM2 */
static IppsECCPState* new_ECC_sm2(void)
{
int ctxSize = 0;
IppsECCPState* pSM2 = NULL;
IppStatus status = ippStsNoErr;
// Get the size of ECC context for SM2
status = ippsECCPGetSizeStdSM2(&ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to get size of ECCP\n");
return NULL;
}
// Allocate the ECC context for SM2
pSM2 = (IppsECCPState*)(malloc(ctxSize));
if (pSM2 == NULL) {
printf("Error: fail to allocate memory for ECCP\n");
return NULL;
}
// Initialize the ECC context for SM2
status = ippsECCPInitStdSM2(pSM2);
if (status != ippStsNoErr) {
printf("Error: fail to initialize ECCP\n");
SAFE_FREE_HEAP(pSM2, ctxSize);
return NULL;
}
// Set up a recommended set of domain parameters for ECC context for SM2
status = ippsECCPSetStdSM2(pSM2);
if (status != ippStsNoErr) {
printf("Error: fail to set up recommended set of domain parameters for ECCP\n");
SAFE_FREE_HEAP(pSM2, ctxSize);
return NULL;
}
return pSM2;
}
/* Define EC over GF(p) Point context */
static IppsECCPPointState* new_ECC_Point(void)
{
int ctxSize = 0;
IppsECCPPointState* pPoint = NULL;
IppStatus status = ippStsNoErr;
status = ippsECCPPointGetSize(256, &ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to get size of ECCPPoint\n");
return NULL;
}
pPoint = (IppsECCPPointState*)(malloc(ctxSize));
if (pPoint == NULL) {
printf("Error: fail to allocate memory for ECCPPoint\n");
return NULL;
}
status = ippsECCPPointInit(256, pPoint);
if (status != ippStsNoErr) {
printf("Error: fail to initialize ECCPPoint\n");
SAFE_FREE_HEAP(pPoint, ctxSize);
return NULL;
}
return pPoint;
}
/* Define Big Number context */
static IppsBigNumState* new_BN(int len, const unsigned int* pData)
{
int ctxSize = 0;
IppsBigNumState* pBN = NULL;
IppStatus status = ippStsNoErr;
status = ippsBigNumGetSize(len, &ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to get size of BigNum\n");
return NULL;
}
pBN = (IppsBigNumState*)(malloc(ctxSize));
if (pBN == NULL) {
printf("Error: fail to allocate memory for BigNum\n");
return NULL;
}
status = ippsBigNumInit(len, pBN);
if (status != ippStsNoErr) {
printf("Error: fail to initialize BigNum\n");
SAFE_FREE_HEAP(pBN, ctxSize);
return NULL;
}
if (pData)
ippsSet_BN(IppsBigNumPOS, len, pData, pBN);
return pBN;
}
/* Convert bit size into 32-bit word size */
static int Bitsize2Wordsize(int nBits)
{
return (nBits+31)>>5;
}
/* Generate a secure random number */
static int secure_rand(unsigned int* pX, int size)
{
if (sgx_read_rand((unsigned char*)pX, size) != SGX_SUCCESS) {
printf("Error: fail to generate a secure random number\n");
return -1;
}
return 0;
}
/* Define Pseudo-random generation context */
static IppsPRNGState* new_PRNG(void)
{
int size = 0;
IppsPRNGState* pPRNG = NULL;
IppsBigNumState* pBN = NULL;
IppStatus ipp_ret = ippStsNoErr;
int seedBitsize = 160;
int seedSize = Bitsize2Wordsize(seedBitsize);
unsigned int* seed = NULL;
unsigned int* augm = NULL;
ipp_ret = ippsPRNGGetSize(&size);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to get size of PRNG\n");
return NULL;
}
pPRNG = (IppsPRNGState*)malloc(size);
if (pPRNG == NULL) {
printf("Error: fail to allocate memory for PRNG\n");
return NULL;
}
ipp_ret = ippsPRNGInit(seedBitsize, pPRNG);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to initialize PRNG\n");
SAFE_FREE_HEAP(pPRNG, size);
return NULL;
}
seed = (unsigned int*)malloc(seedSize);
if (secure_rand(seed, seedSize) != 0) {
printf("Error: fail to generate a secure random number for seed\n");
SAFE_FREE_HEAP(seed, seedSize);
return NULL;
}
ipp_ret = ippsPRNGSetSeed(pBN=new_BN(seedSize, seed), pPRNG);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to set the seed value of PRNG\n");
SAFE_FREE_HEAP(pPRNG, size);
free(pBN);
SAFE_FREE_HEAP(seed, seedSize);
return NULL;
}
free(pBN);
augm = (unsigned int*)malloc(seedSize);
if (secure_rand(augm, seedSize) != 0) {
printf("Error: fail to generate a secure random number for augm\n");
SAFE_FREE_HEAP(augm, seedSize);
return NULL;
}
ipp_ret = ippsPRNGSetAugment(pBN=new_BN(seedSize, augm), pPRNG);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to set the entropy augmentation of PRNG\n");
SAFE_FREE_HEAP(pPRNG, size);
free(pBN);
SAFE_FREE_HEAP(augm, seedSize);
return NULL;
}
free(pBN);
SAFE_FREE_HEAP(augm, seedSize);
SAFE_FREE_HEAP(seed, seedSize);
return pPRNG;
}
/* Calculate ZA = H256(ENTLA || IDA || a || b || xG || yG || xA || yA) */
static int hash_digest_z(const IppsHashMethod *hash_method, const char *id, const int id_len, const IppsBigNumState *pubX, const IppsBigNumState *pubY, unsigned char *z_digest)
{
int ctx_size = 0;
IppsHashState_rmf* hash_handle = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
int id_bit_len = id_len * 8;
unsigned char entl[2] = {0};
entl[0] = (id_bit_len & 0xff00) >> 8;
entl[1] = id_bit_len & 0xff;
unsigned char a[32] = {
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};
unsigned char b[32] = {
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};
unsigned char xG[32] = {
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};
unsigned char yG[32] = {
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 xA[32] = {0};
unsigned char yA[32] = {0};
do {
ipp_ret = ippsGetOctString_BN(xA, 32, pubX);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to Convert BN value pubX into octet string xA\n");
ret = -1;
break;
}
ipp_ret = ippsGetOctString_BN(yA, 32, pubY);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to Convert BN value pubY into octet string yA\n");
ret = -2;
break;
}
ipp_ret = ippsHashGetSize_rmf(&ctx_size);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to get size of ippsHashGetSize_rmf\n");
ret = -3;
break;
}
hash_handle = (IppsHashState_rmf*)(malloc(ctx_size));
if (!hash_handle)
{
printf("Error: fail to allocate memory for ippsHashGetSize_rmf\n");
ret = -4;
break;
}
// Set Hash 256 handler:
// SM3 - ippsHashMethod_SM3()
// SHA256 - ippsHashMethod_SHA256_TT()
ipp_ret = ippsHashInit_rmf(hash_handle, hash_method);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to set hash 256 handler\n");
ret = -5;
break;
}
// ZA = H256(ENTLA || IDA || a || b || xG || yG || xA || yA)
ipp_ret = ippsHashUpdate_rmf(entl, sizeof(entl), hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of ENTLA\n");
ret = -6;
break;
}
ipp_ret = ippsHashUpdate_rmf((unsigned char*)id, id_len, hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of IDA\n");
ret = -7;
break;
}
ipp_ret = ippsHashUpdate_rmf(a, sizeof(a), hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of a\n");
ret = -8;
break;
}
ipp_ret = ippsHashUpdate_rmf(b, sizeof(b), hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of b\n");
ret = -9;
break;
}
ipp_ret = ippsHashUpdate_rmf(xG, sizeof(xG), hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of xG\n");
ret = -10;
break;
}
ipp_ret = ippsHashUpdate_rmf(yG, sizeof(yG), hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of yG\n");
ret = -11;
break;
}
ipp_ret = ippsHashUpdate_rmf(xA, sizeof(xA), hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of xA\n");
ret = -12;
break;
}
ipp_ret = ippsHashUpdate_rmf(yA, sizeof(yA), hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of yA\n");
ret = -13;
break;
}
ipp_ret = ippsHashFinal_rmf(z_digest, hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to complete message digesting and return digest\n");
ret = -14;
break;
}
} while(0);
SAFE_FREE_HEAP(hash_handle, ctx_size);
return ret;
}
/* Calculate ZA = H256(Z||M) */
static int hash_digest_with_preprocess(const IppsHashMethod *hash_method, const char *msg, const int msg_len, const char *id, const int id_len, const IppsBigNumState* pubX, const IppsBigNumState* pubY, unsigned char *digest)
{
int ctx_size = 0;
IppsHashState_rmf* hash_handle = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
unsigned char z_digest[32] = {0};
do {
ret = hash_digest_z(hash_method, id, id_len, pubX, pubY, z_digest);
if (ret != 0)
{
printf("Error: fail to complete SM3 digest of leading data Z\n");
return -1;
break;
}
ipp_ret = ippsHashGetSize_rmf(&ctx_size);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to get size of IppsHashState_rmf\n");
ret = -2;
break;
}
hash_handle = (IppsHashState_rmf*)(malloc(ctx_size));
if (!hash_handle)
{
printf("Error: fail to allocate memory for IppsHashState_rmf\n");
ret = -3;
break;
}
// Set Hash 256 handler:
// SM3 - ippsHashMethod_SM3()
// SHA256 - ippsHashMethod_SHA256_TT()
ipp_ret = ippsHashInit_rmf(hash_handle, hash_method);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to initialize IppsHashState_rmf\n");
ret = -4;
break;
}
// ZA = H256(Z||M)
ipp_ret = ippsHashUpdate_rmf(z_digest, sizeof(z_digest), hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of Z\n");
ret = -5;
break;
}
ipp_ret = ippsHashUpdate_rmf((unsigned char *)msg, msg_len, hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to update hash value of M\n");
ret = -6;
break;
}
ipp_ret = ippsHashFinal_rmf(digest, hash_handle);
if (ipp_ret != ippStsNoErr)
{
printf("Error: fail to complete message digesting and return digest\n");
ret = -7;
break;
}
} while(0);
SAFE_FREE_HEAP(hash_handle, ctx_size);
return ret;
}
/* SM2 sign */
static int sm2_do_sign(const IppsBigNumState *regPrivateKey, const IppsHashMethod *hash_method, const char *id, const int id_len, const char *msg, const int msg_len, IppsBigNumState* signX, IppsBigNumState* signY)
{
IppsECCPState *pECCPS = NULL;
IppsPRNGState *pPRNGS = NULL;
IppsBigNumState *ephPrivateKey = NULL;
IppsECCPPointState *regPublicKey = NULL, *ephPublicKey = NULL;
IppsBigNumState *pMsg = NULL;
IppsBigNumState *pX = NULL, *pY = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
unsigned char hash[32] = {0};
do {
// 1. Create ECC context for SM2
pECCPS = new_ECC_sm2();
if (pECCPS == NULL) {
printf("Error: fail to create pECCPS\n");
ret = -1;
break;
}
// 2. Create ephemeral private key and public key, regular public key
ephPrivateKey = new_BN(ordSize, 0);
if (ephPrivateKey == NULL) {
printf("Error: fail to create ephemeral private key\n");
ret = -2;
break;
}
ephPublicKey = new_ECC_Point();
if (ephPublicKey == NULL) {
printf("Error: fail to create ephemeral public key\n");
ret = -3;
break;
}
regPublicKey = new_ECC_Point();
if (regPublicKey == NULL) {
printf("Error: fail to create regular public key\n");
ret = -4;
break;
}
ipp_ret = ippsECCPPublicKey(regPrivateKey, regPublicKey, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to calculate regular public key\n");
ret = -5;
break;
}
// 3. Generate ephemeral key pairs
pPRNGS = new_PRNG();
if (pPRNGS == NULL) {
printf("Error: fail to create pPRNGS\n");
ret = -6;
break;
}
ipp_ret = ippsECCPGenKeyPair(ephPrivateKey, ephPublicKey, pECCPS, ippsPRNGen, pPRNGS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to generate ephemeral key pairs\n");
ret = -7;
break;
}
// 4. Create pX and pY
pX = new_BN(ordSize, 0);
if (pX == NULL){
printf("Error: fail to create pX\n");
ret = -8;
break;
}
pY = new_BN(ordSize, 0);
if (pY == NULL){
printf("Error: fail to create pY\n");
ret = -9;
break;
}
ipp_ret = ippsECCPGetPoint(pX, pY, regPublicKey, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to convert internal presentation EC point into regular affine coordinates EC point\n");
ret = -10;
break;
}
// 5. Do user message digest
ret = hash_digest_with_preprocess(hash_method, msg, msg_len, id, id_len, pX, pY, hash);
if (ret != 0) {
printf("Error: fail to do hash digest with preprocess\n");
ret = -11;
break;
}
pMsg = new_BN(ordSize, 0);
if (pMsg == NULL) {
printf("Error: fail to create BN\n");
ret = -12;
break;
}
ipp_ret = ippsSetOctString_BN(hash, sizeof(hash), pMsg);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to convert octet string into BN value\n");
ret = -13;
break;
}
// 6. Sign using ECC context for SM2
ipp_ret = ippsECCPSetKeyPair(ephPrivateKey, ephPublicKey, ippFalse, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to set ephemeral key pairs\n");
ret = -14;
break;
}
ipp_ret = ippsECCPSignSM2(pMsg, regPrivateKey, ephPrivateKey, signX, signY, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to compute signature\n");
ret = -15;
break;
}
} while(0);
// 7. Final, remove secret and release resources
// !!!Please clear secret including key/context related buffer/big number by manual!!!
free(pY);
free(pX);
free(pMsg);
free(regPublicKey);
free(ephPublicKey);
free(ephPrivateKey);
free(pPRNGS);
free(pECCPS);
return ret;
}
/* SM2 verify */
static int sm2_do_verify(const IppsECCPPointState *regPublicKey, const IppsHashMethod *hash_method, const char *id, const int id_len, const char *msg, const int msg_len, IppsBigNumState* signX, IppsBigNumState* signY)
{
IppsECCPState *pECCPS = NULL;
IppsBigNumState* pMsg = NULL;
IppsBigNumState *pX = NULL, *pY = NULL;
IppStatus ipp_ret = ippStsNoErr;
IppECResult eccResult = ippECValid;
int ret = 0;
unsigned char hash[32] = {0};
do {
// 1. Create ECC context for SM2
pECCPS = new_ECC_sm2();
if (pECCPS == NULL) {
printf("Error: fail to create pECCPS\n");
ret = -1;
break;
}
// 2. Create pX and pY
pX = new_BN(ordSize, 0);
if (pX == NULL){
printf("Error: fail to create pX\n");
ret = -2;
break;
}
pY = new_BN(ordSize, 0);
if (pY == NULL){
printf("Error: fail to create pY\n");
ret = -3;
break;
}
ipp_ret = ippsECCPGetPoint(pX, pY, regPublicKey, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to convert internal presentation EC point into regular affine coordinates EC point\n");
ret = -4;
break;
}
// 3. Do user message digest
ret = hash_digest_with_preprocess(hash_method, msg, msg_len, id, id_len, pX, pY, hash);
if (ret != 0) {
printf("Error: fail to do hash digest with preprocess\n");
ret = -5;
break;
}
pMsg = new_BN(ordSize, 0);
if (pMsg == NULL) {
printf("Error: fail to create BN\n");
ret = -6;
break;
}
ipp_ret = ippsSetOctString_BN(hash, sizeof(hash), pMsg);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to convert octet string into BN value\n");
ret = -7;
break;
}
// 4. Verify using ECC context for SM2
ipp_ret = ippsECCPSetKeyPair(NULL, regPublicKey, ippTrue, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to set regular public key\n");
ret = -8;
break;
}
ipp_ret = ippsECCPVerifySM2(pMsg, regPublicKey, signX, signY, &eccResult, pECCPS);
if((ipp_ret != ippStsNoErr) || (eccResult != ippECValid)) {
printf("Error: fail to verify signature\n");
ret = -9;
break;
}
} while(0);
// 5. Final, remove secret and release resourcesz
// !!!Please clear secret including key/context related buffer/big number by manual!!!
free(pY);
free(pX);
free(pMsg);
free(pECCPS);
return ret;
}
/* Signing and verification using ECC context for SM2 */
int ecall_sm2_sign_verify(void)
{
IppsECCPState *pECCPS = NULL;
IppsBigNumState *regPrivateKey = NULL;
IppsECCPPointState *regPublicKey = NULL;
IppsBigNumState *signX = NULL, *signY = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
char *message = "context need to be signed";
char *user_id = "1234567812345678";
/*
Generate a SM2 random key
!!! THIS IS ONLY A SIMPLE SAMPLE OF RANDOM KEY GENERATION, YOU STILL HAVE TO GENERATE YOUR KEY WITH ENOUGH ENTROPY !!!
*/
unsigned char priKey[32] = {0};
if (secure_rand((unsigned int*)priKey, 32) != 0) {
printf("Error: fail to generate a SM2 random key\n");
SAFE_FREE_STACK(priKey, 32);
return -1;
}
do {
// 1. Create ECC context for SM2
pECCPS = new_ECC_sm2();
if (pECCPS == NULL) {
printf("Error: fail to create ecc context for sm2\n");
ret = -2;
break;
}
// 2. Create regular private key and public key
regPrivateKey = new_BN(ordSize, 0);
if (regPrivateKey == NULL) {
printf("Error: fail to create regular private key\n");
ret = -3;
break;
}
regPublicKey = new_ECC_Point();
if (regPublicKey == NULL) {
printf("Error: fail to create regular public key\n");
ret = -4;
break;
}
// 3. Create regular private and public key pairs
ipp_ret = ippsSetOctString_BN(priKey, sizeof(priKey)-1, regPrivateKey);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to convert octet string into BN value\n");
ret = -5;
break;
}
ipp_ret = ippsECCPPublicKey(regPrivateKey, regPublicKey, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to calculate regular public key\n");
ret = -6;
break;
}
// 4. Create signX and signY
signX = new_BN(ordSize, 0);
if (signX == NULL) {
printf("Error: fail to create signX\n");
ret = -7;
break;
}
signY = new_BN(ordSize, 0);
if (signY == NULL) {
printf("Error: fail to create signY\n");
ret = -8;
break;
}
// 5. Sign using ECC context for SM2
ret = sm2_do_sign(regPrivateKey, ippsHashMethod_SM3(), user_id, strlen(user_id), message, strlen(message), signX, signY);
if(ret != 0)
{
printf("Error: fail to sign\n");
ret = -9;
break;
}
// 6. Verify using ECC context for SM2
ret = sm2_do_verify(regPublicKey, ippsHashMethod_SM3(), user_id, strlen(user_id), message, strlen(message), signX, signY);
if (ret != 0)
{
printf("Error: fail to verify\n");
ret = -10;
break;
}
} while(0);
// 7. Final, remove secret and release resources
// !!!Please clear secret including key/context related buffer/big number by manual!!!
free(signY);
free(signX);
free(regPublicKey);
free(regPrivateKey);
free(pECCPS);
SAFE_FREE_STACK(priKey, 32);
return ret;
}
/* SM2 encrypt(GM version) */
static int sm2_do_encrypt_gm(const char* message, int message_len, Ipp8u** cipher_text, int* cipher_len, IppsECCPState *pECCPS, IppsECCPPointState *regPublicKey, IppsECCPPointState *ephPublicKey, IppsBigNumState *ephPrivateKey)
{
int maxOutlen = 0;
int pOutSize = 0;
IppsGFpECState *pEC = NULL;
Ipp8u* pScratchBuffer = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
do {
maxOutlen = 64 + message_len + 32 + 1; // encrypt/decrypt buffer = pubkey (64B) + message (inpLen) + tag (32B)
*cipher_text = (Ipp8u*)malloc(maxOutlen);
memset(*cipher_text, 0, maxOutlen);
pEC = pECCPS;
pScratchBuffer = (Ipp8u*)malloc(1024 * 10);
ipp_ret = ippsGFpECEncryptSM2_Ext(*cipher_text, maxOutlen, &pOutSize, (Ipp8u*)message, message_len, regPublicKey, ephPublicKey, ephPrivateKey, pEC, pScratchBuffer);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to encrypt.\n");
ret = -1;
break;
}
*cipher_len = pOutSize;
} while(0);
SAFE_FREE_HEAP(pScratchBuffer, 1024 * 10);
return ret;
}
/* SM2 decrypt(GM version) */
static int sm2_do_decrypt_gm(const Ipp8u* cipher_text, int message_len, Ipp8u** plain_text, int* plain_len, IppsECCPState *pECCPS, IppsBigNumState *regPrivateKey)
{
int maxOutlen = 0;
int pOutSize = 0;
IppsGFpECState *pEC = NULL;
Ipp8u* pScratchBuffer = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
do {
maxOutlen = 64 + message_len + 32 + 1; // encrypt/decrypt buffer = pubkey (64B) + message (inpLen) + tag (32B)
*plain_text = (Ipp8u*)malloc(maxOutlen);
memset(*plain_text, 0, maxOutlen);
pEC = pECCPS;
pScratchBuffer = (Ipp8u*)malloc(1024 * 10);
ipp_ret = ippsGFpECDecryptSM2_Ext(*plain_text, maxOutlen, &pOutSize, cipher_text, maxOutlen, regPrivateKey, pEC, pScratchBuffer);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to decrypt.\n");
ret = -1;
break;
}
*plain_len = pOutSize;
} while(0);
SAFE_FREE_HEAP(pScratchBuffer, 1024 * 10);
return ret;
}
/* Encryption and decryption using ECC context for SM2 (GM version, standard is GM/T 0003-2012) */
int ecall_sm2_encrypt_decrypt_gm(void)
{
IppsECCPState *pECCPS = NULL;
IppsBigNumState *regPrivateKey = NULL;
IppsECCPPointState *regPublicKey = NULL;
IppsPRNGState *pPRNGS = NULL;
IppsBigNumState *ephPrivateKey = NULL;
IppsECCPPointState *ephPublicKey = NULL;
Ipp8u *cipher_text = NULL, *plain_text = NULL;
int cipher_len = 0, plain_len = 0;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
char *message = "context need to be encrypted";
int message_len = strlen(message);
/*
Generate a SM2 random key
!!! THIS IS ONLY A SIMPLE SAMPLE OF RANDOM KEY GENERATION, YOU STILL HAVE TO GENERATE YOUR KEY WITH ENOUGH ENTROPY !!!
*/
unsigned char priKey[32] = {0};
if (secure_rand((unsigned int*)priKey, 32) != 0) {
printf("Error: fail to generate a SM2 random key\n");
SAFE_FREE_STACK(priKey, 32);
return -1;
}
do {
// 1. Create ECC context for SM2
pECCPS = new_ECC_sm2();
if (pECCPS == NULL) {
printf("Error: fail to create ecc context for sm2\n");
ret = -2;
break;
}
// 2. Create regular private key and public key
regPrivateKey = new_BN(ordSize, 0);
if (regPrivateKey == NULL) {
printf("Error: fail to create regular private key\n");
ret = -3;
break;
}
regPublicKey = new_ECC_Point();
if (regPublicKey == NULL) {
printf("Error: fail to create regular public key\n");
ret = -4;
break;
}
// 3. Generate regular private and public key pairs
ipp_ret = ippsSetOctString_BN(priKey, sizeof(priKey)-1, regPrivateKey);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to convert octet string into BN value\n");
ret = -5;
break;
}
ipp_ret = ippsECCPPublicKey(regPrivateKey, regPublicKey, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to calculate regular public key\n");
ret = -6;
break;
}
// 4. Generate ephemeral private and public key pairs
pPRNGS = new_PRNG();
if (pPRNGS == NULL) {
printf("Error: fail to create pPRNGS\n");
ret = -7;
break;
}
ephPrivateKey = new_BN(ordSize, 0);
if (ephPrivateKey == NULL) {
printf("Error: fail to create ephemeral private key\n");
ret = -8;
break;
}
ephPublicKey = new_ECC_Point();
if (ephPublicKey == NULL) {
printf("Error: fail to create ephemeral public key\n");
ret = -9;
break;
}
ipp_ret = ippsECCPGenKeyPair(ephPrivateKey, ephPublicKey, pECCPS, ippsPRNGen, pPRNGS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to generate ephemeral key pairs.\n");
ret = -10;
break;
}
ipp_ret = ippsECCPSetKeyPair(ephPrivateKey, ephPublicKey, ippFalse, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to set ephemeral key pairs\n");
ret = -11;
break;
}
// 5. Encrypt
ret = sm2_do_encrypt_gm(message, message_len, &cipher_text, &cipher_len, pECCPS, regPublicKey, ephPublicKey, ephPrivateKey);
if (ret != 0) {
printf("Error: fail to encrypt.\n");
ret = -12;
break;
}
// 6. Decrypt
ret = sm2_do_decrypt_gm(cipher_text, message_len, &plain_text, &plain_len, pECCPS, regPrivateKey);
if (ret != 0) {
printf("Error: fail to decrypt.\n");
ret = -13;
break;
}
// 7. Compare decrypted message and original message
if(strlen((char*)message) != strlen((char*)plain_text) || memcmp(message, plain_text, strlen((char*)message)) != 0)
{
printf("Error: decrypted message does not match original message!\n");
ret = -14;
break;
}
} while(0);
// 8. Final, remove secret and release resources
// !!!Please clear secret including key/context related buffer/big number by manual!!!
free(plain_text);
free(cipher_text);
free(ephPublicKey);
free(ephPrivateKey);
free(pPRNGS);
free(regPublicKey);
free(regPrivateKey);
free(pECCPS);
SAFE_FREE_STACK(priKey, 32);
return ret;
}
/* SM2 encrypt(IEEE version) */
static int sm2_do_encrypt_ieee(const char* message, int message_len, Ipp8u** cipher_text, IppsECCPState *pECCPS, IppsBigNumState *regPrivateKey, IppsECCPPointState *ephPublicKey)
{
IppsGFpECState *pEC = pECCPS;
int pSize = 0;
IppsECESState_SM2 *pState = NULL;
Ipp8u* pEcScratchBuffer = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
do {
ipp_ret = ippsGFpECESGetSize_SM2(pEC, &pSize);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to get size of the SM2 ECC\n");
ret = -1;
break;
}
pState = (IppsECESState_SM2*)malloc(pSize);
ipp_ret = ippsGFpECESInit_SM2(pEC, pState, pSize);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to init the SM2 ECC\n");
ret = -2;
break;
}
pEcScratchBuffer = (Ipp8u*)malloc(1024 * 10);
ipp_ret = ippsGFpECESSetKey_SM2(regPrivateKey, ephPublicKey, pState, pEC, pEcScratchBuffer);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to compute a shared secret\n");
ret = -3;
break;
}
ipp_ret = ippsGFpECESStart_SM2(pState);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to start the ECES SM2 encryption chain\n");
ret = -4;
break;
}
*cipher_text = (Ipp8u*)malloc(64 + message_len + 32); //encrypt/decrypt buffer = pubkey(64B) + message(len) + tag(32B)
memset(*cipher_text, 0, 64 + message_len + 32);
ipp_ret = ippsGFpECESEncrypt_SM2((Ipp8u*)message, *cipher_text, 64 + message_len + 32, pState);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to encrypt the plaintext data buffer\n");
ret = -5;
break;
}
ipp_ret = ippsGFpECESFinal_SM2(*cipher_text + 64 + message_len, 32, pState);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to complete the ECES SM2 encryption chain\n");
ret = -6;
break;
}
} while(0);
SAFE_FREE_HEAP(pEcScratchBuffer, 1024 * 10);
SAFE_FREE_HEAP(pState, pSize);
return ret;
}
/* SM2 decrypt(IEEE version) */
static int sm2_do_decrypt_ieee(const Ipp8u* cipher_text, int message_len, Ipp8u** plain_text, IppsECCPState *pECCPS, IppsBigNumState *ephPrivateKey, IppsECCPPointState *regPublicKey)
{
IppsGFpECState *pEC = pECCPS;
int pSize = 0;
IppsECESState_SM2 *pState = NULL;
Ipp8u* pEcScratchBuffer = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
do {
ipp_ret = ippsGFpECESGetSize_SM2(pEC, &pSize);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to get size of the SM2 ECC\n");
ret = -1;
break;
}
pState = (IppsECESState_SM2*)malloc(pSize);
ipp_ret = ippsGFpECESInit_SM2(pEC, pState, pSize);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to init the SM2 ECC\n");
ret = -2;
break;
}
pEcScratchBuffer = (Ipp8u*)malloc(1024 * 10);
ipp_ret = ippsGFpECESSetKey_SM2(ephPrivateKey, regPublicKey, pState, pEC, pEcScratchBuffer);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to compute a shared secret\n");
ret = -3;
break;
}
ipp_ret = ippsGFpECESStart_SM2(pState);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to start the ECES SM2 decryption chain\n");
ret = -4;
break;
}
*plain_text = (Ipp8u*)malloc(64 + message_len + 32);
memset(*plain_text, 0, 64 + message_len + 32);
ipp_ret = ippsGFpECESDecrypt_SM2(cipher_text, *plain_text, message_len, pState);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to decrypt the ciphertext data buffer\n");
ret = -5;
break;
}
ipp_ret = ippsGFpECESFinal_SM2(*plain_text + 64 + message_len, 32, pState);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to complete the ECES SM2 decryption chain\n");
ret = -6;
break;
}
} while(0);
SAFE_FREE_HEAP(pEcScratchBuffer, 1024 * 10);
SAFE_FREE_HEAP(pState, pSize);
return ret;
}
/* Encryption and decryption using ECC context for SM2 (IEEE version, standard is IEEE Std 1363A-2004) */
int ecall_sm2_encrypt_decrypt_ieee(void)
{
IppsECCPState *pECCPS = NULL;
IppsBigNumState *user1PrivateKey = NULL;
IppsECCPPointState *user1PublicKey = NULL;
IppsPRNGState *pPRNGS = NULL;
IppsBigNumState *user2PrivateKey = NULL;
IppsECCPPointState *user2PublicKey = NULL;
IppsECESState_SM2 *pState = NULL;
Ipp8u* pEcScratchBuffer = NULL;
Ipp8u *cipher_text = NULL, *plain_text = NULL;
IppStatus ipp_ret = ippStsNoErr;
int ret = 0;
char *message = "context need to be encrypted";
int message_len = strlen(message);
/*
Generate a SM2 random key
!!! THIS IS ONLY A SIMPLE SAMPLE OF RANDOM KEY GENERATION, YOU STILL HAVE TO GENERATE YOUR KEY WITH ENOUGH ENTROPY !!!
*/
unsigned char priKey[32] = {0};
if (secure_rand((unsigned int*)priKey, 32) != 0) {
printf("Error: fail to generate a SM2 random key\n");
SAFE_FREE_STACK(priKey, 32);
return -1;
}
do {
// 1. Create ECC context for SM2
pECCPS = new_ECC_sm2();
if (pECCPS == NULL) {
printf("Error: fail to create ECC context for SM2\n");
ret = -2;
break;
}
// 2. Create regular private key and public key
user1PrivateKey = new_BN(ordSize, 0);
if (user1PrivateKey == NULL) {
printf("Error: fail to create regular private key\n");
ret = -3;
break;
}
user1PublicKey = new_ECC_Point();
if (user1PublicKey == NULL) {
printf("Error: fail to create regular public key\n");
ret = -4;
break;
}
// 3. Generate regular private and public key pairs
ipp_ret = ippsSetOctString_BN(priKey, sizeof(priKey)-1, user1PrivateKey);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to convert octet string into BN value\n");
ret = -5;
break;
}
ipp_ret = ippsECCPPublicKey(user1PrivateKey, user1PublicKey, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to calculate regular public key\n");
ret = -6;
break;
}
// 4. Generate ephemeral private and public key pairs
pPRNGS = new_PRNG();
if (pPRNGS == NULL) {
printf("Error: fail to create pPRNGS\n");
ret = -7;
break;
}
user2PrivateKey = new_BN(ordSize, 0);
if (user2PrivateKey == NULL) {
printf("Error: fail to create ephemeral private key\n");
ret = -8;
break;
}
user2PublicKey = new_ECC_Point();
if (user2PublicKey == NULL) {
printf("Error: fail to create ephemeral public key\n");
ret = -9;
break;
}
ipp_ret = ippsECCPGenKeyPair(user2PrivateKey, user2PublicKey, pECCPS, ippsPRNGen, pPRNGS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to generate ephemeral key pairs\n");
ret = -10;
break;
}
ipp_ret = ippsECCPSetKeyPair(user2PrivateKey, user2PublicKey, ippFalse, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to set ephemeral key pairs\n");
ret = -11;
break;
}
// 5. Encrypt
ret = sm2_do_encrypt_ieee(message, message_len, &cipher_text, pECCPS, user1PrivateKey, user2PublicKey);
if (ret != 0) {
printf("Error: fail to encrypt.\n");
ret = -12;
break;
}
// 6. Decrypt
ret = sm2_do_decrypt_ieee(cipher_text, message_len, &plain_text, pECCPS, user2PrivateKey, user1PublicKey);
if (ret != 0) {
printf("Error: fail to decrypt.\n");
ret = -13;
break;
}
// 7. Compare decrypted message and original message
if(strlen((char*)message) != strlen((char*)plain_text) || memcmp(message, plain_text, strlen((char*)message)) != 0)
{
printf("Error: decrypted message does not match original message!\n");
ret = -14;
break;
}
} while(0);
// 8. Final, remove secret and release resources
// !!!Please clear secret including key/context related buffer/big number by manual!!!
free(pEcScratchBuffer);
free(pState);
free(user2PublicKey);
free(user2PrivateKey);
free(pPRNGS);
free(user1PublicKey);
free(user1PrivateKey);
free(pECCPS);
SAFE_FREE_STACK(priKey, 32);
return 0;
}
/* Compute a SM3 digest of a message. */
int ecall_sm3(void)
{
int ctxSize = 0;
IppsSM3State* pSM3 = NULL;
IppStatus status = ippStsNoErr;
unsigned char msg[] = "this is a test message";
unsigned char digest[32] = "";
unsigned char tag[32] = "";
int ret = 0;
do {
// 1. Init
// Get size of the SM3 context
status = ippsSM3GetSize(&ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to get size of SM3 context\n");
ret = -1;
break;
}
// Allocate the SM3 context
pSM3 = (IppsSM3State*)(malloc(ctxSize));
if (pSM3 == NULL) {
printf("Error: fail to allocate memory for SM3 context\n");
ret = -2;
break;
}
// Initialize the SM3 context
status = ippsSM3Init(pSM3);
if (status != ippStsNoErr) {
printf("Error: fail to initialize SM3 context\n");
ret = -3;
break;
}
// 2. Update
// Digest the message of specified length
status = ippsSM3Update(msg, strlen((char*)msg), pSM3);
if (status != ippStsNoErr) {
printf("Error: fail to digest the message of specified length\n");
ret = -4;
break;
}
// 3. GetTag
// Compute current SM3 digest value of the processed part of the message
status = ippsSM3GetTag(tag, sizeof(tag), pSM3);
if (status != ippStsNoErr) {
printf("Error: fail to compute current SM3 digest value of the processed part of the message\n");
ret = -5;
break;
}
// 4. Final
// Complete computation of the SM3 digest value
status = ippsSM3Final(digest, pSM3);
if (status != ippStsNoErr) {
printf("Error: fail to complete computation of the SM3 digest value\n");
ret = -6;
break;
}
} while(0);
//Remove secret and release resources
// !!!Please clear secret including key/context related buffer/big number by manual!!!
SAFE_FREE_HEAP(pSM3, ctxSize);
return ret;
}
/* SM4 block cipher mode(CBC) of operation. */
int ecall_sm4_cbc()
{
// Plain text
unsigned char plainText[16] = {
0xAA,0xAA,0xAA,0xAA,0xBB,0xBB,0xBB,0xBB,
0xCC,0xCC,0xCC,0xCC,0xDD,0xDD,0xDD,0xDD
};
/*
Generate a SM4 random secret key
!!! THIS IS ONLY A SIMPLE SAMPLE OF RANDOM KEY GENERATION, YOU STILL HAVE TO GENERATE YOUR KEY WITH ENOUGH ENTROPY !!!
*/
unsigned char key[16] = {0};
if (secure_rand((unsigned int*)key, 16) != 0) {
printf("Error: fail to generate a SM4 random secret key\n");
SAFE_FREE_STACK(key, 16);
return -1;
}
/*
Generate a SM4 random initialization vector(iv)
!!! THIS IS ONLY A SIMPLE SAMPLE OF RANDOM IV GENERATION, YOU STILL HAVE TO GENERATE YOUR IV WITH ENOUGH ENTROPY !!!
*/
unsigned char iv[16] = {0};
if (secure_rand((unsigned int*)iv, 16) != 0) {
printf("Error: fail to generate a SM4 random initialization vector\n");
SAFE_FREE_STACK(iv, 16);
return -2;
}
unsigned char encryptedText[16] = {};
unsigned char decryptedText[16] = {};
int ctxSize = 0;
IppsSMS4Spec* pSM4 = 0;
IppStatus status = ippStsNoErr, status1 = ippStsNoErr, status2 = ippStsNoErr;
int ret = 0;
do {
// 1. Get size needed for SM4 context structure
status = ippsSMS4GetSize(&ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to get size of SM4 context\n");
ret = -3;
break;
}
// 2. Allocate memory for SM4 context structure
pSM4 = (IppsSMS4Spec*)malloc(ctxSize);
if (pSM4 == NULL) {
printf("Error: fail to allocate memory for SM4 context\n");
ret = -4;
break;
}
// 3. Initialize SM4 context
status = ippsSMS4Init(key, sizeof(key), pSM4, ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to initialize SM4 context\n");
ret = -5;
break;
}
// 4. CBC Encryption and decryption
status1 = ippsSMS4EncryptCBC(plainText, encryptedText, sizeof(plainText), pSM4, iv);
if (status1 != ippStsNoErr) {
printf("Error: fail to encrypt the plaintext\n");
ret = -6;
break;
}
status2 = ippsSMS4DecryptCBC(encryptedText, decryptedText, sizeof(encryptedText), pSM4, iv);
if (status2 != ippStsNoErr) {
printf("Error: fail to decrypt the ciphertext\n");
ret = -7;
break;
}
// 5. Compare original and decrypted text
if (memcmp(plainText, decryptedText, sizeof(plainText)) != 0) {
printf("Error: decrypted text is different from plaintext\n");
ret = -8;
break;
}
} while (0);
// 6. Remove secret and release resources
// !!!Please clear secret including key/context related buffer/big number by manual!!!
SAFE_FREE_HEAP(pSM4, ctxSize);
SAFE_FREE_STACK(key, 16);
SAFE_FREE_STACK(iv, 16);
return ret;
}
/* SM4 counter mode(CTR) of operation. */
int ecall_sm4_ctr()
{
// message to be encrypted
unsigned char msg[] = "the message to be encrypted";
/*
Generate a SM4 random secret key
!!! THIS IS ONLY A SIMPLE SAMPLE OF RANDOM KEY GENERATION, YOU STILL HAVE TO GENERATE YOUR KEY WITH ENOUGH ENTROPY !!!
*/
unsigned char key[16] = {0};
if (secure_rand((unsigned int*)key, 16) != 0) {
printf("Error: fail to generate a SM4 random secret key\n");
SAFE_FREE_STACK(key, 16);
return -1;
}
/*
Generate a SM4 random initial counter
!!! THIS IS ONLY A SIMPLE SAMPLE OF RANDOM COUNTER GENERATION, YOU STILL HAVE TO GENERATE YOUR COUNTER WITH ENOUGH ENTROPY !!!
*/
unsigned char ctr0[16] = {0};
if (secure_rand((unsigned int*)ctr0, 16) != 0) {
printf("Error: fail to generate a SM4 random initial counter\n");
SAFE_FREE_STACK(ctr0, 16);
return -2;
}
// counter
unsigned char ctr[16];
unsigned char etext[sizeof(msg)];
unsigned char dtext[sizeof(etext)];
int ctxSize = 0;
IppsSMS4Spec* pSM4 = 0;
IppStatus status = ippStsNoErr, status1 = ippStsNoErr, status2 = ippStsNoErr;
int ret = 0;
do {
// 1. Get size needed for SM4 context structure
status = ippsSMS4GetSize(&ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to get size of SM4 context\n");
ret = -3;
break;
}
// 2. Allocate memory for SM4 context structure
pSM4 = (IppsSMS4Spec*)malloc(ctxSize);
if (pSM4 == NULL) {
printf("Error: fail to allocate memory for SM4 context\n");
ret = -4;
break;
}
// 3. Initialize SM4 context
status = ippsSMS4Init(key, sizeof(key), pSM4, ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to initialize SM4 context\n");
ret = -5;
break;
}
// 4. Encryption and decryption
// Initialize counter before encryption
memcpy(ctr, ctr0, sizeof(ctr));
// Encrypt message
status1 = ippsSMS4EncryptCTR(msg, etext, sizeof(msg), pSM4, ctr, 64);
if (status1 != ippStsNoErr) {
printf("Erro: fail to encrypt the plaintext\n");
ret = -6;
break;
}
// Initialize counter before decryption
memcpy(ctr, ctr0, sizeof(ctr));
// Decrypt message
status2 = ippsSMS4DecryptCTR(etext, dtext, sizeof(etext), pSM4, ctr, 64);
if (status2 != ippStsNoErr) {
printf("Error: fail to decrypt the ciphertext\n");
ret = -7;
break;
}
// 5. Compare original message and decrypted text
if (memcmp(msg, dtext, sizeof(msg)) != 0) {
printf("Error: decrypted text is different from plaintext\n");
ret = -8;
break;
}
} while (0);
// 6. Remove secret and release resources
// !!!Please clear secret including key/context related buffer/big number by manual!!!
SAFE_FREE_HEAP(pSM4, ctxSize);
SAFE_FREE_STACK(key, 16);
SAFE_FREE_STACK(ctr0, 16);
return ret;
}