Files
Angie Chinchilla 9441de4c38 Initial release of Intel SGX for Linux.
This release is used in conjunction with the linux-sgx-driver Intial release:
https://github.com/01org/linux-sgx-driver
commit-id: 0e865ce5e6b297a787bcdc12d98bada8174be6d7

Intel-id: 33399

Signed-off-by: Angie Chinchilla <angie.v.chinchilla@intel.com>
2016-06-23 18:51:53 -04:00

352 lines
12 KiB
C++

/*
* Copyright (C) 2011-2016 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.
*
*/
/**
* File:
* ipp_rsa_key.cpp
*Description:
* Wrapper for rsa key operation functions (public key generation and free excluded)
*
*/
#include "ipp_wrapper.h"
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
extern "C" int memset_s(void *s, size_t smax, int c, size_t n);
static IppStatus newPRNG(IppsPRNGState **pRandGen)
{
if(pRandGen == NULL)
return ippStsBadArgErr;
int ctxSize = 0;
IppStatus error_code = ippsPRNGGetSize(&ctxSize);
if(error_code != ippStsNoErr)
return error_code;
IppsPRNGState* pCtx = (IppsPRNGState *) malloc(ctxSize);
if(pCtx == NULL)
return ippStsMemAllocErr;
error_code = ippsPRNGInit(160, pCtx);
if(error_code != ippStsNoErr)
{
free(pCtx);
return error_code;
}
*pRandGen = pCtx;
return error_code;
}
static IppStatus newPrimeGen(int nMaxBits, IppsPrimeState ** pPrimeG)
{
if(pPrimeG == NULL || nMaxBits <= 0 )
return ippStsBadArgErr;
int ctxSize = 0;
IppStatus error_code = ippsPrimeGetSize(nMaxBits, &ctxSize);
if(error_code != ippStsNoErr)
return error_code;
IppsPrimeState* pCtx = (IppsPrimeState *) malloc(ctxSize);
if(pCtx == NULL)
return ippStsMemAllocErr;
error_code = ippsPrimeInit(nMaxBits, pCtx);
if(error_code != ippStsNoErr)
{
free(pCtx);
return error_code;
}
*pPrimeG = pCtx;
return error_code;
}
extern "C" IppStatus create_rsa_priv2_key(int p_byte_size, const Ipp32u *p, const Ipp32u *q,
const Ipp32u *dmp1, const Ipp32u *dmq1, const Ipp32u *iqmp,
IppsRSAPrivateKeyState **new_pri_key2)
{
IppsRSAPrivateKeyState *p_rsa2 = NULL;
IppsBigNumState *p_p = NULL, *p_q = NULL, *p_dmp1 = NULL, *p_dmq1 = NULL, *p_iqmp = NULL;
int rsa2_size = 0;
if(p_byte_size <= 0 || p == NULL || q == NULL || dmp1 == NULL || dmq1 == NULL || iqmp == NULL || new_pri_key2 == NULL)
{
return ippStsBadArgErr;
}
IppStatus error_code = ippStsNoErr;
do{
error_code = newBN(p, p_byte_size, &p_p);
ERROR_BREAK(error_code);
error_code = newBN(q, p_byte_size, &p_q);
ERROR_BREAK(error_code);
error_code = newBN(dmp1, p_byte_size, &p_dmp1);
ERROR_BREAK(error_code);
error_code = newBN(dmq1, p_byte_size, &p_dmq1);
ERROR_BREAK(error_code);
error_code = newBN(iqmp, p_byte_size, &p_iqmp);
ERROR_BREAK(error_code);
error_code = ippsRSA_GetSizePrivateKeyType2(p_byte_size * 8, p_byte_size * 8, &rsa2_size);
ERROR_BREAK(error_code);
p_rsa2 = (IppsRSAPrivateKeyState *)malloc(rsa2_size);
NULL_BREAK(p_rsa2);
error_code = ippsRSA_InitPrivateKeyType2(p_byte_size * 8, p_byte_size * 8, p_rsa2, rsa2_size);
ERROR_BREAK(error_code);
error_code = ippsRSA_SetPrivateKeyType2(p_p, p_q, p_dmp1, p_dmq1, p_iqmp, p_rsa2);
ERROR_BREAK(error_code);
}while(0);
secure_free_BN(p_p, p_byte_size);
secure_free_BN(p_q, p_byte_size);
secure_free_BN(p_dmp1, p_byte_size);
secure_free_BN(p_dmq1, p_byte_size);
secure_free_BN(p_iqmp, p_byte_size);
if(error_code != ippStsNoErr || p_rsa2 == NULL)
{
if(error_code == ippStsNoErr )
error_code = ippStsMemAllocErr;
/* Clear sensitive data before free */
secure_free_rsa_pri2_key(p_byte_size, p_rsa2);
return error_code;
}
*new_pri_key2 = p_rsa2;
return error_code;
}
extern "C" IppStatus create_rsa_priv1_key(int n_byte_size, int d_byte_size, const Ipp32u *n, const Ipp32u *d, IppsRSAPrivateKeyState **new_pri_key1)
{
IppsRSAPrivateKeyState *p_rsa1 = NULL;
IppsBigNumState *p_n = NULL, *p_d = NULL;
int rsa1_size = 0;
if(n_byte_size <= 0 || d_byte_size <= 0 || n == NULL || d == NULL || new_pri_key1 == NULL)
{
return ippStsBadArgErr;
}
IppStatus error_code = ippStsNoErr;
do{
error_code = newBN(n, n_byte_size, &p_n);
ERROR_BREAK(error_code);
error_code = newBN(d, d_byte_size, &p_d);
ERROR_BREAK(error_code);
error_code = ippsRSA_GetSizePrivateKeyType1(n_byte_size * 8, d_byte_size * 8, &rsa1_size);
ERROR_BREAK(error_code);
p_rsa1 = (IppsRSAPrivateKeyState *)malloc(rsa1_size);
NULL_BREAK(p_rsa1);
error_code = ippsRSA_InitPrivateKeyType1(n_byte_size * 8, d_byte_size * 8, p_rsa1, rsa1_size);
ERROR_BREAK(error_code);
error_code = ippsRSA_SetPrivateKeyType1(p_n, p_d, p_rsa1);
ERROR_BREAK(error_code);
}while(0);
secure_free_BN(p_n, n_byte_size);
secure_free_BN(p_d, d_byte_size);
if(error_code != ippStsNoErr || p_rsa1 == NULL)
{
if(error_code == ippStsNoErr )
error_code = ippStsMemAllocErr;
/* Clear sensitive data before free */
secure_free_rsa_pri1_key(n_byte_size, d_byte_size, p_rsa1);
return error_code;
}
*new_pri_key1 = p_rsa1;
return error_code;
}
extern "C" IppStatus create_validate_rsa_key_pair(int n_byte_size, int e_byte_size, const Ipp32u *n, const Ipp32u *d, const Ipp32u *e, const Ipp32u *p, const Ipp32u *q,
const Ipp32u *dmp1, const Ipp32u *dmq1, const Ipp32u *iqmp,
IppsRSAPrivateKeyState **new_pri_key, IppsRSAPublicKeyState **new_pub_key, int *validate_result)
{
if(n_byte_size <= 0 || e_byte_size <= 0 || n == NULL || d == NULL || e == NULL ||
p == NULL || q == NULL || dmp1 == NULL || dmq1 == NULL || iqmp == NULL || new_pri_key == NULL ||
new_pub_key == NULL || validate_result == NULL)
{
return ippStsBadArgErr;
}
IppsRSAPrivateKeyState *p_pri_key1 = NULL, *p_pri_key2 = NULL;
IppsRSAPublicKeyState *p_pub_key = NULL;
IppStatus error_code = ippStsNoErr;
IppsPRNGState *p_rand = NULL;
IppsPrimeState *p_prime = NULL;
Ipp8u * scratch_buffer = NULL;
int result = IPP_IS_VALID;
int max_size = 0, pri1_size = 0, pri2_size = 0, pub_size = 0;
do
{
/* Generate the pri_key1, pri_key2 and pub_key */
error_code = create_rsa_priv1_key(n_byte_size, n_byte_size, n, d, &p_pri_key1);
ERROR_BREAK(error_code);
error_code = create_rsa_priv2_key(n_byte_size/2, p, q, dmp1, dmq1, iqmp, &p_pri_key2);
ERROR_BREAK(error_code);
error_code = create_rsa_pub_key(n_byte_size, e_byte_size, n, e, &p_pub_key);
ERROR_BREAK(error_code);
/* Generate random state and prime state */
error_code = newPRNG(&p_rand);
ERROR_BREAK(error_code);
error_code = newPrimeGen(n_byte_size * 8 / 2, &p_prime);
ERROR_BREAK(error_code);
/* Allocate scratch buffer */
error_code = ippsRSA_GetBufferSizePrivateKey(&pri1_size, p_pri_key1);
ERROR_BREAK(error_code);
error_code = ippsRSA_GetBufferSizePrivateKey(&pri2_size, p_pri_key2);
ERROR_BREAK(error_code);
max_size = MAX(pri1_size, pri2_size);
error_code = ippsRSA_GetBufferSizePublicKey(&pub_size, p_pub_key);
ERROR_BREAK(error_code);
max_size = MAX(max_size, pub_size);
scratch_buffer = (Ipp8u *)malloc(max_size);
NULL_BREAK(scratch_buffer);
memset(scratch_buffer, 0, max_size);
/* Validate keys */
error_code = ippsRSA_ValidateKeys(&result, p_pub_key, p_pri_key2, p_pri_key1, scratch_buffer, 10, p_prime, ippsPRNGen, p_rand);
ERROR_BREAK(error_code);
}while(0);
SAFE_FREE_MM(p_rand);
SAFE_FREE_MM(p_prime);
secure_free_rsa_pri2_key(n_byte_size/2, p_pri_key2);
if(error_code != ippStsNoErr || scratch_buffer == NULL)
{
if(error_code == ippStsNoErr)
error_code = ippStsMemAllocErr;
SAFE_FREE_MM(scratch_buffer);
secure_free_rsa_pri1_key(n_byte_size, n_byte_size, p_pri_key1);
secure_free_rsa_pub_key(n_byte_size, e_byte_size, p_pub_key);
return error_code;
}
SAFE_FREE_MM(scratch_buffer);
*new_pri_key = p_pri_key1;
*new_pub_key = p_pub_key;
*validate_result = result;
return error_code;
}
extern "C" IppStatus get_pub_key(const IppsRSAPublicKeyState *pub_key, int *e_byte_size, Ipp32u *e, int *n_byte_size, Ipp32u *n)
{
IppStatus error_code = ippStsNoErr;
IppsBigNumState *p_n=NULL, *p_e=NULL;
if(!pub_key || !e_byte_size || !e || !n_byte_size || !n)
{
return ippStsBadArgErr;
}
do
{
error_code = newBN(NULL, SE_KEY_SIZE, &p_n);
ERROR_BREAK(error_code);
error_code = newBN(NULL, sizeof(Ipp32u), &p_e);
ERROR_BREAK(error_code);
error_code = ippsRSA_GetPublicKey(p_n, p_e, pub_key);
ERROR_BREAK(error_code);
IppsBigNumSGN sgn = IppsBigNumPOS;
Ipp32u *pdata = NULL;
int length_in_bit = 0;
error_code = ippsRef_BN(&sgn, &length_in_bit, &pdata, p_n);
ERROR_BREAK(error_code);
*n_byte_size = ROUND_TO(length_in_bit, 8)/8;
memset(n, 0, *n_byte_size);
memcpy(n, pdata, ROUND_TO(length_in_bit, 8)/8);
error_code = ippsRef_BN(&sgn, &length_in_bit, &pdata, p_e);
ERROR_BREAK(error_code);
*e_byte_size = ROUND_TO(length_in_bit, 8)/8;
memset(e, 0, *e_byte_size);
memcpy(e, pdata, ROUND_TO(length_in_bit, 8)/8);
} while(0);
secure_free_BN(p_n, SE_KEY_SIZE);
secure_free_BN(p_e, sizeof(Ipp32u));
return error_code;
}
extern "C" void secure_free_rsa_pri1_key(int n_byte_size, int d_byte_size, IppsRSAPrivateKeyState *pri_key1)
{
if(n_byte_size <= 0 || d_byte_size <= 0 || pri_key1 == NULL)
{
if(pri_key1)
free(pri_key1);
return;
}
int rsa1_size = 0;
if(ippsRSA_GetSizePrivateKeyType1(n_byte_size * 8, d_byte_size * 8, &rsa1_size) != ippStsNoErr)
{
free(pri_key1);
return;
}
/* Clear the buffer before free. */
memset_s(pri_key1, rsa1_size, 0, rsa1_size);
free(pri_key1);
return;
}
extern "C" void secure_free_rsa_pri2_key(int p_byte_size, IppsRSAPrivateKeyState *pri_key2)
{
if(p_byte_size <= 0 || pri_key2 == NULL)
{
if(pri_key2)
free(pri_key2);
return;
}
int rsa2_size = 0;
if(ippsRSA_GetSizePrivateKeyType2(p_byte_size * 8, p_byte_size * 8, &rsa2_size) != ippStsNoErr)
{
free(pri_key2);
return;
}
/* Clear the buffer before free. */
memset_s(pri_key2, rsa2_size, 0, rsa2_size);
free(pri_key2);
return;
}