#ifdef CRYPTKIT_CSP_ENABLE
#include "FEEKeys.h"
#include "FEECSPUtils.h"
#include "CryptKitSpace.h"
#include <CryptKit/feePublicKey.h>
#include <CryptKit/falloc.h>
#include <Security/cssmdata.h>
#include "AppleCSPSession.h"
#include "AppleCSPUtils.h"
#include <assert.h>
#include <Security/debugging.h>
#define feeKeyDebug(args...) secdebug("feeKey", ## args)
CryptKit::FEEBinaryKey::FEEBinaryKey(feePubKey feeKey)
: mFeeKey(feeKey)
{
if(mFeeKey == NULL) {
mFeeKey = feePubKeyAlloc();
if(mFeeKey == NULL) {
CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
}
}
}
CryptKit::FEEBinaryKey::~FEEBinaryKey()
{
if(mFeeKey) {
feePubKeyFree(mFeeKey);
mFeeKey = NULL;
}
}
void CryptKit::FEEBinaryKey::generateKeyBlob(
CssmAllocator &allocator,
CssmData &blob,
CSSM_KEYBLOB_FORMAT &format,
AppleCSPSession &session,
const CssmKey *paramKey,
CSSM_KEYATTR_FLAGS &attrFlags)
{
unsigned char *keyBlob;
unsigned len;
feeReturn frtn;
bool derBlob;
bool freeTheKey = false;
feePubKey keyToEncode = mFeeKey;
assert(mFeeKey != NULL);
switch(format) {
case CSSM_KEYBLOB_RAW_FORMAT_NONE:
derBlob = true;
break;
case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
{
if(mKeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) {
keyToEncode = feePubKeyAlloc();
if(keyToEncode == NULL) {
CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
}
frtn = feePubKeyInitPubKeyFromPriv(mFeeKey, keyToEncode);
if(frtn) {
feePubKeyFree(keyToEncode);
throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
}
freeTheKey = true;
}
derBlob = true;
break;
}
case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
derBlob = false;
break;
default:
feeKeyDebug("FEEBinaryKey::generateKeyBlob: bad format (%ld)\n", format);
CssmError::throwMe(feePubKeyIsPrivate(mFeeKey) ?
CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT :
CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
}
if(feePubKeyIsPrivate(keyToEncode)) {
if(derBlob) {
frtn = feePubKeyCreateDERPrivBlob(keyToEncode, &keyBlob, &len);
}
else {
frtn = feePubKeyCreatePrivBlob(keyToEncode, &keyBlob, &len);
}
}
else {
if(derBlob) {
frtn = feePubKeyCreateDERPubBlob(keyToEncode, &keyBlob, &len);
}
else {
frtn = feePubKeyCreatePubBlob(keyToEncode, &keyBlob, &len);
}
}
if(frtn) {
throwCryptKit(frtn, "feePubKeyCreate*Blob");
}
setUpCssmData(blob, len, allocator);
memmove(blob.data(), keyBlob, len);
blob.length(len);
ffree(keyBlob);
format = derBlob ? FEE_KEYBLOB_DEFAULT_FORMAT :
CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
if(freeTheKey) {
feePubKeyFree(keyToEncode);
}
}
void CryptKit::FEEKeyPairGenContext::generate(
const Context &context,
CssmKey &pubKey,
CssmKey &privKey)
{
FEEBinaryKey *pubBinKey = new FEEBinaryKey();
FEEBinaryKey *privBinKey = new FEEBinaryKey();
try {
AppleKeyPairGenContext::generate(context,
session(),
pubKey,
pubBinKey,
privKey,
privBinKey);
}
catch (...) {
delete pubBinKey;
delete privBinKey;
throw;
}
}
void CryptKit::FEEKeyPairGenContext::generate(
const Context &context,
BinaryKey &pubBinKey,
BinaryKey &privBinKey,
uint32 &keyBits)
{
FEEBinaryKey &fPubBinKey =
dynamic_cast<FEEBinaryKey &>(pubBinKey);
FEEBinaryKey &fPrivBinKey =
dynamic_cast<FEEBinaryKey &>(privBinKey);
keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
CssmCryptoData *cseed = context.get<CssmCryptoData>(CSSM_ATTRIBUTE_SEED);
CssmData *seed;
bool haveSeed;
CssmAutoData aSeed(session()); if(cseed) {
haveSeed = true;
seed = &cseed->param();
}
else {
haveSeed = false;
unsigned keyBytes = ((keyBits + 7) / 8) + 1;
aSeed.malloc(keyBytes);
session().getRandomBytes(keyBytes, aSeed);
seed = &aSeed.get();
}
feePrimeType primeType = FPT_Default;
uint32 uPrimeType = context.getInt(CSSM_ATTRIBUTE_FEE_PRIME_TYPE);
switch(uPrimeType) {
case CSSM_FEE_PRIME_TYPE_DEFAULT:
break;
case CSSM_FEE_PRIME_TYPE_MERSENNE:
primeType = FPT_Mersenne;
break;
case CSSM_FEE_PRIME_TYPE_FEE:
primeType = FPT_FEE;
break;
case CSSM_FEE_PRIME_TYPE_GENERAL:
primeType = FPT_General;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
}
feeCurveType curveType = FCT_Default;
uint32 uCurveType = context.getInt(CSSM_ATTRIBUTE_FEE_CURVE_TYPE);
switch(uCurveType) {
case CSSM_FEE_CURVE_TYPE_DEFAULT:
break;
case CSSM_FEE_CURVE_TYPE_MONTGOMERY:
curveType = FCT_Montgomery;
break;
case CSSM_FEE_CURVE_TYPE_WEIERSTRASS:
curveType = FCT_Weierstrass;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
}
feeReturn frtn = feePubKeyInitFromPrivDataKeyBits(
fPrivBinKey.feeKey(),
(unsigned char *)seed->data(),
seed->length(),
keyBits,
primeType,
curveType,
haveSeed ? 1 : 0);
if(frtn) {
throwCryptKit(frtn, "feePubKeyInitFromPrivDataKeyBits");
}
frtn = feePubKeyInitPubKeyFromPriv(fPrivBinKey.feeKey(),
fPubBinKey.feeKey());
if(frtn) {
throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
}
}
CryptKit::FEEKeyInfoProvider::FEEKeyInfoProvider(
const CssmKey &cssmKey,
AppleCSPSession &session) :
CSPKeyInfoProvider(cssmKey, session)
{
}
CSPKeyInfoProvider *FEEKeyInfoProvider::provider(
const CssmKey &cssmKey,
AppleCSPSession &session)
{
switch(cssmKey.algorithm()) {
case CSSM_ALGID_FEE:
break;
default:
return NULL;
}
switch(cssmKey.keyClass()) {
case CSSM_KEYCLASS_PUBLIC_KEY:
case CSSM_KEYCLASS_PRIVATE_KEY:
break;
default:
return NULL;
}
return new FEEKeyInfoProvider(cssmKey, session);
}
void CryptKit::FEEKeyInfoProvider::CssmKeyToBinary(
CssmKey *paramKey, CSSM_KEYATTR_FLAGS &attrFlags, BinaryKey **binKey)
{
*binKey = NULL;
feePubKey feeKey = NULL;
feeKey = rawCssmKeyToFee(mKey);
FEEBinaryKey *feeBinKey = new FEEBinaryKey(feeKey);
*binKey = feeBinKey;
}
void CryptKit::FEEKeyInfoProvider::QueryKeySizeInBits(
CSSM_KEY_SIZE &keySize)
{
feePubKey feeKey = NULL;
if(mKey.blobType() != CSSM_KEYBLOB_RAW) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
}
feeKey = rawCssmKeyToFee(mKey);
keySize.LogicalKeySizeInBits = feePubKeyBitsize(feeKey);
keySize.EffectiveKeySizeInBits = keySize.LogicalKeySizeInBits;
feePubKeyFree(feeKey);
}
bool CryptKit::FEEKeyInfoProvider::getHashableBlob(
CssmAllocator &allocator,
CssmData &blob) {
assert(mKey.blobType() == CSSM_KEYBLOB_RAW);
if((mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_NONE) &&
(mKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY)) {
const CssmData &keyBlob = CssmData::overlay(mKey.KeyData);
copyCssmData(keyBlob, blob, allocator);
return true;
}
return false;
}
#endif