#ifdef BSAFE_CSP_ENABLE
#include "bsafecspi.h"
#include "bsafePKCS1.h"
#include "cspdebugging.h"
bool BSafe::bsafeAlgToInfoType(
CSSM_ALGORITHMS alg,
bool isPublic,
B_INFO_TYPE &infoType, CSSM_KEYBLOB_FORMAT &format) {
switch(alg) {
case CSSM_ALGID_RSA:
if(isPublic) {
infoType = RSA_PUB_KEYINFO_TYPE;
format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
}
else {
infoType = RSA_PRIV_KEYINFO_TYPE;
format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
}
return true;
case CSSM_ALGID_DSA:
format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
if(isPublic) {
infoType = DSA_PUB_KEYINFO_TYPE;
}
else {
infoType = DSA_PRIV_KEYINFO_TYPE;
}
return true;
default:
return false;
}
}
BSafe::BSafeBinaryKey::BSafeBinaryKey(
bool isPub,
uint32 Alg)
: mIsPublic(isPub),
mAlg(Alg)
{
BSafe::check(B_CreateKeyObject(&mBsKey), true);
}
BSafe::BSafeBinaryKey::~BSafeBinaryKey()
{
B_DestroyKeyObject(&mBsKey);
}
void BSafe::BSafeBinaryKey::generateKeyBlob(
CssmAllocator &allocator,
CssmData &blob,
CSSM_KEYBLOB_FORMAT &format, AppleCSPSession &session,
const CssmKey *paramKey, CSSM_KEYATTR_FLAGS &attrFlags) {
assert(mBsKey != NULL);
B_INFO_TYPE bsType;
if(!bsafeAlgToInfoType(mAlg, mIsPublic, bsType, format)) {
CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
}
if(format == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
CssmRemoteData rData(
CssmAllocator::standard(CssmAllocator::sensitive), blob);
BS_GetKeyPkcs1(mBsKey, rData);
rData.release();
}
else {
BSafeItem *info;
BSafe::check(
B_GetKeyInfo((POINTER *)&info, mBsKey, bsType), true);
blob = info->copy<CssmData>(allocator);
}
}
void BSafe::BSafeKeyPairGenContext::generate(
const Context &context,
CssmKey &pubKey,
CssmKey &privKey)
{
BSafeBinaryKey *pubBinKey = new BSafeBinaryKey(true,
context.algorithm());
BSafeBinaryKey *privBinKey = new BSafeBinaryKey(false,
context.algorithm());
try {
AppleKeyPairGenContext::generate(context,
session(),
pubKey,
pubBinKey,
privKey,
privBinKey);
}
catch (...) {
delete pubBinKey;
delete privBinKey;
throw;
}
}
void BSafe::BSafeKeyPairGenContext::generate(
const Context &context,
BinaryKey &pubBinKey, BinaryKey &privBinKey, uint32 &keySize) {
BSafeBinaryKey &bsPubBinKey =
dynamic_cast<BSafeBinaryKey &>(pubBinKey);
BSafeBinaryKey &bsPrivBinKey =
dynamic_cast<BSafeBinaryKey &>(privBinKey);
if (!initialized) {
setupAlgorithm(context, keySize);
check(B_GenerateInit(bsAlgorithm, chooser(), bsSurrender), true);
initialized = true;
}
setRandom();
check(B_GenerateKeypair(bsAlgorithm,
bsPubBinKey.bsKey(),
bsPrivBinKey.bsKey(),
bsRandom,
bsSurrender), true);
}
void BSafe::BSafeKeyPairGenContext::setupAlgorithm(
const Context &context,
uint32 &keySize)
{
switch(context.algorithm()) {
case CSSM_ALGID_RSA:
{
A_RSA_KEY_GEN_PARAMS genParams;
keySize = genParams.modulusBits =
context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
if (CssmData *params =
context.get<CssmData>(CSSM_ATTRIBUTE_ALG_PARAMS)) {
genParams.publicExponent = BSafeItem(*params);
} else {
static unsigned char exponent[] = { 1, 0, 1 };
genParams.publicExponent = BSafeItem(exponent, sizeof(exponent));
}
uint32 mode = context.getInt(CSSM_ATTRIBUTE_MODE);
if(mode == CSSM_ALGMODE_CUSTOM) {
setAlgorithm(AI_RSAKeyGen, &genParams);
}
else {
setAlgorithm(AI_RSAStrongKeyGen, &genParams);
}
}
break;
case CSSM_ALGID_DSA:
{
A_DSA_PARAMS genParams;
genParams.prime =
BSafeItem(context.get<CssmData>(
CSSM_ATTRIBUTE_PRIME,
CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS));
genParams.subPrime =
BSafeItem(context.get<CssmData>(
CSSM_ATTRIBUTE_SUBPRIME,
CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS));
genParams.base =
BSafeItem(context.get<CssmData>(
CSSM_ATTRIBUTE_BASE,
CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS));
setAlgorithm(AI_DSAKeyGen, &genParams);
keySize = B_IntegerBits(genParams.prime.data, genParams.prime.len);
}
break;
default:
CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
}
}
void BSafe::BSafeKeyPairGenContext::generate(
const Context &context,
uint32 bitSize,
CssmData ¶ms,
uint32 &attrCount,
Context::Attr * &attrs)
{
assert(context.algorithm() == CSSM_ALGID_DSA);
B_ALGORITHM_OBJ genAlg = NULL;
B_ALGORITHM_OBJ result = NULL;
try {
check(B_CreateAlgorithmObject(&genAlg));
B_DSA_PARAM_GEN_PARAMS genParams;
genParams.primeBits = bitSize;
check(B_SetAlgorithmInfo(genAlg, AI_DSAParamGen, POINTER(&genParams)));
setRandom();
check(B_GenerateInit(genAlg, chooser(), bsSurrender), true);
check(B_CreateAlgorithmObject(&result));
check(B_GenerateParameters(genAlg, result, bsRandom, bsSurrender));
A_DSA_PARAMS *kParams = NULL;
check(B_GetAlgorithmInfo((POINTER *)&kParams, result, AI_DSAKeyGen), true);
attrs = normAllocator->alloc<Context::Attr>(3);
attrs[0] = Context::Attr(CSSM_ATTRIBUTE_PRIME,
*BSafeItem(kParams->prime).copyp<CssmData>(*normAllocator));
attrs[1] = Context::Attr(CSSM_ATTRIBUTE_SUBPRIME,
*BSafeItem(kParams->subPrime).copyp<CssmData>(*normAllocator));
attrs[2] = Context::Attr(CSSM_ATTRIBUTE_BASE,
*BSafeItem(kParams->base).copyp<CssmData>(*normAllocator));
attrCount = 3;
B_DestroyAlgorithmObject(&result);
B_DestroyAlgorithmObject(&genAlg);
} catch (...) {
B_DestroyAlgorithmObject(&result);
B_DestroyAlgorithmObject(&genAlg);
throw;
}
}
BSafe::BSafeKeyInfoProvider::BSafeKeyInfoProvider(
const CssmKey &cssmKey,
AppleCSPSession &session) :
CSPKeyInfoProvider(cssmKey, session)
{
}
CSPKeyInfoProvider *BSafe::BSafeKeyInfoProvider::provider(
const CssmKey &cssmKey,
AppleCSPSession &session)
{
switch(cssmKey.keyClass()) {
case CSSM_KEYCLASS_PUBLIC_KEY:
case CSSM_KEYCLASS_PRIVATE_KEY:
break;
default:
return NULL;
}
switch(mKey.algorithm()) {
case CSSM_ALGID_RSA:
case CSSM_ALGID_DSA:
break;
default:
return NULL;
}
return new BSafeKeyInfoProvider(cssmKey, session);
}
void BSafe::BSafeKeyInfoProvider::CssmKeyToBinary(
CssmKey *paramKey, CSSM_KEYATTR_FLAGS &attrFlags, BinaryKey **binKey)
{
*binKey = NULL;
const CSSM_KEYHEADER *hdr = &mKey.KeyHeader;
assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
B_INFO_TYPE bsType;
CSSM_KEYBLOB_FORMAT format;
bool isPub;
switch(hdr->KeyClass) {
case CSSM_KEYCLASS_PUBLIC_KEY:
isPub = true;
break;
case CSSM_KEYCLASS_PRIVATE_KEY:
isPub = false;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
if(!bsafeAlgToInfoType(hdr->AlgorithmId, isPub, bsType, format)) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
if(hdr->Format != format) {
dprintf0("BSafe::cssmKeyToBinary: format mismatch\n");
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
}
BSafeBinaryKey *bsBinKey = new BSafeBinaryKey(isPub,
hdr->AlgorithmId);
if(format == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
BS_setKeyPkcs1(mKey, bsBinKey->bsKey());
}
else {
BSafeItem item(mKey.KeyData);
BSafe::check(
B_SetKeyInfo(bsBinKey->bsKey(), bsType, POINTER(&item)), true);
}
*binKey = bsBinKey;
}
void BSafe::BSafeKeyInfoProvider::QueryKeySizeInBits(
CSSM_KEY_SIZE &keySize)
{
if(mKey.blobType() != CSSM_KEYBLOB_RAW) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
}
B_KEY_OBJ bKey;
A_RSA_KEY *rsaKeyInfo = NULL;
A_DSA_PUBLIC_KEY *dsaPubKeyInfo = NULL;
A_DSA_PRIVATE_KEY *dsaPrivKeyInfo = NULL;
ITEM *sizeItem = NULL;
BSafe::check(B_CreateKeyObject(&bKey), true);
B_INFO_TYPE infoType;
switch(mKey.algorithm()) {
case CSSM_ALGID_RSA:
switch(mKey.keyClass()) {
case CSSM_KEYCLASS_PUBLIC_KEY:
if(mKey.blobFormat() !=
CSSM_KEYBLOB_RAW_FORMAT_PKCS1) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
}
BS_setKeyPkcs1(mKey, bKey);
infoType = KI_RSAPublic;
break;
case CSSM_KEYCLASS_PRIVATE_KEY:
{
if(mKey.blobFormat() !=
CSSM_KEYBLOB_RAW_FORMAT_PKCS8) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
}
BSafeItem item(mKey.KeyData);
BSafe::check(
B_SetKeyInfo(bKey, KI_PKCS_RSAPrivateBER,
POINTER(&item)), true);
infoType = KI_RSAPrivate;
break;
}
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
rsaKeyInfo = getKey<A_RSA_KEY>(bKey, infoType);
sizeItem = &rsaKeyInfo->modulus;
break;
case CSSM_ALGID_DSA:
if(mKey.blobFormat() !=
CSSM_KEYBLOB_RAW_FORMAT_FIPS186) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT);
}
switch(mKey.keyClass()) {
case CSSM_KEYCLASS_PUBLIC_KEY:
{
BSafeItem item(mKey.KeyData);
BSafe::check(B_SetKeyInfo(bKey,
DSA_PUB_KEYINFO_TYPE,
(POINTER)&item), true);
dsaPubKeyInfo = getKey<A_DSA_PUBLIC_KEY>(bKey,
KI_DSAPublic);
sizeItem = &dsaPubKeyInfo->params.prime;
break;
}
case CSSM_KEYCLASS_PRIVATE_KEY:
{
BSafeItem item(mKey.KeyData);
BSafe::check(B_SetKeyInfo(bKey,
DSA_PRIV_KEYINFO_TYPE,
(POINTER)&item), true);
dsaPrivKeyInfo = getKey<A_DSA_PRIVATE_KEY>(bKey,
KI_DSAPrivate);
sizeItem = &dsaPrivKeyInfo->params.prime;
break;
}
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
break;
default:
CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
}
uint32 iSize = B_IntegerBits(sizeItem->data, sizeItem->len);
keySize.LogicalKeySizeInBits = iSize;
keySize.EffectiveKeySizeInBits = iSize;
B_DestroyKeyObject(&bKey);
}
#endif