/****************************************************************************
*																			*
*				cryptlib ECC Key Generation/Checking Routines				*
*			Copyright Matthias Bruestle and Peter Gutmann 2006-2007			*
*																			*
****************************************************************************/

#define PKC_CONTEXT		/* Indicate that we're working with PKC context */
#if defined( INC_ALL )
  #include "crypt.h"
  #include "context.h"
  #include "keygen.h"
#else
  #include "crypt.h"
  #include "context/context.h"
  #include "context/keygen.h"
#endif /* Compiler-specific includes */

#ifdef USE_ECC

/****************************************************************************
*																			*
*								Fixed ECC Parameters						*
*																			*
****************************************************************************/

/* We always used pre-generated parameters both because it's unlikely that
   anyone will ever decide to generate nonstandard parameters when standard
   ones are available (or at least no sane person, no doubt every little
   standards committee wanting to make their mark will feel the need to
   have their own personal incompatible parameters).  In addition using
   externally-generated parameters can (as for DSA) lead to problems with
   maliciously-generated paramters (see "CM-Curves with good Cryptography
   Properties", Neal Koblitz, Proceedings of Crypto'91, p.279), and finally
   (also like DSA) it can lead to problems with parameter-substitution 
   attacks (see "Digital Signature Schemes with Domain Parameters", Serge
   Vaudenay, Proceedings of ACISP'04, p.188) */

typedef struct {
	ECC_PARAM_TYPE paramType;
	const int curveSizeBits;
	const BYTE *p;
	const BYTE *a;
	const BYTE *b;
	const BYTE *gx;
	const BYTE *gy;
	const BYTE *r;
	} ECC_DOMAIN_PARAMS;

