Files
Li, Xun 321a6580fb Linux 2.16 Open Source Gold Release
Upgraded to OpenSSL 1.1.1m.
Provided RA-TLS (Remote Attestation based Transport Layer Security) APIs and
  Samples.
Supported PKRU (Protection Key rights Register) in Enclave.
Added APIs of SHA384 and VerifyReport2 to support TDX.
Enhanced QPL (Quote Provider Library) to support caching Intel PCK
  (Provisioning Certificate Key) certificate chain in local memory, or
  retrieving Intel PCK cert chain from local HTTP/S address.
Upgraded Intel ECDSA Quote Verification Enclave to integrate SgxSSL/OpenSSL
  version 1.1.1m.
Introduced Intel ID enclave for QE identity generation.
Fixed bugs.

Signed-off-by: Li, Xun <xun.li@intel.com>
2022-04-06 12:06:27 +08:00

998 lines
27 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 <ippcp.h> /* ipp library */
#ifndef SAFE_FREE
#define SAFE_FREE(ptr, size) do {if (NULL != (ptr)) {memset_s(ptr, size, 0, size); free(ptr); (ptr)=NULL;}} 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(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(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(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(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;
}
/* Set up an array of 32-bit items with random number */
static int rand(void)
{
int num = 0;
sgx_read_rand((unsigned char*)&num, sizeof(int));
return num;
}
static unsigned int* rand32(unsigned int* pX, int size)
{
for(int n = 0; n < size; n++)
pX[n] = rand();
return pX;
}
/* 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(pPRNG, size);
return NULL;
}
seed = (unsigned int*)malloc(seedSize);
augm = (unsigned int*)malloc(seedSize);
ipp_ret = ippsPRNGSetSeed(pBN=new_BN(seedSize, rand32(seed, seedSize)), pPRNG);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to set the seed value of PRNG\n");
SAFE_FREE(pPRNG, size);
SAFE_FREE(pBN, sizeof(pBN));
SAFE_FREE(pBN, sizeof(augm));
SAFE_FREE(pBN, sizeof(seed));
return NULL;
}
SAFE_FREE(pBN, sizeof(pBN));
ipp_ret = ippsPRNGSetAugment(pBN=new_BN(seedSize, rand32(augm, seedSize)), pPRNG);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to set the entropy augmentation of PRNG\n");
SAFE_FREE(pPRNG, size);
SAFE_FREE(pBN, sizeof(pBN));
SAFE_FREE(pBN, sizeof(augm));
SAFE_FREE(pBN, sizeof(seed));
return NULL;
}
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(hash_handle, sizeof(hash_handle));
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(hash_handle, sizeof(hash_handle));
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
SAFE_FREE(pY, sizeof(pY));
SAFE_FREE(pX, sizeof(pX));
SAFE_FREE(pMsg, sizeof(pMsg));
SAFE_FREE(regPublicKey, sizeof(regPublicKey));
SAFE_FREE(ephPublicKey, sizeof(ephPublicKey));
SAFE_FREE(ephPrivateKey, sizeof(ephPrivateKey));
SAFE_FREE(pPRNGS, sizeof(pPRNGS));
SAFE_FREE(pECCPS, sizeof(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 resources
SAFE_FREE(pY, sizeof(pY));
SAFE_FREE(pX, sizeof(pX));
SAFE_FREE(pMsg, sizeof(pMsg));
SAFE_FREE(pECCPS, sizeof(pECCPS));
return ret;
}
/* Signing and verification using ECC context for SM2 */
int ecall_sm2(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";
unsigned char priKey[] = "\xd0\x91\x56\x73\x30\x17\xbd\xad\x80\x9f\xd9\xbb\xd8\xc6\x93\xf6\x02\x30\x59\x31\x69\xb6\xf9\x4a\xaf\x1c\x8e\xe1\x38\xcc\x99\xb5";
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 = -1;
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 = -2;
break;
}
regPublicKey = new_ECC_Point();
if (regPublicKey == NULL) {
printf("Error: fail to create regular public key\n");
ret = -3;
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 = -4;
break;
}
ipp_ret = ippsECCPPublicKey(regPrivateKey, regPublicKey, pECCPS);
if (ipp_ret != ippStsNoErr) {
printf("Error: fail to calculate regular public key\n");
ret = -5;
break;
}
// 4. Create signX and signY
signX = new_BN(ordSize, 0);
if (signX == NULL) {
printf("Error: fail to create signX\n");
ret = -6;
break;
}
signY = new_BN(ordSize, 0);
if (signY == NULL) {
printf("Error: fail to create signY\n");
ret = -7;
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 = -8;
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 = -9;
break;
}
} while(0);
// 7. Final, remove secret and release resources
SAFE_FREE(signY, sizeof(signY));
SAFE_FREE(signX, sizeof(signX));
SAFE_FREE(regPublicKey, sizeof(regPublicKey));
SAFE_FREE(regPrivateKey, sizeof(regPrivateKey));
SAFE_FREE(pECCPS, sizeof(pECCPS));
return ret;
}
/* 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
SAFE_FREE(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
};
// Secret key
unsigned char key[16] = {
0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF,
0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10
};
// Initialization vector
unsigned char iv[16] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
};
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 = -1;
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 = -2;
break;
}
// 3. Initialize SM4 context
status = ippsSMS4Init(key, sizeof(key), pSM4, ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to initialize SM4 context\n");
ret = -3;
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 = -4;
break;
}
status2 = ippsSMS4DecryptCBC(encryptedText, decryptedText, sizeof(encryptedText), pSM4, iv);
if (status2 != ippStsNoErr) {
printf("Error: fail to decrypt the ciphertext\n");
ret = -5;
break;
}
// 5. Compare original and decrypted text
if (memcmp(plainText, decryptedText, sizeof(plainText)) != 0) {
printf("Error: decrypted text is different from plaintext\n");
ret = -6;
break;
}
} while (0);
// 6. Remove secret and release resources
SAFE_FREE(pSM4, ctxSize);
return ret;
}
/* SM4 counter mode(CTR) of operation. */
int ecall_sm4_ctr()
{
// message to be encrypted
unsigned char msg[] = "the message to be encrypted";
// secret key
unsigned char key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15";
// initial counter
unsigned char ctr0[] = "\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00";
// 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 = -1;
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 = -2;
break;
}
// 3. Initialize SM4 context
status = ippsSMS4Init(key, sizeof(key), pSM4, ctxSize);
if (status != ippStsNoErr) {
printf("Error: fail to initialize SM4 context\n");
ret = -3;
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 = -4;
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 = -5;
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 = -6;
break;
}
} while (0);
// 6. Remove secret and release resources
SAFE_FREE(pSM4, ctxSize);
return ret;
}