mirror of
https://github.com/intel/linux-sgx
synced 2026-06-08 14:49:32 +00:00
321a6580fb
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>
998 lines
27 KiB
C++
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;
|
|
}
|