///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004 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 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 INTEL 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 "stdafx.h"
#include <ipp.h>

#include "rsa.h"

int gen_t(int kp)
{
    int t;

	t = 27;
	if(kp>150) t = 18;
	if(kp>200) t = 15;
	if(kp>250) t = 12;
	if(kp>300) t = 9;
	if(kp>350) t = 8;
	if(kp>400) t = 7;
	if(kp>450) t = 6;
    return t;
}

/*
void PrintKey(IppsRSA*)
{
	Ipp32u *pKeyData = ippsMalloc_32u(keyLen_);
	int keyLen;
	ippsRSAKeyGet(pKeyData, &keyLen, IppsRSAKeyD,
				  pRSADecKey_);
	for (i = 0; i<keyLen; i++)
		printf("%x ", pKeyData[i]);
	printf("\n");
	ippsRSAKeyGet(pKeyData, &keyLen, IppsRSAKeyE,
				  pRSADecKey_);
	for (i = 0; i<keyLen; i++)
		printf("%x ", pKeyData[i]);
	printf("\n");
	ippsFree(pKeyData);
}
*/

void RSAKeyGen::GenerateKeys()
{
	int sign, i;
	Ipp32u pSeed[10];
	BigNum content(keyLen_/2), seed(10),
		publicKey((keyLen_+31)/32);

	// Initialize publicKey to reasonable value
	publicKey.Zero();
	publicKey.Randomize(keyLen_/32);

	// Generate some random data for content and seed
	content.Randomize();
	seed.Randomize();
	seed.Get(&sign, pSeed);
	
	IppStatus st = ippsRSAKeyGen(publicKey.GetBN(),
		content.GetBN(), pSeed, gen_t(primeLen_),
		keyLen_, primeLen_, pRSADecKey_);

	//if (st != 0)
	//printf("st = %s\n", ippCoreGetStatusString(st));

	int length;
	Ipp32u *pData = ippsMalloc_32u((keyLen_+31)/32);
	ippsRSAKeyGet(pData, &length, IppsRSAKeyN,
		pRSADecKey_);
	ippsRSAKeySet(pData, length, IppsRSAKeyN,
		pRSAEncKey_);
	ippsRSAKeyGet(pData, &length, IppsRSAKeyE,
		pRSADecKey_);
	ippsRSAKeySet(pData, length, IppsRSAKeyE,
		pRSAEncKey_);
}

RSAKeyGen::~RSAKeyGen()
{
	if (pRSAEncKey_) ippsFree(pRSAEncKey_);
	if (pRSADecKey_) ippsFree(pRSADecKey_);
}

IppStatus myRSAInitAlloc(IppsExpMethod method,
	int k, int kp, IppsRSAType flag, IppsRSA **pKey)
{
	int bufSize[4];

	ippsRSABufferSizes(method, k, kp,
		flag, &bufSize[0], &bufSize[1], &bufSize[2],
		&bufSize[3]);
	Ipp32u* pBuf =
		ippsMalloc_32u(bufSize[0]+bufSize[1]+bufSize[2]+
		bufSize[3]);

	*pKey = (IppsRSA*)pBuf;
	return ippsRSAInit(method, k, kp, flag,
		pBuf+bufSize[3], pBuf+bufSize[3]+bufSize[0],
		pBuf+bufSize[3]+bufSize[0]+bufSize[1], *pKey);
}

RSAKeyGen::RSAKeyGen(int keyLen, int primeLen):
	keyLen_(keyLen), primeLen_(primeLen)
{
	myRSAInitAlloc(IppsSlidingWindows,
		keyLen_, primeLen_, IppsRSAPrivate, &pRSADecKey_);
	myRSAInitAlloc(IppsSlidingWindows,
		keyLen_, primeLen_, IppsRSAPublic, &pRSAEncKey_);
}
