#include "AppleX509CLSession.h"
#include "DecodedCert.h"
#include "clNameUtils.h"
#include "clNssUtils.h"
#include "cldebugging.h"
#include "CSPAttacher.h"
#include "clNssUtils.h"
#include <Security/oidsattr.h>
#include <Security/oidscert.h>
#include <Security/cssmapple.h>
#include <Security/csrTemplates.h>
#include <Security/SecAsn1Templates.h>
void AppleX509CLSession::generateCsr(
CSSM_CC_HANDLE CCHandle,
const CSSM_APPLE_CL_CSR_REQUEST *csrReq,
CSSM_DATA_PTR &csrPtr)
{
NSSCertRequest certReq;
NSSCertRequestInfo &reqInfo = certReq.reqInfo;
PRErrorCode prtn;
memset(&certReq, 0, sizeof(certReq));
SecNssCoder coder;
ArenaAllocator alloc(coder);
clIntToData(0, reqInfo.version, alloc);
if(csrReq->subjectNameX509 == NULL) {
CssmError::throwMe(CSSMERR_CL_INVALID_POINTER);
}
CL_cssmNameToNss(*csrReq->subjectNameX509, reqInfo.subject, coder);
CL_CSSMKeyToSubjPubKeyInfoNSS(*csrReq->subjectPublicKey,
reqInfo.subjectPublicKeyInfo, coder);
if(csrReq->challengeString) {
reqInfo.attributes = (NSS_Attribute **)coder.malloc(2 * sizeof(NSS_Attribute *));
reqInfo.attributes[1] = NULL;
reqInfo.attributes[0] = (NSS_Attribute *)coder.malloc(sizeof(NSS_Attribute));
NSS_Attribute *attr = reqInfo.attributes[0];
memset(attr, 0, sizeof(NSS_Attribute));
attr->attrValue = (CSSM_DATA **)coder.malloc(2 * sizeof(CSSM_DATA *));
attr->attrValue[1] = NULL;
attr->attrValue[0] = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
attr->attrType = CSSMOID_ChallengePassword;
CSSM_DATA strData;
strData.Data = (uint8 *)csrReq->challengeString;
strData.Length = strlen(csrReq->challengeString);
prtn = coder.encodeItem(&strData, kSecAsn1PrintableStringTemplate,
*attr->attrValue[0]);
if(prtn) {
clErrorLog("generateCsr: error encoding challengeString\n");
CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
}
}
CSSM_DATA encReqInfo;
prtn = coder.encodeItem(&reqInfo, kSecAsn1CertRequestInfoTemplate, encReqInfo);
if(prtn) {
clErrorLog("generateCsr: error encoding CertRequestInfo\n");
CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
}
CssmAutoData sig(*this);
CssmData &infoData = CssmData::overlay(encReqInfo);
signData(CCHandle, infoData, sig);
certReq.signatureAlgorithm.algorithm = csrReq->signatureOid;
CL_nullAlgParams(certReq.signatureAlgorithm);
certReq.signature.Data = (uint8 *)sig.data();
certReq.signature.Length = sig.length() * 8;
CssmAutoData encCsr(*this);
prtn = SecNssEncodeItemOdata(&certReq, kSecAsn1CertRequestTemplate, encCsr);
if(prtn) {
clErrorLog("generateCsr: error encoding CertRequestInfo\n");
CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR);
}
csrPtr = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
csrPtr->Data = (uint8 *)encCsr.data();
csrPtr->Length = encCsr.length();
encCsr.release();
}
void AppleX509CLSession::verifyCsr(
const CSSM_DATA *csrPtr)
{
NSSCertRequest certReq;
SecNssCoder coder;
PRErrorCode prtn;
memset(&certReq, 0, sizeof(certReq));
prtn = coder.decodeItem(*csrPtr, kSecAsn1CertRequestTemplate, &certReq);
if(prtn) {
CssmError::throwMe(CSSMERR_CL_INVALID_DATA);
}
NSSCertRequestInfo &reqInfo = certReq.reqInfo;
CSSM_KEY_PTR cssmKey = CL_extractCSSMKeyNSS(reqInfo.subjectPublicKeyInfo,
*this, NULL);
CSSM_X509_ALGORITHM_IDENTIFIER sigAlgId = certReq.signatureAlgorithm;
CSSM_ALGORITHMS vfyAlg = CL_oidToAlg(sigAlgId.algorithm);
if(vfyAlg == CSSM_ALGID_ECDSA_SPECIFIED) {
vfyAlg = CL_nssDecodeECDSASigAlgParams(sigAlgId.parameters, coder);
}
NSS_SignedCertRequest certReqSigned;
memset(&certReqSigned, 0, sizeof(certReqSigned));
prtn = coder.decodeItem(*csrPtr, kSecAsn1SignedCertRequestTemplate, &certReqSigned);
if(prtn) {
CssmError::throwMe(CSSMERR_CL_INVALID_DATA);
}
CSSM_DATA sigBytes = certReqSigned.signature;
sigBytes.Length = (sigBytes.Length + 7 ) / 8;
CssmData &sigCdata = CssmData::overlay(sigBytes);
CssmData &toVerify = CssmData::overlay(certReqSigned.certRequestBlob);
CSSM_CSP_HANDLE cspHand = getGlobalCspHand(true);
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
vfyAlg,
NULL, cssmKey,
&ccHand);
if(crtn) {
CssmError::throwMe(crtn);
}
verifyData(ccHand, toVerify, sigCdata);
CL_freeCSSMKey(cssmKey, *this);
}