#include "RSA_DSA_utils.h"
#include "RSA_DSA_keys.h"
#include <opensslUtils/openRsaSnacc.h>
#include <Security/logging.h>
#include <Security/debugging.h>
#include <open_ssl/opensslUtils/opensslUtils.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
#define rsaMiscDebug(args...) debug("rsaMisc", ## args)
RSA *contextToRsaKey(
const Context &context,
AppleCSPSession &session,
CSSM_KEYCLASS keyClass, CSSM_KEYUSE usage, bool &mallocdKey) {
CssmKey &cssmKey =
context.get<CssmKey>(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY);
const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
if(hdr.AlgorithmId != CSSM_ALGID_RSA) {
CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
}
if(hdr.KeyClass != keyClass) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
cspValidateIntendedKeyUsage(&hdr, usage);
return cssmKeyToRsa(cssmKey, session, mallocdKey);
}
RSA *cssmKeyToRsa(
const CssmKey &cssmKey,
AppleCSPSession &session,
bool &allocdKey) {
RSA *rsaKey = NULL;
allocdKey = false;
const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
if(hdr->AlgorithmId != CSSM_ALGID_RSA) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
switch(hdr->BlobType) {
case CSSM_KEYBLOB_RAW:
rsaKey = rawCssmKeyToRsa(cssmKey);
allocdKey = true;
break;
case CSSM_KEYBLOB_REFERENCE:
{
BinaryKey &binKey = session.lookupRefKey(cssmKey);
RSABinaryKey *rsaBinKey = dynamic_cast<RSABinaryKey *>(&binKey);
if(rsaBinKey == NULL) {
rsaMiscDebug("cssmKeyToRsa: wrong BinaryKey subclass\n");
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
}
assert(rsaBinKey->mRsaKey != NULL);
rsaKey = rsaBinKey->mRsaKey;
break;
}
default:
CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
}
return rsaKey;
}
RSA *rawCssmKeyToRsa(
const CssmKey &cssmKey)
{
const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
bool isPub;
assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
if(hdr->AlgorithmId != CSSM_ALGID_RSA) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
switch(hdr->KeyClass) {
case CSSM_KEYCLASS_PUBLIC_KEY:
if(hdr->Format != RSA_PUB_KEY_FORMAT) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
}
isPub = true;
break;
case CSSM_KEYCLASS_PRIVATE_KEY:
if(hdr->Format != RSA_PRIV_KEY_FORMAT) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
}
isPub = false;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
RSA *rsaKey = RSA_new();
if(rsaKey == NULL) {
CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
}
CSSM_RETURN crtn;
if(isPub) {
crtn = RSAPublicKeyDecode(rsaKey,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
}
else {
crtn = RSAPrivateKeyDecode(rsaKey,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
}
if(crtn) {
CssmError::throwMe(crtn);
}
return rsaKey;
}
DSA *contextToDsaKey(
const Context &context,
AppleCSPSession &session,
CSSM_KEYCLASS keyClass, CSSM_KEYUSE usage, bool &mallocdKey) {
CssmKey &cssmKey =
context.get<CssmKey>(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY);
const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
if(hdr.AlgorithmId != CSSM_ALGID_DSA) {
CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
}
if(hdr.KeyClass != keyClass) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
cspValidateIntendedKeyUsage(&hdr, usage);
return cssmKeyToDsa(cssmKey, session, mallocdKey);
}
DSA *cssmKeyToDsa(
const CssmKey &cssmKey,
AppleCSPSession &session,
bool &allocdKey) {
DSA *dsaKey = NULL;
allocdKey = false;
const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
if(hdr->AlgorithmId != CSSM_ALGID_DSA) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
switch(hdr->BlobType) {
case CSSM_KEYBLOB_RAW:
dsaKey = rawCssmKeyToDsa(cssmKey);
allocdKey = true;
break;
case CSSM_KEYBLOB_REFERENCE:
{
BinaryKey &binKey = session.lookupRefKey(cssmKey);
DSABinaryKey *dsaBinKey = dynamic_cast<DSABinaryKey *>(&binKey);
if(dsaBinKey == NULL) {
rsaMiscDebug("cssmKeyToDsa: wrong BinaryKey subclass\n");
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
}
assert(dsaBinKey->mDsaKey != NULL);
dsaKey = dsaBinKey->mDsaKey;
break;
}
default:
CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
}
return dsaKey;
}
DSA *rawCssmKeyToDsa(
const CssmKey &cssmKey)
{
const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
bool isPub;
assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
if(hdr->AlgorithmId != CSSM_ALGID_DSA) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
switch(hdr->KeyClass) {
case CSSM_KEYCLASS_PUBLIC_KEY:
if(hdr->Format != DSA_PUB_KEY_FORMAT) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
}
isPub = true;
break;
case CSSM_KEYCLASS_PRIVATE_KEY:
if(hdr->Format != DSA_PRIV_KEY_FORMAT) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
}
isPub = false;
break;
default:
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
}
DSA *dsaKey = DSA_new();
if(dsaKey == NULL) {
CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
}
CSSM_RETURN crtn;
if(isPub) {
crtn = DSAPublicKeyDecode(dsaKey,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
}
else {
crtn = DSAPrivateKeyDecode(dsaKey,
cssmKey.KeyData.Data,
cssmKey.KeyData.Length);
}
if(crtn) {
CssmError::throwMe(crtn);
}
return dsaKey;
}