Session_Crypto.cpp [plain text]
#include "AppleX509CLSession.h"
#include "DecodedCert.h"
#include "cldebugging.h"
#include "CSPAttacher.h"
#include "clNssUtils.h"
#include <Security/keyTemplates.h>
#include <security_asn1/nssUtils.h>
#include <Security/oidscert.h>
#include <Security/cssmapple.h>
void
AppleX509CLSession::CertGetKeyInfo(
const CssmData &Cert,
CSSM_KEY_PTR &Key)
{
DecodedCert decodedCert(*this, Cert);
Key = decodedCert.extractCSSMKey(*this);
}
void
AppleX509CLSession::CertVerifyWithKey(
CSSM_CC_HANDLE CCHandle,
const CssmData &CertToBeVerified)
{
CssmAutoData tbs(*this);
CssmAutoData algId(*this);
CssmAutoData sig(*this);
CL_certCrlDecodeComponents(CertToBeVerified, tbs, algId, sig);
verifyData(CCHandle, tbs, sig);
}
void
AppleX509CLSession::CertVerify(
CSSM_CC_HANDLE CCHandle,
const CssmData &CertToBeVerified,
const CssmData *SignerCert,
const CSSM_FIELD *VerifyScope,
uint32 ScopeSize)
{
if((VerifyScope != NULL) || (ScopeSize != 0)) {
CssmError::throwMe(CSSMERR_CL_SCOPE_NOT_SUPPORTED);
}
if((CCHandle == CSSM_INVALID_HANDLE) && (SignerCert == NULL)) {
CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE);
}
CssmAutoData tbs(*this); CssmAutoData algId(*this); CssmAutoData sig(*this); CL_certCrlDecodeComponents(CertToBeVerified, tbs, algId, sig);
CSSM_KEY_PTR signerPubKey = NULL;
CSSM_CONTEXT_PTR context = NULL;
CSSM_CSP_HANDLE cspHand = CSSM_INVALID_HANDLE;
CSSM_CC_HANDLE ourCcHand = CSSM_INVALID_HANDLE;
if(SignerCert != NULL) {
CertGetKeyInfo(*SignerCert, signerPubKey);
}
try {
if(CCHandle != CSSM_INVALID_HANDLE) {
if(SignerCert != NULL) {
CSSM_RETURN crtn;
crtn = CSSM_GetContext(CCHandle, &context);
if(crtn) {
CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE);
}
CSSM_CONTEXT_ATTRIBUTE_PTR attr;
crtn = CSSM_GetContextAttribute(context,
CSSM_ATTRIBUTE_KEY,
&attr);
if(crtn) {
clErrorLog("CertVerify: valid CCHandle but no key!\n");
CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE);
}
assert(signerPubKey != NULL);
CSSM_KEY_PTR contextPubKey = attr->Attribute.Key;
if(contextPubKey->KeyHeader.AlgorithmId !=
signerPubKey->KeyHeader.AlgorithmId) {
clErrorLog("CertVerify: AlgorithmId mismatch!\n");
CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE);
}
}
}
else {
assert(SignerCert != NULL);
assert(signerPubKey != NULL);
CSSM_X509_ALGORITHM_IDENTIFIER cssmAlgId;
SecNssCoder coder;
PRErrorCode prtn;
CssmData &algIdData = algId.get();
memset(&cssmAlgId, 0, sizeof(cssmAlgId));
prtn = coder.decode(algIdData.data(), algIdData.length(),
kSecAsn1AlgorithmIDTemplate, &cssmAlgId);
if(prtn) {
CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
}
CSSM_ALGORITHMS vfyAlg = CL_oidToAlg(cssmAlgId.algorithm);
if(vfyAlg == CSSM_ALGID_ECDSA_SPECIFIED) {
vfyAlg = CL_nssDecodeECDSASigAlgParams(cssmAlgId.parameters, coder);
}
cspHand = getGlobalCspHand(true);
CSSM_RETURN crtn;
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
vfyAlg,
NULL, signerPubKey,
&ourCcHand);
CCHandle = ourCcHand;
}
verifyData(CCHandle, tbs, sig);
}
catch(...) {
if(context != NULL) {
CSSM_FreeContext(context);
}
CL_freeCSSMKey(signerPubKey, *this);
if(ourCcHand != CSSM_INVALID_HANDLE) {
CSSM_DeleteContext(ourCcHand);
}
throw;
}
if(context != NULL) {
CSSM_FreeContext(context);
}
CL_freeCSSMKey(signerPubKey, *this);
if(ourCcHand != CSSM_INVALID_HANDLE) {
CSSM_DeleteContext(ourCcHand);
}
}
void
AppleX509CLSession::CertSign(
CSSM_CC_HANDLE CCHandle,
const CssmData &CertTemplate,
const CSSM_FIELD *SignScope,
uint32 ScopeSize,
CssmData &SignedCert)
{
if((SignScope != NULL) || (ScopeSize != 0)) {
CssmError::throwMe(CSSMERR_CL_SCOPE_NOT_SUPPORTED);
}
if(CCHandle == CSSM_INVALID_HANDLE) {
CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE);
}
CSSM_CONTEXT_PTR context = NULL; CSSM_RETURN crtn;
crtn = CSSM_GetContext(CCHandle, &context);
if(crtn) {
CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE);
}
CSSM_CONTEXT_ATTRIBUTE_PTR attr; crtn = CSSM_GetContextAttribute(context,
CSSM_ATTRIBUTE_KEY,
&attr);
if(crtn) {
clErrorLog("CertSign: valid CCHandle but no signing key!\n");
CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE);
}
CSSM_KEY_PTR signingKey = attr->Attribute.Key;
if(signingKey == NULL) {
clErrorLog("CertSign: valid CCHandle, NULL signing key!\n");
CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE);
}
CssmAutoData encAlgId(*this);
CssmAutoData rawSig(*this);
CssmAutoData fullCert(*this);
try {
SecNssCoder coder;
CSSM_X509_ALGORITHM_IDENTIFIER algId;
memset(&algId, 0, sizeof(algId));
const CSSM_OID *oid = cssmAlgToOid(context->AlgorithmType);
if(oid == NULL) {
clErrorLog("CertSIgn: unknown alg (%u)\n",
(unsigned)context->AlgorithmType);
CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
}
algId.algorithm = *oid;
switch(context->AlgorithmType) {
case CSSM_ALGID_SHA1WithECDSA:
case CSSM_ALGID_SHA224WithECDSA:
case CSSM_ALGID_SHA256WithECDSA:
case CSSM_ALGID_SHA384WithECDSA:
case CSSM_ALGID_SHA512WithECDSA:
case CSSM_ALGID_ECDSA_SPECIFIED:
break;
default:
CL_nullAlgParams(algId);
break;
}
PRErrorCode prtn;
prtn = SecNssEncodeItemOdata(&algId, kSecAsn1AlgorithmIDTemplate,
encAlgId);
if(prtn) {
CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
}
signData(CCHandle, CertTemplate, rawSig);
CL_certEncodeComponents(CertTemplate, encAlgId, rawSig, fullCert);
}
catch (...) {
CSSM_FreeContext(context);
throw;
}
CSSM_FreeContext(context);
SignedCert = fullCert.release();
}
void
AppleX509CLSession::signData(
CSSM_CC_HANDLE ccHand,
const CssmData &tbs,
CssmOwnedData &sig) {
CSSM_RETURN crtn;
CssmData cSig;
crtn = CSSM_SignData(
ccHand,
&tbs,
1, CSSM_ALGID_NONE, &cSig);
if(crtn) {
clErrorLog("AppleX509CLSession::CSSM_SignData: %ld\n", (long)crtn);
CssmError::throwMe(crtn);
}
sig.set(cSig);
}
void AppleX509CLSession::verifyData(
CSSM_CC_HANDLE ccHand,
const CssmData &tbs,
const CssmData &sig)
{
CSSM_RETURN crtn;
crtn = CSSM_VerifyData(ccHand,
&tbs,
1,
CSSM_ALGID_NONE, &sig);
if(crtn) {
if(crtn == CSSMERR_CSP_VERIFY_FAILED) {
CssmError::throwMe(CSSMERR_CL_VERIFICATION_FAILURE);
}
else {
CssmError::throwMe(crtn);
}
}
}