#ifdef CRYPTKIT_CSP_ENABLE
#include <security_utilities/debugging.h>
#include <security_utilities/logging.h>
#include "FEECSPUtils.h"
#include "FEEKeys.h"
#include <security_cryptkit/feeFunctions.h>
#include <security_cryptkit/feePublicKey.h>
#define feeMiscDebug(args...) secinfo("feeMisc", ## args)
void CryptKit::throwCryptKit(
feeReturn frtn,
const char *op)
{
if(op) {
Security::Syslog::error("Apple CSP %s: %s", op, feeReturnString(frtn));
}
switch(frtn) {
case FR_Success:
return;
case FR_BadPubKey:
case FR_BadPubKeyString:
case FR_IncompatibleKey:
case FR_BadKeyBlob:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
case FR_IllegalDepth:
CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
case FR_BadSignatureFormat:
CssmError::throwMe(CSSMERR_CSP_INVALID_SIGNATURE);
case FR_InvalidSignature:
CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
case FR_IllegalArg:
CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT);
case FR_BadCipherText:
case FR_BadEnc64:
CssmError::throwMe(CSSMERR_CSP_INVALID_DATA);
case FR_Unimplemented:
CssmError::throwMe(CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED);
case FR_Memory:
CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
case FR_ShortPrivData:
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED);
case FR_IllegalCurve:
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
case FR_WrongSignatureType:
case FR_BadUsageName:
case FR_BadCipherFile:
case FR_Internal:
CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
}
}
feePubKey CryptKit::contextToFeeKey(
const Context &context,
AppleCSPSession &session,
CSSM_ATTRIBUTE_TYPE attrType, CSSM_KEYCLASS keyClass, CSSM_KEYUSE usage, bool &mallocdKey) {
CssmKey &cssmKey =
context.get<CssmKey>(attrType, CSSMERR_CSP_MISSING_ATTR_KEY);
const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
switch(hdr.AlgorithmId) {
case CSSM_ALGID_FEE:
case CSSM_ALGID_ECDSA:
break;
default:
CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
}
if(hdr.KeyClass != keyClass) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
cspValidateIntendedKeyUsage(&hdr, usage);
cspVerifyKeyTimes(hdr);
return cssmKeyToFee(cssmKey, session, mallocdKey);
}
feePubKey CryptKit::cssmKeyToFee(
const CssmKey &cssmKey,
AppleCSPSession &session,
bool &allocdKey) {
feePubKey feeKey = NULL;
allocdKey = false;
const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
switch(hdr->AlgorithmId) {
case CSSM_ALGID_FEE:
case CSSM_ALGID_ECDSA:
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
switch(hdr->BlobType) {
case CSSM_KEYBLOB_RAW:
feeKey = rawCssmKeyToFee(cssmKey);
allocdKey = true;
break;
case CSSM_KEYBLOB_REFERENCE:
{
BinaryKey &binKey = session.lookupRefKey(cssmKey);
FEEBinaryKey *feeBinKey = dynamic_cast<FEEBinaryKey *>(&binKey);
if(feeBinKey == NULL) {
feeMiscDebug("CryptKit::cssmKeyToFee: wrong BinaryKey subclass\n");
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
}
assert(feeBinKey->feeKey() != NULL);
feeKey = feeBinKey->feeKey();
break;
}
default:
CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
}
return feeKey;
}
feePubKey CryptKit::rawCssmKeyToFee(
const CssmKey &cssmKey)
{
const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
switch(hdr->AlgorithmId) {
case CSSM_ALGID_FEE:
case CSSM_ALGID_ECDSA:
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
switch(hdr->KeyClass) {
case CSSM_KEYCLASS_PUBLIC_KEY:
case CSSM_KEYCLASS_PRIVATE_KEY:
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
feePubKey feeKey = feePubKeyAlloc();
if(feeKey == NULL) {
CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
}
feeReturn frtn = FR_IllegalArg;
bool badFormat = false;
switch(hdr->AlgorithmId) {
case CSSM_ALGID_FEE:
switch(hdr->KeyClass) {
case CSSM_KEYCLASS_PUBLIC_KEY:
switch(hdr->Format) {
case FEE_KEYBLOB_DEFAULT_FORMAT:
frtn = feePubKeyInitFromDERPubBlob(feeKey,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
break;
case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
frtn = feePubKeyInitFromPubBlob(feeKey,
cssmKey.KeyData.Data,
(unsigned int)cssmKey.KeyData.Length);
break;
default:
badFormat = true;
break;
}
break;
case CSSM_KEYCLASS_PRIVATE_KEY:
switch(hdr->Format) {
case FEE_KEYBLOB_DEFAULT_FORMAT:
frtn = feePubKeyInitFromDERPrivBlob(feeKey,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
break;
case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
frtn = feePubKeyInitFromPrivBlob(feeKey,
cssmKey.KeyData.Data,
(unsigned int)cssmKey.KeyData.Length);
break;
default:
badFormat = true;
break;
}
break;
default:
break;
}
break;
case CSSM_ALGID_ECDSA:
switch(hdr->KeyClass) {
case CSSM_KEYCLASS_PUBLIC_KEY:
switch(hdr->Format) {
case CSSM_KEYBLOB_RAW_FORMAT_NONE:
case CSSM_KEYBLOB_RAW_FORMAT_X509:
frtn = feePubKeyInitFromX509Blob(feeKey,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
break;
case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
frtn = feePubKeyInitFromOpenSSLBlob(feeKey,
1,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
break;
case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
default:
badFormat = true;
break;
}
break;
case CSSM_KEYCLASS_PRIVATE_KEY:
switch(hdr->Format) {
case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
frtn = feePubKeyInitFromPKCS8Blob(feeKey,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
break;
case CSSM_KEYBLOB_RAW_FORMAT_NONE:
case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
frtn = feePubKeyInitFromOpenSSLBlob(feeKey,
0,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
break;
case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
default:
badFormat = true;
break;
}
break;
default:
break;
}
break;
}
if(badFormat) {
CssmError::throwMe(hdr->KeyClass == CSSM_KEYCLASS_PRIVATE_KEY ?
CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT :
CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
}
if(frtn) {
feePubKeyFree(feeKey);
throwCryptKit(frtn, "feePubKeyInitFromKeyBlob");
}
return feeKey;
}
feeReturn CryptKit::feeRandCallback(
void *ref, unsigned char *bytes, unsigned numBytes)
{
AppleCSPSession *session =
reinterpret_cast<AppleCSPSession *>(ref);
try {
session->getRandomBytes(numBytes, bytes);
}
catch(...) {
return FR_Internal;
}
return FR_Success;
}
#endif