#include "ocspRequest.h"
#include <clAppUtils/CertParser.h>
#include <security_cdsa_utils/cuCdsaUtils.h>
#include <security_ocspd/ocspResponse.h>
#include <security_ocspd/ocspExtensions.h>
#include <security_ocspd/ocspdUtils.h>
#include <assert.h>
#include <string.h>
#include <Security/oidsalg.h>
#include <Security/oidscert.h>
#include <Security/ocspTemplates.h>
#include <security_utilities/devrandom.h>
#include <CommonCrypto/CommonDigest.h>
#include <security_cdsa_utilities/cssmerrors.h>
static uint8 nullParam[2] = {5, 0};
#define OCSP_NONCE_SIZE 8
OCSPRequest::OCSPRequest(
CertParser &subject,
CertParser &issuer,
bool genNonce)
: mCoder(NULL),
mSubject(subject),
mIssuer(issuer),
mGenNonce(genNonce),
mCertID(NULL)
{
SecAsn1CoderCreate(&mCoder);
mNonce.Data = NULL;
mNonce.Length = 0;
mEncoded.Data = NULL;
mEncoded.Length = 0;
}
OCSPRequest::~OCSPRequest()
{
delete mCertID;
if(mCoder) {
SecAsn1CoderRelease(mCoder);
}
}
const CSSM_DATA *OCSPRequest::encode()
{
CSSM_DATA issuerName;
CSSM_DATA issuerKey;
CSSM_KEY_PTR issuerPubKey;
CSSM_DATA subjectSerial;
CSSM_RETURN crtn = CSSM_OK;
uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH];
uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH];
SecAsn1OCSPRequest singleReq;
SecAsn1OCSPCertID &certId = singleReq.reqCert;
SecAsn1OCSPSignedRequest signedReq;
SecAsn1OCSPRequest *reqArray[2] = { &singleReq, NULL };
SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest;
uint8 version = 0;
CSSM_DATA vers = {1, &version};
uint8 nonceBytes[OCSP_NONCE_SIZE];
CSSM_DATA nonceData = {OCSP_NONCE_SIZE, nonceBytes};
OCSPNonce *nonce = NULL;
NSS_CertExtension *extenArray[2] = {NULL, NULL};
if(mEncoded.Data) {
return &mEncoded;
}
memset(&singleReq, 0, sizeof(singleReq));
certId.algId.algorithm = CSSMOID_SHA1;
certId.algId.parameters.Data = nullParam;
certId.algId.parameters.Length = sizeof(nullParam);
issuerName.Length = 0; issuerName.Data = (uint8 *)mSubject.fieldForOid(CSSMOID_X509V1IssuerNameStd,
issuerName.Length);
issuerKey.Length = sizeof(CSSM_KEY);
issuerKey.Data = (uint8 *)mIssuer.fieldForOid(CSSMOID_CSSMKeyStruct,
issuerKey.Length);
subjectSerial.Length = 0;
subjectSerial.Data = (uint8 *)mSubject.fieldForOid(CSSMOID_X509V1SerialNumber,
subjectSerial.Length);
ocspdSha1(issuerName.Data, issuerName.Length, issuerNameHash);
issuerPubKey = (CSSM_KEY_PTR)issuerKey.Data;
ocspdSha1(issuerPubKey->KeyData.Data, issuerPubKey->KeyData.Length, pubKeyHash);
certId.issuerNameHash.Data = issuerNameHash;
certId.issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH;
certId.issuerPubKeyHash.Data = pubKeyHash;
certId.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH;
certId.serialNumber = subjectSerial;
memset(&signedReq, 0, sizeof(signedReq));
tbs.version = &vers;
tbs.requestList = reqArray;
if(mGenNonce) {
DevRandomGenerator drg;
drg.random(nonceBytes, OCSP_NONCE_SIZE);
nonce = new OCSPNonce(mCoder, false, nonceData);
extenArray[0] = nonce->nssExt();
tbs.requestExtensions = extenArray;
SecAsn1AllocCopyItem(mCoder, &nonceData, &mNonce);
}
if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate,
&mEncoded)) {
printf("OCSPRequest::encode: error encoding OCSP req\n");
crtn = CSSMERR_TP_INTERNAL_ERROR;
goto errOut;
}
mCertID = new OCSPClientCertID(issuerName, issuerPubKey->KeyData, subjectSerial);
errOut:
if(nonce) {
delete nonce;
}
if(crtn) {
CssmError::throwMe(crtn);
}
return &mEncoded;
}
const CSSM_DATA *OCSPRequest::nonce()
{
assert(mEncoded.Data != NULL);
if(mNonce.Data) {
return &mNonce;
}
else {
return NULL;
}
}
OCSPClientCertID *OCSPRequest::certID()
{
encode();
return mCertID;
}