static const ECC_DOMAIN_PARAMS domainParamTbl[] = {
	/* NIST P192, X9.62 P192v1 */
	{ ECC_PARAM_P192, 192,
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC",
	  "\x64\x21\x05\x19\xE5\x9C\x80\xE7\x0F\xA7\xE9\xAB\x72\x24\x30\x49" \
		"\xFE\xB8\xDE\xEC\xC1\x46\xB9\xB1",
	  "\x18\x8D\xA8\x0E\xB0\x30\x90\xF6\x7C\xBF\x20\xEB\x43\xA1\x88\x00" \
		"\xF4\xFF\x0A\xFD\x82\xFF\x10\x12",
	  "\x07\x19\x2B\x95\xFF\xC8\xDA\x78\x63\x10\x11\xED\x6B\x24\xCD\xD5" \
		"\x73\xF9\x77\xA1\x1E\x79\x48\x11",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x99\xDE\xF8\x36" \
		"\x14\x6B\xC9\xB1\xB4\xD2\x28\x31" },
#if 0
	/* X9.62 P192v2 */
	{ ECC_PARAM_P192v2, 192,
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC",
	  "\xCC\x22\xD6\xDF\xB9\x5C\x6B\x25\xE4\x9C\x0D\x63\x64\xA4\xE5\x98" \
		"\x0C\x39\x3A\xA2\x16\x68\xD9\x53",
	  "\xEE\xA2\xBA\xE7\xE1\x49\x78\x42\xF2\xDE\x77\x69\xCF\xE9\xC9\x89" \
		"\xC0\x72\xAD\x69\x6F\x48\x03\x4A",
	  "\x65\x74\xD1\x1D\x69\xB6\xEC\x7A\x67\x2B\xB8\x2A\x08\x3D\xF2\xF2" \
		"\xB0\x84\x7D\xE9\x70\xB2\xDE\x15",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\x5F\xB1\xA7\x24" \
		"\xDC\x80\x41\x86\x48\xD8\xDD\x31" },
	/* X9.62 P192v3 */
	{ ECC_PARAM_P192v3, 192,
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC",
	  "\x22\x12\x3D\xC2\x39\x5A\x05\xCA\xA7\x42\x3D\xAE\xCC\xC9\x47\x60" \
		"\xA7\xD4\x62\x25\x6B\xD5\x69\x16",
	  "\x7D\x29\x77\x81\x00\xC6\x5A\x1D\xA1\x78\x37\x16\x58\x8D\xCE\x2B" \
		"\x8B\x4A\xEE\x8E\x22\x8F\x18\x96",
	  "\x38\xA9\x0F\x22\x63\x73\x37\x33\x4B\x49\xDC\xB6\x6A\x6D\xC8\xF9" \
		"\x97\x8A\xCA\x76\x48\xA9\x43\xB0",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7A\x62\xD0\x31" \
		"\xC8\x3F\x42\x94\xF6\x40\xEC\x13" },
	/* NIST P224 */
	{ ECC_PARAM_P224, 224,
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE",
	  "\xB4\x05\x0A\x85\x0C\x04\xB3\xAB\xF5\x41\x32\x56\x50\x44\xB0\xB7" \
		"\xD7\xBF\xD8\xBA\x27\x0B\x39\x43\x23\x55\xFF\xB4",
	  "\xB7\x0E\x0C\xBD\x6B\xB4\xBF\x7F\x32\x13\x90\xB9\x4A\x03\xC1\xD3" \
		"\x56\xC2\x11\x22\x34\x32\x80\xD6\x11\x5C\x1D\x21",
	  "\xBD\x37\x63\x88\xB5\xF7\x23\xFB\x4C\x22\xDF\xE6\xCD\x43\x75\xA0" \
		"\x5A\x07\x47\x64\x44\xD5\x81\x99\x85\x00\x7E\x34",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\xA2" \
		"\xE0\xB8\xF0\x3E\x13\xDD\x29\x45\x5C\x5C\x2A\x3D" },
	/* X9.62 P239v1 */
	{ ECC_PARAM_P239, 239,
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\xFF\xFF\xFF" \
		"\xFF\xFF\x80\x00\x00\x00\x00\x00\x7F\xFF\xFF\xFF\xFF\xFF",
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\xFF\xFF\xFF" \
		"\xFF\xFF\x80\x00\x00\x00\x00\x00\x7F\xFF\xFF\xFF\xFF\xFC",
	  "\x6B\x01\x6C\x3B\xDC\xF1\x89\x41\xD0\xD6\x54\x92\x14\x75\xCA\x71" \
		"\xA9\xDB\x2F\xB2\x7D\x1D\x37\x79\x61\x85\xC2\x94\x2C\x0A",
	  "\x0F\xFA\x96\x3C\xDC\xA8\x81\x6C\xCC\x33\xB8\x64\x2B\xED\xF9\x05" \
		"\xC3\xD3\x58\x57\x3D\x3F\x27\xFB\xBD\x3B\x3C\xB9\xAA\xAF",
	  "\x7D\xEB\xE8\xE4\xE9\x0A\x5D\xAE\x6E\x40\x54\xCA\x53\x0B\xA0\x46" \
		"\x54\xB3\x68\x18\xCE\x22\x6B\x39\xFC\xCB\x7B\x02\xF1\xAE",
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\xFF\xFF\x9E" \
		"\x5E\x9A\x9F\x5D\x90\x71\xFB\xD1\x52\x26\x88\x90\x9D\x0B" },
	/* X9.62 P239v2 */
	{ ECC_PARAM_P239v2, 239,
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\xFF\xFF\xFF" \
		"\xFF\xFF\x80\x00\x00\x00\x00\x00\x7F\xFF\xFF\xFF\xFF\xFF",
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\xFF\xFF\xFF" \
		"\xFF\xFF\x80\x00\x00\x00\x00\x00\x7F\xFF\xFF\xFF\xFF\xFC",
	  "\x61\x7F\xAB\x68\x32\x57\x6C\xBB\xFE\xD5\x0D\x99\xF0\x24\x9C\x3F" \
		"\xEE\x58\xB9\x4B\xA0\x03\x8C\x7A\xE8\x4C\x8C\x83\x2F\x2C",
	  "\x38\xAF\x09\xD9\x87\x27\x70\x51\x20\xC9\x21\xBB\x5E\x9E\x26\x29" \
		"\x6A\x3C\xDC\xF2\xF3\x57\x57\xA0\xEA\xFD\x87\xB8\x30\xE7",
	  "\x5B\x01\x25\xE4\xDB\xEA\x0E\xC7\x20\x6D\xA0\xFC\x01\xD9\xB0\x81" \
		"\x32\x9F\xB5\x55\xDE\x6E\xF4\x60\x23\x7D\xFF\x8B\xE4\xBA",
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x00\x00\xCF" \
		"\xA7\xE8\x59\x43\x77\xD4\x14\xC0\x38\x21\xBC\x58\x20\x63" },
	/* X9.62 P239v3 */
	{ ECC_PARAM_P239v3, 239,
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\xFF\xFF\xFF" \
		"\xFF\xFF\x80\x00\x00\x00\x00\x00\x7F\xFF\xFF\xFF\xFF\xFF",
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\xFF\xFF\xFF" \
		"\xFF\xFF\x80\x00\x00\x00\x00\x00\x7F\xFF\xFF\xFF\xFF\xFC",
	  "\x25\x57\x05\xFA\x2A\x30\x66\x54\xB1\xF4\xCB\x03\xD6\xA7\x50\xA3" \
		"\x0C\x25\x01\x02\xD4\x98\x87\x17\xD9\xBA\x15\xAB\x6D\x3E",
	  "\x67\x68\xAE\x8E\x18\xBB\x92\xCF\xCF\x00\x5C\x94\x9A\xA2\xC6\xD9" \
		"\x48\x53\xD0\xE6\x60\xBB\xF8\x54\xB1\xC9\x50\x5F\xE9\x5A",
	  "\x16\x07\xE6\x89\x8F\x39\x0C\x06\xBC\x1D\x55\x2B\xAD\x22\x6F\x3B" \
		"\x6F\xCF\xE4\x8B\x6E\x81\x84\x99\xAF\x18\xE3\xED\x6C\xF3",
	  "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F\xFF\xFF\x97" \
		"\x5D\xEB\x41\xB3\xA6\x05\x7C\x3C\x43\x21\x46\x52\x65\x51" },
#endif /* 0 */
	/* NIST P256, X9.62 P256v1 */
	{ ECC_PARAM_P256, 256,
	  "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
	  "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC",
	  "\x5A\xC6\x35\xD8\xAA\x3A\x93\xE7\xB3\xEB\xBD\x55\x76\x98\x86\xBC" \
		"\x65\x1D\x06\xB0\xCC\x53\xB0\xF6\x3B\xCE\x3C\x3E\x27\xD2\x60\x4B",
	  "\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2" \
		"\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96",
	  "\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16" \
		"\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5",
	  "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51" },
#if 0
	/* NIST P384 */
	{ ECC_PARAM_P384, 384,
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" \
		"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFC",
	  "\xB3\x31\x2F\xA7\xE2\x3E\xE7\xE4\x98\x8E\x05\x6B\xE3\xF8\x2D\x19" \
		"\x18\x1D\x9C\x6E\xFE\x81\x41\x12\x03\x14\x08\x8F\x50\x13\x87\x5A" \
		"\xC6\x56\x39\x8D\x8A\x2E\xD1\x9D\x2A\x85\xC8\xED\xD3\xEC\x2A\xEF",
	  "\xAA\x87\xCA\x22\xBE\x8B\x05\x37\x8E\xB1\xC7\x1E\xF3\x20\xAD\x74" \
		"\x6E\x1D\x3B\x62\x8B\xA7\x9B\x98\x59\xF7\x41\xE0\x82\x54\x2A\x38" \
		"\x55\x02\xF2\x5D\xBF\x55\x29\x6C\x3A\x54\x5E\x38\x72\x76\x0A\xB7",
	  "\x36\x17\xDE\x4A\x96\x26\x2C\x6F\x5D\x9E\x98\xBF\x92\x92\xDC\x29" \
		"\xF8\xF4\x1D\xBD\x28\x9A\x14\x7C\xE9\xDA\x31\x13\xB5\xF0\xB8\xC0" \
		"\x0A\x60\xB1\xCE\x1D\x7E\x81\x9D\x7A\x43\x1D\x7C\x90\xEA\x0E\x5F",
	  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC7\x63\x4D\x81\xF4\x37\x2D\xDF" \
		"\x58\x1A\x0D\xB2\x48\xB0\xA7\x7A\xEC\xEC\x19\x6A\xCC\xC5\x29\x73" },
	/* NIST P521 */
	{ ECC_PARAM_P521, 521,
	  "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF",
	  "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFC",
	  "\x00\x51\x95\x3E\xB9\x61\x8E\x1C\x9A\x1F\x92\x9A\x21\xA0\xB6\x85" \
		"\x40\xEE\xA2\xDA\x72\x5B\x99\xB3\x15\xF3\xB8\xB4\x89\x91\x8E\xF1" \
		"\x09\xE1\x56\x19\x39\x51\xEC\x7E\x93\x7B\x16\x52\xC0\xBD\x3B\xB1" \
		"\xBF\x07\x35\x73\xDF\x88\x3D\x2C\x34\xF1\xEF\x45\x1F\xD4\x6B\x50" \
		"\x3F\x00",
	  "\x00\xC6\x85\x8E\x06\xB7\x04\x04\xE9\xCD\x9E\x3E\xCB\x66\x23\x95" \
		"\xB4\x42\x9C\x64\x81\x39\x05\x3F\xB5\x21\xF8\x28\xAF\x60\x6B\x4D" \
		"\x3D\xBA\xA1\x4B\x5E\x77\xEF\xE7\x59\x28\xFE\x1D\xC1\x27\xA2\xFF" \
		"\xA8\xDE\x33\x48\xB3\xC1\x85\x6A\x42\x9B\xF9\x7E\x7E\x31\xC2\xE5" \
		"\xBD\x66",
	  "\x01\x18\x39\x29\x6A\x78\x9A\x3B\xC0\x04\x5C\x8A\x5F\xB4\x2C\x7D" \
		"\x1B\xD9\x98\xF5\x44\x49\x57\x9B\x44\x68\x17\xAF\xBD\x17\x27\x3E" \
		"\x66\x2C\x97\xEE\x72\x99\x5E\xF4\x26\x40\xC5\x50\xB9\x01\x3F\xAD" \
		"\x07\x61\x35\x3C\x70\x86\xA2\x72\xC2\x40\x88\xBE\x94\x76\x9F\xD1" \
		"\x66\x50",
	  "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" \
		"\xFF\xFA\x51\x86\x87\x83\xBF\x2F\x96\x6B\x7F\xCC\x01\x48\xF7\x09" \
		"\xA5\xD0\x3B\xB5\xC9\xB8\x89\x9C\x47\xAE\xBB\x6F\xB7\x1E\x91\x38" \
		"\x64\x09" },
#endif /* 0 */
	{ ECC_PARAM_NONE, 0, NULL, NULL, NULL, NULL, NULL, NULL },
		{ ECC_PARAM_NONE, 0, NULL, NULL, NULL, NULL, NULL, NULL }
	};

/* Initialise the bignums for the domain parameter values 
   { p, a, b, gx, gy, r } */

int loadECCparams( CONTEXT_INFO *contextInfoPtr, 
				   const ECC_PARAM_TYPE eccParamType )
	{
	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
	const ECC_DOMAIN_PARAMS *eccParams;
	int curveSize, i, bnStatus = BN_STATUS;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( eccParamType > ECC_PARAM_NONE && eccParamType < ECC_PARAM_LAST );

	/* Find the parameter info for this curve */
	for( i = 0; i < domainParamTbl[ i ].paramType != ECC_PARAM_NONE && \
				i < FAILSAFE_ARRAYSIZE( domainParamTbl, ECC_DOMAIN_PARAMS ); 
		 i++ )
		{
		if( domainParamTbl[ i ].paramType == eccParamType )
			break;
		}
	if( i >= FAILSAFE_ARRAYSIZE( domainParamTbl, ECC_DOMAIN_PARAMS ) )
		retIntError();
	eccParams = &domainParamTbl[ i ];
	curveSize = bitsToBytes( eccParams->curveSizeBits );

	/* Load the parameters into the context bignums */
	pkcInfo->eccParamType = eccParamType;
	CKPTR( BN_bin2bn( eccParams->p, curveSize, &pkcInfo->eccParam_p ) );
	CKPTR( BN_bin2bn( eccParams->a, curveSize, &pkcInfo->eccParam_a ) );
	CKPTR( BN_bin2bn( eccParams->b, curveSize, &pkcInfo->eccParam_b ) );
	CKPTR( BN_bin2bn( eccParams->gx, curveSize, &pkcInfo->eccParam_gx ) );
	CKPTR( BN_bin2bn( eccParams->gy, curveSize, &pkcInfo->eccParam_gy ) );

	return( getBnStatus( bnStatus ) );
	}

/****************************************************************************
*																			*
*								Generate an ECC Key							*
*																			*
****************************************************************************/

/* Generate a generic ECC key */

int generateECCkey( CONTEXT_INFO *contextInfoPtr, const int keyBits )
	{
	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );

	return( CRYPT_ERROR_NOTAVAIL );
	}

/****************************************************************************
*																			*
*							Initialise/Check an ECC Key						*
*																			*
****************************************************************************/

/* Check ECC parameters when loading a key */

int checkECCkey( const CONTEXT_INFO *contextInfoPtr )
	{
	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
	BIGNUM *p = &pkcInfo->eccParam_p;
	BIGNUM *a = &pkcInfo->eccParam_a, *b = &pkcInfo->eccParam_b;
	BIGNUM *gx = &pkcInfo->eccParam_gx, *gy = &pkcInfo->eccParam_gy;
	BIGNUM *qx = &pkcInfo->eccParam_qx, *qy = &pkcInfo->eccParam_qy;
	int length;

	assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );

	/* Make sure that the necessary key parameters have been initialised */
	if( BN_is_zero( p ) || BN_is_zero( a ) || BN_is_zero( b ) || \
		BN_is_zero( gx ) || BN_is_zero( gy ) || \
		BN_is_zero( &pkcInfo->eccParam_r ) )
		return( CRYPT_ARGERROR_STR1 );
	if( BN_is_zero( qx ) || BN_is_zero( qy ) )
		return( CRYPT_ARGERROR_STR1 );
	if( !( contextInfoPtr->flags & CONTEXT_ISPUBLICKEY ) && \
		BN_is_zero( &pkcInfo->eccParam_d ) )
		return( CRYPT_ARGERROR_STR1 );

	/* Make sure that the key paramters are valid:

		pLen >= MIN_PKCSIZE_ECC, pLen <= CRYPT_MAX_PKCSIZE_ECC

		[...] */
	length = BN_num_bytes( p );
	if( length < MIN_PKCSIZE_ECC || length > CRYPT_MAX_PKCSIZE_ECC )
		return( CRYPT_ARGERROR_STR1 );

	/* Make sure that the private key value is valid */
	if( !( contextInfoPtr->flags & CONTEXT_ISPUBLICKEY ) )
		{
		}

	return( CRYPT_OK );
	}

/* Initialise an ECC key */

int initECCkey( CONTEXT_INFO *contextInfoPtr )
	{
	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
	BIGNUM *p = &pkcInfo->eccParam_p, *r = &pkcInfo->eccParam_r;
	int xBits, yBits, bnStatus = BN_STATUS;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );

	/* Evaluate the Montgomery forms */
	BN_MONT_CTX_init( &pkcInfo->eccParam_mont_p );
	BN_MONT_CTX_init( &pkcInfo->eccParam_mont_r );
	CK( BN_MONT_CTX_set( &pkcInfo->eccParam_mont_p, p, pkcInfo->bnCTX ) );
	if( bnStatusOK( bnStatus ) )
		CK( BN_MONT_CTX_set( &pkcInfo->eccParam_mont_r, r, pkcInfo->bnCTX ) );

	/* ECCs are somewhat wierd in that the nominal key size isn't defined by
	   the prime p but by the magnitude of the point Q on the curve (in fact
	   p is significantly larger than the Q components), so to get the key
	   size we have to check the x and y components of Q */
	xBits = BN_num_bits( &pkcInfo->eccParam_qx );
	yBits = BN_num_bits( &pkcInfo->eccParam_qy );
	pkcInfo->keySizeBits = max( xBits, yBits );
	if( bnStatusError( bnStatus ) )
		return( getBnStatus( bnStatus ) );

	return( CRYPT_OK );
	}
#endif /* USE_ECC */
