X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/ocspTool/ocspRequest.cpp diff --git a/SecurityTests/clxutils/ocspTool/ocspRequest.cpp b/SecurityTests/clxutils/ocspTool/ocspRequest.cpp new file mode 100644 index 00000000..8fa856cd --- /dev/null +++ b/SecurityTests/clxutils/ocspTool/ocspRequest.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2004-2005 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * ocspRequest.cpp - OCSP Request class + */ + +#include "ocspRequest.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* preencoded DER NULL */ +static uint8 nullParam[2] = {5, 0}; + +/* size of nonce we generate, in bytes */ +#define OCSP_NONCE_SIZE 8 + +/* + * The only constructor. + */ +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() +{ + /* fields obtained from issuer */ + CSSM_DATA issuerName; + CSSM_DATA issuerKey; + CSSM_KEY_PTR issuerPubKey; + /* from subject */ + 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) { + /* already done */ + return &mEncoded; + } + + /* + * One single request, no extensions + */ + memset(&singleReq, 0, sizeof(singleReq)); + + /* algId refers to the hash we'll perform in issuer name and key */ + certId.algId.algorithm = CSSMOID_SHA1; + certId.algId.parameters.Data = nullParam; + certId.algId.parameters.Length = sizeof(nullParam); + + /* gather fields from two certs */ + issuerName.Length = 0; // don't check + 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); + + /* SHA1(issuerName) */ + ocspdSha1(issuerName.Data, issuerName.Length, issuerNameHash); + + /* SHA1(issuer public key) */ + issuerPubKey = (CSSM_KEY_PTR)issuerKey.Data; + ocspdSha1(issuerPubKey->KeyData.Data, issuerPubKey->KeyData.Length, pubKeyHash); + + /* build the CertID from those components */ + 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; + + /* + * Build top level request with one entry in requestList, no signature, + * one optional extension (a nonce) + */ + memset(&signedReq, 0, sizeof(signedReq)); + tbs.version = &vers; + tbs.requestList = reqArray; + + /* one extension - the nonce */ + 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); + } + + /* Encode */ + if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate, + &mEncoded)) { + printf("OCSPRequest::encode: error encoding OCSP req\n"); + crtn = CSSMERR_TP_INTERNAL_ERROR; + goto errOut; + } + /* save a copy of the CertID */ + mCertID = new OCSPClientCertID(issuerName, issuerPubKey->KeyData, subjectSerial); + +errOut: + if(nonce) { + delete nonce; + } + if(crtn) { + CssmError::throwMe(crtn); + } + return &mEncoded; +} + +const CSSM_DATA *OCSPRequest::nonce() +{ + /* not legal before encode() called */ + assert(mEncoded.Data != NULL); + if(mNonce.Data) { + return &mNonce; + } + else { + return NULL; + } +} + +OCSPClientCertID *OCSPRequest::certID() +{ + encode(); + return mCertID; +} +