]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/clxutils/ocspTool/ocspTool.cpp
Security-57740.51.3.tar.gz
[apple/security.git] / SecurityTests / clxutils / ocspTool / ocspTool.cpp
diff --git a/SecurityTests/clxutils/ocspTool/ocspTool.cpp b/SecurityTests/clxutils/ocspTool/ocspTool.cpp
deleted file mode 100644 (file)
index 153cdaa..0000000
+++ /dev/null
@@ -1,1254 +0,0 @@
-/* 
- * ocspTool - simple OCSP request/response generator and parser
- */
-#include <Security/Security.h>
-#include <Security/SecAsn1Coder.h>
-#include <Security/ocspTemplates.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <security_cdsa_utils/cuFileIo.h>
-#include <security_cdsa_utils/cuCdsaUtils.h>
-#include <security_cdsa_utils/cuOidParser.h>
-#include <security_cdsa_utils/cuPrintCert.h>
-#include <clAppUtils/CertParser.h>
-#include <clAppUtils/timeStr.h>
-#include <clAppUtils/identPicker.h>
-#include <CommonCrypto/CommonDigest.h>
-#include <security_ocspd/ocspExtensions.h>
-#include <security_ocspd/ocspdUtils.h>
-#include <utilLib/common.h>
-#include "ocspUtils.h"
-#include "ocspRequest.h"
-#include "ocspNetwork.h"
-#include "findOcspUrl.h"
-
-static void usage(char **argv) 
-{
-       printf("Usage: %s cmd [option...]\n", argv[0]);
-       printf("cmds:\n");
-       printf("   g generate request\n");
-       printf("   G parse request\n");
-       printf("   r generate reply\n");
-       printf("   R parse reply\n");
-       printf("   p generate OCSP request, post, get reply (use -p and/or -o)\n");
-       printf("Options\n");
-       printf("  -c cert_file         -- for generating request\n");
-       printf("  -C issuer_cert_file  -- for generating request\n");
-       printf("  -i in_file           -- for parsing\n");
-       printf("  -o out_file          -- for generating\n");
-       printf("  -s status            -- cert status: g(ood)|r(evoked)|u(nknown)\n");
-       printf("  -r crlReason         -- integer 0..8\n");
-       printf("  -k keychain          -- keychain containing signing cert\n");
-       printf("  -p                   -- parse reply from post op\n");
-       printf("  -u responderURI      -- OCSP responder here, not from cert's AIA extension\n");
-       printf("  -v                   -- verbose; e.g., print certs\n");
-       exit(1);
-}
-
-void doIndent(int indent)
-{
-       for(int dex=0; dex<indent; dex++) {
-               printf(" ");
-       }
-}
-
-static void printString(
-       const CSSM_DATA *str)
-{
-       unsigned i;
-       char *cp = (char *)str->Data;
-       for(i=0; i<str->Length; i++) {
-               printf("%c", *cp++);
-       }
-       printf("\n");
-}
-
-static void printDataAsHex(
-       const CSSM_DATA *d,
-       unsigned maxToPrint = 0)                // optional, 0 means print it all
-{
-       unsigned i;
-       bool more = false;
-       uint32 len = d->Length;
-       uint8 *cp = d->Data;
-       
-       if((maxToPrint != 0) && (len > maxToPrint)) {
-               len = maxToPrint;
-               more = true;
-       }       
-       for(i=0; i<len; i++) {
-               printf("%02X ", ((unsigned char *)cp)[i]);
-       }
-       if(more) {
-               printf("...\n");
-       }
-       else {
-               printf("\n");
-       }
-}
-
-static void printTaggedItem(
-       const NSS_TaggedItem &ti)
-{
-       switch(ti.tag) {
-               case BER_TAG_PRINTABLE_STRING:
-               case BER_TAG_T61_STRING:
-               case BER_TAG_IA5_STRING:
-               case BER_TAG_UTC_TIME:
-               case BER_TAG_GENERALIZED_TIME:
-                       printString(&ti.item);
-                       break;
-               default:
-                       printDataAsHex(&ti.item, 0);
-       }
-}
-
-static void printName(
-       const NSS_Name &name,
-       int indent)
-{
-       OidParser parser;
-       
-       unsigned numRdns = ocspdArraySize((const void **)name.rdns);
-       for(unsigned rdnDex=0; rdnDex<numRdns; rdnDex++) {
-               NSS_RDN *rdn = name.rdns[rdnDex];
-               unsigned numATVs = ocspdArraySize((const void **)rdn->atvs);
-               for(unsigned atvDex=0; atvDex<numATVs; atvDex++) {
-                       NSS_ATV *atv = rdn->atvs[atvDex];
-                       char buf[OID_PARSER_STRING_SIZE];
-                       parser.oidParse(atv->type.Data, atv->type.Length, buf);
-                       doIndent(indent);
-                       printf("%s : ", buf);
-                       printTaggedItem(atv->value);
-               }
-       }
-}      
-
-static uint8 nullParam[2] = {5, 0};
-
-/*
- * Given the following, create a ResponseData (to be signed by caller).
- *
- *             cert status (CS_{Good,Revoked,Unknown})
- *             cert being verified
- *             issuer cert
- *             this update time
- *             next update time (optional)
- *             nonce (optional)
- */
-static int genTbsResp(
-       SecAsn1CoderRef coder,                  // result in this coder's address space
-       CSSM_CL_HANDLE clHand, 
-       SecAsn1OCSPCertStatusTag status,
-       CE_CrlReason reason,                    // for CS_Revoked
-       const CSSM_DATA &subjectCert,
-       const CSSM_DATA &issuerCert,
-       unsigned thisUpdate,                    // required, seconds from now
-       unsigned nextUpdate,                    // optional, seconds from now, 0 ==> skip
-       const CSSM_DATA *nonce,                 // optional
-       CSSM_DATA &encodedTbs)                  // allocated in coder space and RETURNED
-{
-       char *nextUpdStr = NULL;
-       CSSM_DATA nextUpdateData;
-       char *thisUpdStr = NULL;
-       CSSM_DATA *thisUpdateData;
-       SecAsn1OCSPResponseData responseData;
-       OCSPNonce *nonceExt = NULL;
-       char *producedAt = NULL;
-       SecAsn1OCSPSingleResponse singleResp;
-       SecAsn1OCSPSingleResponse *respArray[2] = {&singleResp, NULL};
-       SecAsn1OCSPResponderID responderID;
-       NSS_CertExtension *extenArray[2] = {NULL, NULL};
-       
-       /* SingleResponse */
-       memset(&singleResp, 0, sizeof(singleResp));
-       
-       /* SingleResponse.CertID */
-       SecAsn1OCSPCertID &certId = singleResp.certID;
-       CertParser parser(clHand);
-       CertParser issuerParser(clHand);
-       CSSM_RETURN crtn = parser.initWithData(subjectCert);
-       if(crtn) {
-               cssmPerror("CertParser.initWithData for subject cert", crtn);
-               return -1;
-       }
-       crtn = issuerParser.initWithData(issuerCert);
-       if(crtn) {
-               cssmPerror("CertParser.initWithData for issuer", crtn);
-               return -1;
-       }
-
-       /* 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);
-       
-       /* SHA1(issuerName) */
-       CSSM_DATA issuerName = {0, NULL};
-       issuerName.Data = (uint8 *)parser.fieldForOid(CSSMOID_X509V1IssuerNameStd, 
-               issuerName.Length);
-       if(issuerName.Data == NULL) {
-               printf("***Error fetching issuer name. Aborting.\n");
-               return 1;
-       }
-       uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH];
-       ocspdSha1(issuerName.Data, issuerName.Length, issuerNameHash);
-       
-       /* SHA1(issuer public key) */
-       CSSM_KEY_PTR pubKey = NULL;
-       CSSM_SIZE pubKeyLen = sizeof(CSSM_KEY);
-       pubKey = (CSSM_KEY_PTR)issuerParser.fieldForOid(CSSMOID_CSSMKeyStruct, pubKeyLen);
-       if(pubKey == NULL) {
-               printf("***Error fetching public key from issuer cert. Aborting.\n");
-               return 1;
-       }
-       uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH];
-       ocspdSha1(pubKey->KeyData.Data, pubKey->KeyData.Length, pubKeyHash);
-
-       /* serial number */
-       CSSM_DATA serialNum = {0, NULL};
-       serialNum.Data = (uint8 *)parser.fieldForOid(CSSMOID_X509V1SerialNumber, 
-               serialNum.Length);
-       if(serialNum.Data == NULL) {
-               printf("***Error fetching serial number. Aborting.\n");
-               return 1;
-       }
-
-       /* 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 = serialNum;
-
-       /* SingleResponse.CertStatus - to be encoded on its own */
-       SecAsn1OCSPCertStatus certStatus;
-       memset(&certStatus, 0, sizeof(certStatus));
-       SecAsn1OCSPRevokedInfo revokedInfo;
-       char *revokedAt = NULL;
-       CSSM_DATA reasonData;
-       OSStatus ortn;
-       
-       if(status == CS_Revoked) { 
-               /* cook up SecAsn1OCSPRevokedInfo */
-               certStatus.revokedInfo = &revokedInfo;
-               revokedAt = appTimeAtNowPlus(-3600, TIME_GEN);
-               revokedInfo.revocationTime.Data = (uint8 *)revokedAt; 
-               revokedInfo.revocationTime.Length = strlen(revokedAt);
-               uint8 theReason = reason;
-               reasonData.Data = &theReason;
-               reasonData.Length = 1;
-               revokedInfo.revocationReason = &reasonData;
-               ortn = SecAsn1EncodeItem(coder, &certStatus, 
-                       kSecAsn1OCSPCertStatusRevokedTemplate, 
-                       &singleResp.certStatus);
-       }
-       else {
-               ortn = SecAsn1EncodeItem(coder, &certStatus, 
-                       kSecAsn1OCSPCertStatusGoodTemplate,
-                       &singleResp.certStatus);
-       }
-       if(ortn) {
-               printf("***Error encoding certStatus\n"); 
-               goto errOut;
-       }
-       
-       /* SingleResponse.thisUpdate */
-       thisUpdStr = appTimeAtNowPlus(thisUpdate, TIME_GEN);
-       thisUpdateData = &singleResp.thisUpdate;
-       thisUpdateData->Data = (uint8 *)thisUpdStr;
-       thisUpdateData->Length = strlen(thisUpdStr);
-       
-       /* SingleResponse.nextUpdate, optional */
-       if(nextUpdate) {
-               nextUpdStr = appTimeAtNowPlus(nextUpdate, TIME_GEN); 
-               nextUpdateData.Data = (uint8 *)nextUpdStr;
-               nextUpdateData.Length = strlen(nextUpdStr);
-               singleResp.nextUpdate = &nextUpdateData;
-       }
-       
-       /* Single Extensions - none for now */
-        
-       /* Now up to ResponseData */
-       memset(&responseData, 0, sizeof(responseData));
-       
-       /* skip version */
-       
-       /* 
-        * ResponseData.responderID: KeyHash (of signer); we already got this for CertID.
-        * WE have to encode this one separately and drop it in as an ASN_ANY. 
-        */
-       responderID.byKey = certId.issuerPubKeyHash;
-       ortn = SecAsn1EncodeItem(coder, &responderID, 
-               kSecAsn1OCSPResponderIDAsKeyTemplate,
-               &responseData.responderID);
-       if(ortn) {
-               printf("***Error encoding responderID\n");
-               goto errOut;
-       }
-       
-       /* ResponseData.producedAt = now */
-       producedAt = appTimeAtNowPlus(0, TIME_GEN);
-       responseData.producedAt.Data = (uint8 *)producedAt;
-       responseData.producedAt.Length = strlen(producedAt);
-               
-       /* ResponseData.responses - one of 'em */
-       responseData.responses = respArray;
-       
-       /* ResponseData.responseExtensions - optionally one, nonce */
-       if(nonce) {
-               nonceExt = new OCSPNonce(coder, false, *nonce);
-               extenArray[0] = nonceExt->nssExt();
-               responseData.responseExtensions = extenArray;
-       }
-       else {
-               responseData.responseExtensions = NULL;
-       }
-       
-       /* encode it */
-       encodedTbs.Data = NULL;
-       encodedTbs.Length = 0;
-       ortn = SecAsn1EncodeItem(coder, &responseData, 
-               kSecAsn1OCSPResponseDataTemplate,
-               &encodedTbs);
-       if(ortn) {
-               printf("***Error encoding SecAsn1OCSPResponseData\n");
-       }
-errOut:
-       /* free resources */
-       if(revokedAt) {
-               CSSM_FREE(revokedAt);
-       }
-       if(thisUpdStr) {
-               CSSM_FREE(thisUpdStr);
-       }
-       if(nextUpdStr) {
-               CSSM_FREE(nextUpdStr);
-       }
-       if(nonceExt) {
-               delete nonceExt;
-       }
-       return ortn;
-}
-
-static int genOcspReq(
-       CSSM_CL_HANDLE clHand,
-       const unsigned char *certFile, 
-       unsigned certFileLen, 
-       const unsigned char *issuerCertFile, 
-       unsigned issuerCertFileLen, 
-       unsigned char **outFile,                // RETURNED 
-       unsigned *outFileLen)                   // RETURNED
-{
-       CertParser parser(clHand);
-       CertParser issuerParser(clHand);
-       CSSM_DATA certData = {certFileLen, (uint8 *)certFile};
-       CSSM_RETURN crtn;
-       crtn = parser.initWithData(certData);
-       if(crtn) {
-               cssmPerror("CertParser.initWithData for subject cert", crtn);
-               return -1;
-       }
-       certData.Data = (uint8 *)issuerCertFile;
-       certData.Length = issuerCertFileLen;
-       crtn = issuerParser.initWithData(certData);
-       if(crtn) {
-               cssmPerror("CertParser.initWithData for issuer", crtn);
-               return -1;
-       }
-       
-       /* 
-        * One single request, no extensions
-        */
-       SecAsn1OCSPRequest singleReq;
-       memset(&singleReq, 0, sizeof(singleReq));
-       SecAsn1OCSPCertID &certId = singleReq.reqCert;
-
-       /* 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);
-       
-       /* SHA1(issuerName) */
-       CSSM_DATA issuerName = {0, NULL};
-       issuerName.Data = (uint8 *)parser.fieldForOid(CSSMOID_X509V1IssuerNameStd, 
-               issuerName.Length);
-       if(issuerName.Data == NULL) {
-               printf("***Error fetching issuer name. Aborting.\n");
-               return 1;
-       }
-       uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH];
-       ocspdSha1(issuerName.Data, issuerName.Length, issuerNameHash);
-       
-       /* SHA1(issuer public key) */
-       CSSM_KEY_PTR pubKey = NULL;
-       CSSM_SIZE pubKeyLen = sizeof(CSSM_KEY);
-       pubKey = (CSSM_KEY_PTR)issuerParser.fieldForOid(CSSMOID_CSSMKeyStruct, pubKeyLen);
-       if(pubKey == NULL) {
-               printf("***Error fetching public key from issuer cert. Aborting.\n");
-               return 1;
-       }
-       uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH];
-       ocspdSha1(pubKey->KeyData.Data, pubKey->KeyData.Length, pubKeyHash);
-
-       /* serial number */
-       CSSM_DATA serialNum = {0, NULL};
-       serialNum.Data = (uint8 *)parser.fieldForOid(CSSMOID_X509V1SerialNumber, 
-               serialNum.Length);
-       if(serialNum.Data == NULL) {
-               printf("***Error fetching serial number. Aborting.\n");
-               return 1;
-       }
-
-       /* 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 = serialNum;
-
-       /* 
-        * Build top level request with one entry in requestList, no signature,
-        * one extension (a nonce)
-        */
-       SecAsn1OCSPSignedRequest signedReq;
-       SecAsn1OCSPRequest *reqArray[2] = { &singleReq, NULL };
-       SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest;
-       memset(&signedReq, 0, sizeof(signedReq));
-       uint8 version = 0;
-       CSSM_DATA vers = {1, &version};
-       tbs.version = &vers;
-       tbs.requestList = reqArray;
-
-       /* one extension - the nonce */
-       SecAsn1CoderRef coder;
-       SecAsn1CoderCreate(&coder);
-       uint8 nonceBytes[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
-       CSSM_DATA nonceData = {8, nonceBytes};
-       OCSPNonce *nonce = new OCSPNonce(coder, false, nonceData);
-       NSS_CertExtension *extenArray[2] = {nonce->nssExt(), NULL};
-       tbs.requestExtensions = extenArray;
-       
-       /* Encode */
-       OSStatus ortn;
-       CSSM_DATA encoded = {0, NULL};
-       ortn = SecAsn1EncodeItem(coder, &signedReq, kSecAsn1OCSPSignedRequestTemplate,
-               &encoded);
-       if(ortn) {
-               printf("***Error encoding SecAsn1OCSPSignedRequest\n");
-       }
-       else {
-               *outFile = (unsigned char *)malloc(encoded.Length);
-               *outFileLen = encoded.Length;
-               memmove(*outFile, encoded.Data, encoded.Length);
-       }
-       SecAsn1CoderRelease(coder);
-       return (int)ortn;
-}
-
-static void dumpCertID(
-       SecAsn1OCSPCertID *certID,
-       int indent)
-{
-       doIndent(indent);
-       printf("algId            : ");
-       printDataAsHex(&certID->algId.algorithm);
-       
-       doIndent(indent);
-       printf("issuerNameHash   : ");
-       printDataAsHex(&certID->issuerNameHash);
-       
-       doIndent(indent);
-       printf("issuerPubKeyHash : ");
-       printDataAsHex(&certID->issuerPubKeyHash);
-       
-       doIndent(indent);
-       printf("serialNumber     : ");
-       printDataAsHex(&certID->serialNumber);
-}
-
-static void printCritical(
-       int indent,
-       OCSPExtension *ocspExt)
-{
-       doIndent(indent);
-       printf("Critical           : %s\n", ocspExt->critical() ? "true" : "false");
-}
-
-static void printOcspExt(
-       SecAsn1CoderRef coder,
-       NSS_CertExtension *nssExt, 
-       int indent)
-{
-       OCSPExtension *ocspExt = NULL;
-       try {
-               ocspExt = OCSPExtension::createFromNSS(coder, *nssExt);
-       }
-       catch(...) {
-               doIndent(indent);
-               printf("***Error thrown parsing extension\n");
-               return;
-       }
-       switch(ocspExt->tag()) {
-               case OET_Unknown: 
-                       doIndent(indent);
-                       printf("Extension type: Unknown\n");
-                       printCritical(indent, ocspExt);
-                       return;
-               case OET_Nonce: 
-               {
-                       doIndent(indent);
-                       printf("Extension type     : Nonce\n");
-                       printCritical(indent, ocspExt);
-                       doIndent(indent);
-                       OCSPNonce *nonce = dynamic_cast<OCSPNonce *>(ocspExt);
-                       if(nonce == NULL) {
-                               printf("***dynamic_cast failure in OCSPNonce!\n");
-                               return;
-                       }
-                       printf("nonce value        : ");
-                       printDataAsHex(&nonce->nonce());
-                       break;
-               }
-               case OET_CrlReference: 
-                       doIndent(indent);
-                       printf("Extension type     : CrlReference");
-                       printCritical(indent, ocspExt);
-                       /* TBD */
-                       return;
-               case OET_AcceptResponse: 
-                       doIndent(indent);
-                       printf("Extension type     : AcceptResponse");
-                       printCritical(indent, ocspExt);
-                       /* TBD */
-                       return;
-               case OET_ArchiveCutoff:
-                       doIndent(indent);
-                       printf("Extension type     : ArchiveCutoff");
-                       printCritical(indent, ocspExt);
-                       /* TBD */
-                       return;
-               case OET_ServiceLocator:
-                       doIndent(indent);
-                       printf("Extension type     : ServiceLocator");
-                       printCritical(indent, ocspExt);
-                       /* TBD */
-                       return;
-               default:
-                       /* this code is out of sync with ocspExtensions.{h,cpp} */
-                       doIndent(indent);
-                       printf("Extension type     : unrecognized - code sync error");
-                       printCritical(indent, ocspExt);
-                       return;
-                       
-       }
-}
-
-static int parseOcspReq(
-       CSSM_CL_HANDLE clHand, 
-       unsigned char *inFile, 
-       unsigned inFileLen,
-       bool verbose)
-{
-       SecAsn1CoderRef coder;
-       SecAsn1OCSPSignedRequest signedReq;
-       SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest;
-       OSStatus ortn;
-       int indent;
-       unsigned numExts;
-       unsigned numReqs;
-       
-       SecAsn1CoderCreate(&coder);
-       memset(&signedReq, 0, sizeof(signedReq));
-       
-       ortn = SecAsn1Decode(coder, inFile, inFileLen, kSecAsn1OCSPSignedRequestTemplate,
-               &signedReq);
-       if(ortn) {
-               printf("***Error decoding SecAsn1OCSPSignedRequest\n");
-               goto errOut;
-       }
-       printf("SecAsn1OCSPSignedRequest:\n");
-       
-       printf("SecAsn1OCSPTbsRequest:\n");
-       indent = 2;
-       if(tbs.version) {
-               doIndent(indent);
-               printf("Version : ");
-               printDataAsHex(tbs.version);
-       }
-       if(tbs.requestorName) {
-               doIndent(indent);
-               printf("NSS_GeneralName found; print it later maybe\n");
-       }
-       numReqs = ocspdArraySize((const void **)tbs.requestList);
-       for(unsigned dex=0; dex<numReqs; dex++) {
-               SecAsn1OCSPRequest *req = tbs.requestList[dex];
-               doIndent(indent);
-               printf("Request List Entry %u\n", dex);
-               indent += 2;
-               doIndent(indent);
-               printf("CertID:\n");
-               indent += 2;
-               SecAsn1OCSPCertID *certID = &req->reqCert;
-               dumpCertID(certID, indent);
-               indent -= 2;
-               numExts = ocspdArraySize((const void **)req->extensions);
-               for(unsigned extDex=0; extDex<numExts; extDex++) {
-                       doIndent(indent);
-                       printf("singleExtension[%u]\n", extDex);
-                       printOcspExt(coder, req->extensions[dex], indent + 2);
-               }
-               indent -= 2;
-       }
-
-       numExts = ocspdArraySize((const void **)tbs.requestExtensions);
-       for(unsigned extDex=0; extDex<numExts; extDex++) {
-               doIndent(indent);
-               printf("requestExtension[%u]\n", extDex);
-               printOcspExt(coder, tbs.requestExtensions[extDex], indent + 2);
-       }
-
-       indent -= 2;
-       
-       if(signedReq.signature) {
-               printf("SecAsn1OCSPSignature:\n");
-               indent += 2;
-               doIndent(indent);
-               printf("==unparsed for now ==\n");
-               /* ... */
-               indent -= 2;
-       }
-errOut:
-       SecAsn1CoderRelease(coder);
-       return ortn;
-}
-
-static int genOcspResp(
-       CSSM_CL_HANDLE clHand, 
-       SecAsn1OCSPCertStatusTag status,
-       CE_CrlReason reason,                    // for CS_Revoked
-       const unsigned char *subjectCert,
-       unsigned subjectCertLen,
-       const unsigned char *issuerCert,
-       unsigned issuerCertLen,
-       SecIdentityRef signer,
-       unsigned char **outData,
-       unsigned *outDataLen)
-{
-       SecAsn1CoderRef coder;
-       SecAsn1CoderCreate(&coder);
-
-       CSSM_DATA subjectCertData = {subjectCertLen, (uint8 *)subjectCert};
-       CSSM_DATA issuerCertData = {issuerCertLen, (uint8 *)issuerCert};
-       uint8 nonceBytes[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
-       CSSM_DATA nonceData = {8, nonceBytes};
-       CSSM_DATA tbs;
-       CSSM_DATA encoded = {0, NULL};
-       SecAsn1OCSPResponse topResponse;
-       SecAsn1OCSPResponseBytes responseBytes;
-       uint8 responseStatusByte;
-       CSSM_DATA resp = {0, NULL};
-       CSSM_DATA sig = {0, NULL};
-       
-       int irtn = genTbsResp(coder, clHand, status, reason, 
-               subjectCertData, issuerCertData,
-               0,                      // thisUpdate
-               2600 * 24,      // next update
-               &nonceData,
-               tbs);
-       if(irtn) {
-               printf("***Error encoding tbsResp\n");
-               return irtn;
-       }
-       
-       /* 
-        * That's the TBSResponseData. Sign it.
-        */
-       OSStatus ortn;
-       SecAsn1OCSPBasicResponse basicResp;
-       memset(&basicResp, 0, sizeof(basicResp));
-       ortn = ocspSign(signer, tbs, CSSM_ALGID_SHA1WithRSA, sig);
-       if(ortn) {
-               printf("***Error signing basicResponse.\n");
-               goto errOut;
-       }
-       basicResp.algId.algorithm = CSSMOID_SHA1WithRSA;
-       basicResp.algId.parameters.Data = nullParam;
-       basicResp.algId.parameters.Length = sizeof(nullParam);
-       basicResp.tbsResponseData = tbs;
-       basicResp.sig = sig;
-       /* ASN1 encoder needs to know length in bits */
-       basicResp.sig.Length *= 8;
-       /* no certs for now */
-       /* encode SecAsn1OCSPBasicResponse */
-       
-       ortn = SecAsn1EncodeItem(coder, &basicResp, kSecAsn1OCSPBasicResponseTemplate,
-               &encoded);
-       if(ortn) {
-               printf("***Error encoding SecAsn1OCSPBasicResponse\n");
-       }
-       
-       /* put that into a SecAsn1OCSPResponse */
-       responseBytes.responseType = CSSMOID_PKIX_OCSP_BASIC;
-       responseBytes.response = encoded;
-       responseStatusByte = RS_Success;
-       topResponse.responseStatus.Data = &responseStatusByte;
-       topResponse.responseStatus.Length = 1;
-       topResponse.responseBytes = &responseBytes;
-       ortn = SecAsn1EncodeItem(coder, &topResponse, kSecAsn1OCSPResponseTemplate,
-               &resp);
-       if(ortn) {
-               printf("***Error encoding SecAsn1OCSPBasicResponse\n");
-               goto errOut;
-       }
-
-       /* TA DA */
-       *outData = (unsigned char *)malloc(resp.Length);
-       *outDataLen = resp.Length;
-       memmove(*outData, resp.Data, resp.Length);
-errOut:
-       SecAsn1CoderRelease(coder);
-       if(sig.Data) {
-               APP_FREE(sig.Data);
-       }
-       return ortn;
-}
-
-/* decode and parse tbsResponseData, sitting in SecAsn1OCSPBasicResponse as an 
- * ASN_ANY */
-static int     parseResponseData(
-       SecAsn1CoderRef coder,
-       int indent, 
-       const CSSM_DATA &tbsResponseData)
-{
-       SecAsn1OCSPResponseData respData;
-       SecAsn1OCSPResponderID responderID;
-       uint8 tag;
-       const SecAsn1Template *templ;
-       unsigned numExts;
-       
-       memset(&respData, 0, sizeof(respData));
-       OSStatus ortn = SecAsn1DecodeData(coder, &tbsResponseData,
-               kSecAsn1OCSPResponseDataTemplate, &respData);
-       if(ortn) {
-               printf("***Error decoding ResponseData\n");
-               return 1;
-       }
-       if(respData.version && respData.version->Data) {
-               doIndent(indent);
-               printf("version: %u\n", respData.version->Data[0]);
-       }
-       doIndent(indent);
-       printf("ResponderID:\n");
-       indent += 2;
-       memset(&responderID, 0, sizeof(responderID));
-       if(respData.responderID.Data == NULL) {
-               doIndent(indent);
-               printf("***Malformed(empty)***\n");
-               return 1;
-       }
-       
-       /* lame-o choice processing */
-       tag = respData.responderID.Data[0] & SEC_ASN1_TAGNUM_MASK;
-       switch(tag) {
-               case RIT_Name: 
-                       templ = kSecAsn1OCSPResponderIDAsNameTemplate; 
-                       break;
-               case RIT_Key: 
-                       templ = kSecAsn1OCSPResponderIDAsKeyTemplate; 
-                       break;
-               default:
-                       doIndent(indent);
-                       printf("**Unknown tag for ResponderID (%u)\n", tag);
-                       return 1;
-       }
-       ortn = SecAsn1DecodeData(coder, &respData.responderID, templ, &responderID);
-       if(ortn) {
-               doIndent(indent);
-               printf("***Error decoding ResponderID\n");
-               return 1;
-       }
-       doIndent(indent);
-       switch(tag) {
-               case RIT_Name:
-                       printf("byName:\n");
-                       printName((NSS_Name &)responderID.byName, indent + 2);
-                       break;
-               case RIT_Key:
-                       printf("byKey : ");
-                       printDataAsHex(&responderID.byKey);
-                       break;
-       }
-       indent -= 2;            // end of ResponderID
-       
-       doIndent(indent);
-       printf("producedAt: ");
-       printString(&respData.producedAt);
-       unsigned numResps = ocspdArraySize((const void **)respData.responses);
-       doIndent(indent);
-       printf("Num responses: %u\n", numResps);
-       for(unsigned dex=0; dex<numResps; dex++) {
-               SecAsn1OCSPSingleResponse *resp = respData.responses[dex];
-               doIndent(indent);
-               printf("Response %u:\n", dex);
-               indent += 2;
-               doIndent(indent);
-               printf("CertID:\n");
-               dumpCertID(&resp->certID, indent + 2);
-               
-               doIndent(indent);
-               printf("certStatus: ");
-               /* lame-o choice processing */
-               tag = resp->certStatus.Data[0] & SEC_ASN1_TAGNUM_MASK;
-               switch(tag) {
-                       case CS_Good:
-                               printf("Good\n");
-                               break;
-                       case CS_Unknown:
-                               printf("Unknown\n");
-                               break;
-                       default:
-                               printf("**MALFORMED cert status tag (%u)\n", tag);
-                               break;
-                       case CS_Revoked:
-                       {
-                               printf("Revoked\n");
-                               doIndent(indent);
-                               SecAsn1OCSPCertStatus certStatus;
-                               memset(&certStatus, 0, sizeof(certStatus));
-                               ortn = SecAsn1DecodeData(coder, &resp->certStatus, 
-                                       kSecAsn1OCSPCertStatusRevokedTemplate, &certStatus);
-                               if(ortn) {
-                                       doIndent(indent);
-                                       printf("***error parsing RevokedInfo\n");
-                                       break;
-                               }
-                               if(certStatus.revokedInfo == NULL) {
-                                       doIndent(indent);
-                                       printf("***GAK! Malformed (empty) revokedInfo\n");break;
-                               }
-                               printf("RevokedIndfo:\n");
-                               indent += 2;
-                               doIndent(indent);
-                               printf("revocationTime: ");
-                               printString(&certStatus.revokedInfo->revocationTime);
-                               if(certStatus.revokedInfo->revocationReason) {
-                                       doIndent(indent);
-                                       printf("reason: %u\n", 
-                                               certStatus.revokedInfo->revocationReason->Data[0]);
-                               }
-                               indent -= 2;            // end of RevokedInfo
-                               break;
-                       }
-               }       /* switch cert status tag */
-               
-               doIndent(indent);
-               printf("thisUpdate: ");
-               printString(&resp->thisUpdate);
-               
-               if(resp->nextUpdate) {
-                       doIndent(indent);
-                       printf("nextUpdate: ");
-                       printString(resp->nextUpdate);
-               }
-
-               numExts = ocspdArraySize((const void **)resp->singleExtensions);
-               for(unsigned extDex=0; extDex<numExts; extDex++) {
-                       doIndent(indent);
-                       printf("singleExtensions[%u]\n", extDex);
-                       printOcspExt(coder, resp->singleExtensions[extDex], indent + 2);
-               }
-               
-               indent -= 2;            // end of resp[dex]
-       }
-       
-       numExts = ocspdArraySize((const void **)respData.responseExtensions);
-       for(unsigned extDex=0; extDex<numExts; extDex++) {
-               doIndent(indent);
-               printf("responseExtensions[%u]\n", extDex);
-               printOcspExt(coder, respData.responseExtensions[extDex], indent + 2);
-       }
-       return 0;
-}
-
-static int parseOcspResp(
-       CSSM_CL_HANDLE clHand, 
-       unsigned char *inFile, 
-       unsigned inFileLen,
-       bool verbose)
-{
-       SecAsn1OCSPResponse topResp;
-       SecAsn1CoderRef coder;
-       OSStatus ortn;
-       int indent = 0;
-       const char *str;
-       SecAsn1OCSPBasicResponse basicResp;
-       unsigned numCerts = 0;
-       
-       SecAsn1CoderCreate(&coder);     
-       memset(&topResp, 0, sizeof(topResp));
-       ortn = SecAsn1Decode(coder, inFile, inFileLen, kSecAsn1OCSPResponseTemplate,
-               &topResp);
-       if(ortn) {
-               printf("***Error decoding SecAsn1OCSPResponse\n");
-               goto errOut;
-       }
-       printf("OCSPResponse:\n");
-       indent += 2;
-       doIndent(indent);
-       printf("responseStatus: ");
-       if(topResp.responseStatus.Length == 0) {
-               printf("**MALFORMED**\n");
-       }
-       else {
-               switch(topResp.responseStatus.Data[0]) {
-                       case RS_Success: str = "RS_Success"; break;
-                       case RS_MalformedRequest: str = "RS_MalformedRequest"; break;
-                       case RS_InternalError: str = "RS_InternalError"; break;
-                       case RS_TryLater: str = "RS_TryLater"; break;
-                       case RS_Unused: str = "RS_Unused"; break;
-                       case RS_SigRequired: str = "RS_SigRequired"; break;
-                       case RS_Unauthorized: str = "RS_Unauthorized"; break;
-                       default: str = "MALFORMED (unknown enum)\n"; break;
-               }
-               printf("%s (%u(d))\n", str, topResp.responseStatus.Data[0]);
-       }
-       doIndent(indent);
-       printf("ResponseBytes: ");
-       if(topResp.responseBytes == NULL) {
-               printf("empty\n");
-               goto errOut;
-       }
-       printf("\n");
-       indent += 2;
-       doIndent(indent);
-       printf("responseType: ");
-       if(appCompareCssmData(&topResp.responseBytes->responseType,
-                       &CSSMOID_PKIX_OCSP_BASIC)) {
-               str = "ocsp-basic";
-       }
-       else {
-               str = "Unknown type\n";
-       }
-       printf("%s\n", str);
-               
-       /* decode the BasicOCSPResponse */
-       memset(&basicResp, 0, sizeof(basicResp));
-       ortn = SecAsn1DecodeData(coder, &topResp.responseBytes->response,
-               kSecAsn1OCSPBasicResponseTemplate, &basicResp);
-       if(ortn) {
-               printf("***Error decoding BasicOCSPResponse\n");
-               goto errOut;
-       }
-       
-       doIndent(indent);
-       printf("BasicOCSPResponse:\n");
-       indent += 2;
-       doIndent(indent);
-       printf("ResponseData:\n");
-       parseResponseData(coder, indent + 2, basicResp.tbsResponseData);
-       doIndent(indent);
-       printf("sig: ");
-       printDataAsHex(&basicResp.sig, 8);
-       numCerts = ocspdArraySize((const void **)basicResp.certs);
-       doIndent(indent);
-       printf("Num Certs: %u\n", numCerts);
-       
-       if(verbose) {
-               for(unsigned dex=0; dex<numCerts; dex++) {
-                       printf("+++++++++++++++++++++++++ Cert %u +++++++++++++++++++++++++\n", dex);
-                       printCert(basicResp.certs[dex]->Data, basicResp.certs[dex]->Length, 
-                               CSSM_FALSE);
-                       printf("+++++++++++++++++++++++ End Cert %u +++++++++++++++++++++++\n", dex);
-               }
-       }
-       indent -= 2;            // end of BasicOCSPResponse
-       indent -= 2;            // end of ResponseBytes
-       indent -= 2;            // end of OCSPResponse
-errOut:
-       SecAsn1CoderRelease(coder);
-       return ortn;
-}
-
-static int postOcspReq(
-       CSSM_CL_HANDLE clHand,
-       const unsigned char *certFile, 
-       unsigned certFileLen, 
-       const unsigned char *issuerCertFile, 
-       unsigned issuerCertFileLen, 
-       const char *responderURI,
-       bool doParse,
-       bool verbose,
-       unsigned char **outFile,                // RETURNED 
-       unsigned *outFileLen)                   // RETURNED
-{
-       auto_ptr<CertParser> subject;
-       auto_ptr<CertParser> issuer;
-       CSSM_DATA uriData = {0, NULL};
-       CSSM_DATA *url = NULL;
-       
-       try {
-               CSSM_DATA cdata = {certFileLen, (uint8 *)certFile};
-               subject.reset(new CertParser(clHand, cdata));
-       }
-       catch(...) {
-               printf("***Error parsing subject cert. Aborting.\n");
-               return -1;
-       }
-       try {
-               CSSM_DATA cdata = {issuerCertFileLen, (uint8 *)issuerCertFile};
-               issuer.reset(new CertParser(clHand, cdata));
-       }
-       catch(...) {
-               printf("***Error parsing issuer cert. Aborting.\n");
-               return -1;
-       }
-       
-       SecAsn1CoderRef coder;
-       SecAsn1CoderCreate(&coder);
-       /* subsequent errors to errOut: */
-       int ourRtn = 0;
-       const CSSM_DATA *derReq = NULL;
-       auto_ptr<OCSPRequest> ocspReq;
-       
-       if(responderURI != NULL) {
-               uriData.Data = (uint8 *)responderURI;
-               uriData.Length = strlen(responderURI);
-               url = &uriData;
-       }
-       else {
-               /* get OCSP URL from subject cert */
-               url = ocspUrlFromCert(*subject, coder);
-               if(url == NULL) {
-                       printf("Sorry, no can do.\n");
-                       ourRtn = -1;
-                       goto errOut;
-               }
-       }
-       
-       /* create DER-encoded OCSP request for subject */
-       try {
-               ocspReq.reset(new OCSPRequest(*subject, *issuer, false));
-               derReq = ocspReq->encode();
-       }
-       catch(...) {
-               printf("***Error creating OCSP request. Aborting.\n");
-               ourRtn = -1;
-               goto errOut;
-       }
-       
-       /* do it */
-       CSSM_DATA ocspResp;
-       CSSM_RETURN crtn;
-       crtn = ocspdHttpPost(coder, *url, *derReq, ocspResp);
-       if(crtn) {
-               printf("***Error fetching OCSP response***\n");
-               cssmPerror("ocspdHttpPost", crtn);
-               ourRtn = -1;
-               goto errOut;
-       }
-       *outFile = ocspResp.Data;
-       *outFileLen = ocspResp.Length;
-       if(doParse) {
-               parseOcspResp(clHand, ocspResp.Data, ocspResp.Length, verbose);
-       }
-       /* copy out */
-       *outFile = (unsigned char *)malloc(ocspResp.Length);
-       *outFileLen = ocspResp.Length;
-       memmove(*outFile, ocspResp.Data, ocspResp.Length);
-
-errOut:
-       SecAsn1CoderRelease(coder);
-       return ourRtn;
-}
-
-typedef enum {
-       op_genReq,
-       op_parseReq,
-       op_genReply,
-       op_parseResp,
-       op_post
-} ocspOp;
-
-int main(int argc, char **argv)
-{
-       if(argc < 2) {
-               usage(argv);
-       }
-       ocspOp op;
-       switch(argv[1][0]) {
-               case 'g': op = op_genReq; break;
-               case 'G': op = op_parseReq; break;
-               case 'r': op = op_genReply; break;
-               case 'R': op = op_parseResp; break;
-               case 'p': op = op_post; break;
-               default: usage(argv);
-       }
-       
-       /* user defined vars */
-       char *inFile = NULL;
-       char *outFile = NULL;
-       char *inCertName = NULL;
-       char *issuerCertName = NULL;
-       SecAsn1OCSPCertStatusTag certStatus = CS_Good;
-       CE_CrlReason crlReason = CE_CR_Unspecified;
-       char *kcName = NULL;
-       bool verbose = false;
-       bool doParse = false;
-       const char *responderURI = NULL;
-       
-    extern int optind;
-       optind = 2;
-    extern char *optarg;
-       int arg;
-    while ((arg = getopt(argc, argv, "c:C:i:o:s:r:k:phvu:")) != -1) {
-               switch (arg) {
-                       case 'c':
-                               inCertName = optarg;
-                               break;
-                       case 'C':
-                               issuerCertName = optarg;
-                               break;
-                       case 'i':
-                               inFile = optarg;
-                               break;
-                       case 'o':
-                               outFile = optarg;
-                               break;
-                       case 's':
-                               switch(optarg[0]) {
-                                       case 'g':
-                                               certStatus = CS_Good;
-                                               break;
-                                       case 'r':
-                                               certStatus = CS_Revoked;
-                                               break;
-                                       case 'u':
-                                               certStatus = CS_Unknown;
-                                               break;
-                                       default:
-                                               printf("***Unrecognized certStatus***\n");
-                                               usage(argv);
-                               }
-                               break;
-                       case 'r':
-                               crlReason = atoi(optarg);
-                               break;
-                       case 'k':
-                               kcName = optarg;
-                               break;
-                       case 'v':
-                               verbose = 1;
-                               break;
-                       case 'p':
-                               doParse = true;
-                               break;
-                       case 'u':
-                               responderURI = optarg;
-                               break;
-                       default:
-                       case '?':
-                               usage(argv);
-               }
-       }
-       if(optind != argc) {
-               /* this happens if you give getopt() an arg which doesn't start with '-' */
-               usage(argv);
-       }
-       
-       unsigned char *certData = NULL;
-       unsigned certDataLen = 0;
-       unsigned char *issuerCertData = NULL;
-       unsigned issuerCertDataLen = 0;
-       unsigned char *inData = NULL;
-       unsigned inDataLen = 0;
-       unsigned char *outData = NULL;
-       unsigned outDataLen = 0;
-       SecKeychainRef kcRef = NULL;
-       OSStatus ortn;
-       
-       if(inCertName) {
-               if(readFile(inCertName, &certData, &certDataLen)) {
-                       printf("***Error reading cert file %s. Aborting.\n", inCertName);
-                       exit(1);
-               }
-       }
-       if(issuerCertName) {
-               if(readFile(issuerCertName, &issuerCertData, &issuerCertDataLen)) {
-                       printf("***Error reading cert file %s. Aborting.\n", issuerCertName);
-                       exit(1);
-               }
-       }
-       if(inFile) {
-               if(readFile(inFile, &inData, &inDataLen)) {
-                       printf("***Error reading input file %s. Aborting.\n", inFile);
-                       exit(1);
-               }
-       }
-       if(kcName) {
-               ortn = SecKeychainOpen(kcName, &kcRef);
-               if(ortn) {
-                       cssmPerror("SecKeychainOpen", ortn);
-                       return ortn;
-               }
-       }
-       CSSM_CL_HANDLE clHand = cuClStartup();
-       
-       switch(op) {
-               case op_genReq:
-                       ortn = genOcspReq(clHand, certData, certDataLen, 
-                               issuerCertData, issuerCertDataLen,
-                               &outData, &outDataLen);
-                       break;
-               case op_parseReq:
-                       ortn = parseOcspReq(clHand, inData, inDataLen, verbose);
-                       break;
-               case op_genReply:
-               {
-                       SecIdentityRef idRef = NULL;
-                       ortn = sslSimpleIdentPicker(kcRef, &idRef);
-                       if(ortn) {
-                               printf("***Error choosing identity. Aborting.\n");
-                               exit(1);
-                       }
-                       ortn = genOcspResp(clHand, certStatus, crlReason,
-                               certData, certDataLen, issuerCertData, issuerCertDataLen,
-                               idRef, &outData, &outDataLen);
-                       CFRelease(idRef);
-                       break;
-               }
-               case op_parseResp:
-                       ortn = parseOcspResp(clHand, inData, inDataLen, verbose);
-                       break;
-               case op_post:
-                       ortn = postOcspReq(clHand, certData, certDataLen, 
-                               issuerCertData, issuerCertDataLen, responderURI,
-                               doParse, verbose,
-                               &outData, &outDataLen);
-                       break;
-               default:        
-                       printf("Op %s is not yet implemented.\n", argv[1]);
-                       exit(1);
-       }
-       
-       if(ortn == 0) {
-               if(outData != NULL) {
-                       if(outFile== NULL) {
-                               printf("...generated %u bytes but no place to write it.\n", outDataLen);
-                       }
-                       else {
-                               ortn = writeFile(outFile, outData, outDataLen);
-                               if(ortn) {
-                                       printf("***Error writing output to %s.\n", outFile);
-                               }
-                               else {
-                                       printf("...wrote %u bytes to %s\n", outDataLen, outFile);
-                               }
-                       }
-               }
-       }
-       return ortn;
-}