/* * Obtain a OCSPSingleResponse for a given raw encoded CertID. */ OCSPSingleResponse *OCSPResponse::singleResponseFor(const CSSM_DATA &matchCertID) { unsigned numResponses = ocspdArraySize((const void **)mResponseData.responses); for(unsigned dex=0; dex<numResponses; dex++) { SecAsn1OCSPSingleResponse *resp = mResponseData.responses[dex]; CSSM_DATA certID = {0, NULL}; if(SecAsn1EncodeItem(mCoder, &resp->certID, kSecAsn1OCSPCertIDTemplate, &certID)) { ocspdDebug("OCSPResponse::singleResponse: error encoding certID!"); return NULL; } if(!ocspdCompareCssmData(&matchCertID, &certID)) { /* try to find another */ continue; } try { OCSPSingleResponse *singleResp = new OCSPSingleResponse(resp); return singleResp; } catch(...) { /* try to find another... */ continue; } } ocspdDebug("OCSPResponse::singleResponse: certID not found"); return NULL; }
/* * Given DER-encoded issuer and serial number, create an encoded * IssuerAndSerialNumber. */ krb5_error_code krb5int_pkinit_issuer_serial_encode( const krb5_data *issuer, /* DER encoded */ const krb5_data *serial_num, krb5_data *issuer_and_serial) /* content mallocd and RETURNED */ { KRB5_IssuerAndSerial issuerSerial; SecAsn1CoderRef coder; CSSM_DATA ber = {0, NULL}; OSStatus ortn; if(SecAsn1CoderCreate(&coder)) { return ENOMEM; } PKI_KRB_TO_CSSM_DATA(issuer, &issuerSerial.derIssuer); PKI_KRB_TO_CSSM_DATA(serial_num, &issuerSerial.serialNumber); ortn = SecAsn1EncodeItem(coder, &issuerSerial, KRB5_IssuerAndSerialTemplate, &ber); if(ortn) { ortn = ENOMEM; goto errOut; } ortn = pkiCssmDataToKrb5Data(&ber, issuer_and_serial); errOut: SecAsn1CoderRelease(coder); return ortn; }
int derDecodeInit( TestParams *testParams) { /* * DER encode a sequence of two integers */ twoInts ti; ti.int1.Data = int1; ti.int1.Length = sizeof(int1); ti.int2.Data = int2; ti.int2.Length = sizeof(int2); /* encode --> tempDer */ SecAsn1CoderRef coder; SecAsn1CoderCreate(&coder); CSSM_DATA tmpDer = {0, NULL}; if(SecAsn1EncodeItem(coder, &ti, twoIntsTemp, &tmpDer)) { printf("***derDecodeInit: Error on encodeItem()\n"); return -1; } /* copy to goodDer and badDer */ appCopyCssmData(&tmpDer, &goodDer); appCopyCssmData(&tmpDer, &badDer); /* increment the length of the outer sequence to force error */ badDer.Data[1]++; SecAsn1CoderRelease(coder); return 0; }
/* * If responderID is of form RIT_Name, return the encoded version of the * NSS_Name (for comparison with issuer's subjectName). Evaluated lazily, * once, in mCoder space. */ const CSSM_DATA *OCSPResponse::encResponderName() { if(mResponderIdTag != RIT_Name) { assert(0); return NULL; } if(mEncResponderName.Data != NULL) { return &mEncResponderName; } if(SecAsn1EncodeItem(mCoder, &mResponderId.byName, kSecAsn1NameTemplate, &mEncResponderName)) { ocspdDebug("OCSPResponse::encResponderName: error encoding ResponderId!"); return NULL; } return &mEncResponderName; }
/* * Given a kerberos service tiocket in GSS form (i.e., an AP_REQ), * cook up a DER-encoded SPNEGO blob. Result is malloc'd; caller * must free. */ int spnegoCreateInit( const unsigned char *gssBlob, unsigned gssBlobLen, unsigned char **spnegoBlob, // mallocd and RETURNED unsigned *spnegoBlobLen) // RETURNED { SpnegoNegTokenInitGss negInit; SecAsn1CoderRef coder; if(SecAsn1CoderCreate(&coder)) { /* memory failure */ return -1; } memset(&negInit, 0, sizeof(negInit)); negInit.oid = CSSMOID_SPNEGO; negInit.token.mechTypeList = (CSSM_OID **)nssNullArray(coder, 2); negInit.token.mechTypeList[0] = (CSSM_OID *)&CSSMOID_KERB_V5_LEGACY; negInit.token.mechTypeList[1] = (CSSM_OID *)&CSSMOID_KERB_V5; /* no contextFlags for now, though we might need 'em */ CSSM_DATA gssData; if(gssBlob) { gssData.Data = (uint8 *)gssBlob; gssData.Length = gssBlobLen; negInit.token.mechToken = &gssData; } CSSM_DATA res = {0, NULL}; OSStatus ortn = SecAsn1EncodeItem(coder, &negInit, SpnegoNegTokenInitGssTemplate, &res); if(ortn) { SecAsn1CoderRelease(coder); return -1; } *spnegoBlob = (unsigned char *)malloc(res.Length); memmove(*spnegoBlob, res.Data, res.Length); *spnegoBlobLen = res.Length; /* this frees all memory allocated during SecAsn1EncodeItem() */ SecAsn1CoderRelease(coder); return 0; }
/* * Encode a ReplyKeyPack. The result is used as the Content of a SignedData. */ krb5_error_code krb5int_pkinit_reply_key_pack_encode( const krb5_keyblock *key_block, const krb5_checksum *checksum, krb5_data *reply_key_pack) /* mallocd and RETURNED */ { KRB5_ReplyKeyPack repKeyPack; SecAsn1CoderRef coder; krb5_error_code ourRtn = 0; CSSM_DATA der = {0, NULL}; OSStatus ortn; KRB5_EncryptionKey *encryptKey = &repKeyPack.encryptionKey; KRB5_Checksum *cksum = &repKeyPack.asChecksum; if(SecAsn1CoderCreate(&coder)) { return ENOMEM; } memset(&repKeyPack, 0, sizeof(repKeyPack)); if((ourRtn = pkiIntToData(key_block->enctype, &encryptKey->keyType, coder))) { goto errOut; } encryptKey->keyValue.Length = key_block->length, encryptKey->keyValue.Data = (uint8 *)key_block->contents; if((ourRtn = pkiIntToData(checksum->checksum_type, &cksum->checksumType, coder))) { goto errOut; } cksum->checksum.Data = (uint8 *)checksum->contents; cksum->checksum.Length = checksum->length; ortn = SecAsn1EncodeItem(coder, &repKeyPack, KRB5_ReplyKeyPackTemplate, &der); if(ortn) { ourRtn = ENOMEM; goto errOut; } ourRtn = pkiCssmDataToKrb5Data(&der, reply_key_pack); errOut: SecAsn1CoderRelease(coder); return ourRtn; }
/* * DER encode in specified coder's memory. */ const CSSM_DATA *OCSPClientCertID::encode() { if(mEncoded.Data != NULL) { return &mEncoded; } SecAsn1OCSPCertID certID; uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH]; uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH]; /* 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) */ ocspdSha1(mIssuerName.Data, (CC_LONG)mIssuerName.Length, issuerNameHash); /* SHA1(issuer public key bytes) */ ocspdSha1(mIssuerPubKey.Data, (CC_LONG)mIssuerPubKey.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 = mSubjectSerial; /* encode */ SecAsn1CoderRef coder; SecAsn1CoderCreate(&coder); CSSM_DATA tmp = {0, NULL}; SecAsn1EncodeItem(coder, &certID, kSecAsn1OCSPCertIDTemplate, &tmp); allocCopyData(tmp, mEncoded); SecAsn1CoderRelease(coder); return &mEncoded; }
/* * Encode a KRB5_PA_PK_AS_REP. */ krb5_error_code krb5int_pkinit_pa_pk_as_rep_encode( const krb5_data *dh_signed_data, const krb5_data *enc_key_pack, krb5_data *pa_pk_as_rep) /* mallocd and RETURNED */ { KRB5_PA_PK_AS_REP asRep; SecAsn1CoderRef coder; krb5_error_code ourRtn = 0; CSSM_DATA der = {0, NULL}; OSStatus ortn; CSSM_DATA dhSignedData; CSSM_DATA encKeyPack; if(SecAsn1CoderCreate(&coder)) { return ENOMEM; } memset(&asRep, 0, sizeof(asRep)); if(dh_signed_data) { PKI_KRB_TO_CSSM_DATA(dh_signed_data, &dhSignedData); asRep.dhSignedData = &dhSignedData; } if(enc_key_pack) { PKI_KRB_TO_CSSM_DATA(enc_key_pack, &encKeyPack); asRep.encKeyPack = &encKeyPack; } ortn = SecAsn1EncodeItem(coder, &asRep, KRB5_PA_PK_AS_REPTemplate, &der); if(ortn) { ourRtn = ENOMEM; goto errOut; } ourRtn = pkiCssmDataToKrb5Data(&der, pa_pk_as_rep); errOut: SecAsn1CoderRelease(coder); return ourRtn; }
/* * Top-level encode for PA-PK-AS-REQ. */ krb5_error_code krb5int_pkinit_pa_pk_as_req_encode( const krb5_data *signed_auth_pack, /* DER encoded ContentInfo */ const krb5_data *trusted_CAs, /* optional: trustedCertifiers. Contents are * DER-encoded issuer/serialNumbers. */ krb5_ui_4 num_trusted_CAs, const krb5_data *kdc_cert, /* optional kdcPkId, DER encoded issuer/serial */ krb5_data *pa_pk_as_req) /* mallocd and RETURNED */ { KRB5_PA_PK_AS_REQ req; SecAsn1CoderRef coder; CSSM_DATA ber = {0, NULL}; OSStatus ortn; unsigned dex; assert(signed_auth_pack != NULL); assert(pa_pk_as_req != NULL); if(SecAsn1CoderCreate(&coder)) { return ENOMEM; } /* krb5_data ==> CSSM format */ memset(&req, 0, sizeof(req)); PKI_KRB_TO_CSSM_DATA(signed_auth_pack, &req.signedAuthPack); if(num_trusted_CAs) { /* * Set up a NULL-terminated array of KRB5_ExternalPrincipalIdentifier * pointers. We malloc the actual KRB5_ExternalPrincipalIdentifiers as * a contiguous array; it's in temp SecAsn1CoderRef memory. The referents * are just dropped in from the caller's krb5_datas. */ KRB5_ExternalPrincipalIdentifier *cas = (KRB5_ExternalPrincipalIdentifier *)SecAsn1Malloc(coder, num_trusted_CAs * sizeof(KRB5_ExternalPrincipalIdentifier)); req.trusted_CAs = (KRB5_ExternalPrincipalIdentifier **) pkiNssNullArray(num_trusted_CAs, coder); for(dex=0; dex<num_trusted_CAs; dex++) { req.trusted_CAs[dex] = &cas[dex]; memset(&cas[dex], 0, sizeof(KRB5_ExternalPrincipalIdentifier)); PKI_KRB_TO_CSSM_DATA(&trusted_CAs[dex], &cas[dex].issuerAndSerialNumber); } } if(kdc_cert) { PKI_KRB_TO_CSSM_DATA(kdc_cert, &req.kdcPkId); } /* encode */ ortn = SecAsn1EncodeItem(coder, &req, KRB5_PA_PK_AS_REQTemplate, &ber); if(ortn) { ortn = ENOMEM; goto errOut; } ortn = pkiCssmDataToKrb5Data(&ber, pa_pk_as_req); errOut: SecAsn1CoderRelease(coder); return ortn; }
/* * Encode AuthPack, public key version (no Diffie-Hellman components). */ krb5_error_code krb5int_pkinit_auth_pack_encode( krb5_timestamp kctime, krb5_int32 cusec, /* microseconds */ krb5_ui_4 nonce, const krb5_checksum *pa_checksum, const krb5int_algorithm_id *cms_types, /* optional */ krb5_ui_4 num_cms_types, krb5_data *auth_pack) /* mallocd and RETURNED */ { KRB5_AuthPack localAuthPack; SecAsn1CoderRef coder; CSSM_DATA *cksum = &localAuthPack.pkAuth.paChecksum; krb5_error_code ourRtn = 0; CSSM_DATA ber = {0, NULL}; OSStatus ortn; char *timeStr = NULL; if(SecAsn1CoderCreate(&coder)) { return ENOMEM; } memset(&localAuthPack, 0, sizeof(localAuthPack)); if(pkiKrbTimestampToStr(kctime, &timeStr)) { ourRtn = -1; goto errOut; } localAuthPack.pkAuth.kctime.Data = (uint8 *)timeStr; localAuthPack.pkAuth.kctime.Length = strlen(timeStr); if(pkiIntToData(cusec, &localAuthPack.pkAuth.cusec, coder)) { ourRtn = ENOMEM; goto errOut; } if(pkiIntToData(nonce, &localAuthPack.pkAuth.nonce, coder)) { ourRtn = ENOMEM; goto errOut; } cksum->Data = (uint8 *)pa_checksum->contents; cksum->Length = pa_checksum->length; if((cms_types != NULL) && (num_cms_types != 0)) { unsigned dex; CSSM_X509_ALGORITHM_IDENTIFIER **algIds; /* build a NULL_terminated array of CSSM_X509_ALGORITHM_IDENTIFIERs */ localAuthPack.supportedCMSTypes = (CSSM_X509_ALGORITHM_IDENTIFIER **) SecAsn1Malloc(coder, (num_cms_types + 1) * sizeof(CSSM_X509_ALGORITHM_IDENTIFIER *)); algIds = localAuthPack.supportedCMSTypes; for(dex=0; dex<num_cms_types; dex++) { algIds[dex] = (CSSM_X509_ALGORITHM_IDENTIFIER *) SecAsn1Malloc(coder, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)); pkiKrb5DataToCssm(&cms_types[dex].algorithm, &algIds[dex]->algorithm, coder); if(cms_types[dex].parameters.data != NULL) { pkiKrb5DataToCssm(&cms_types[dex].parameters, &algIds[dex]->parameters, coder); } else { algIds[dex]->parameters.Data = NULL; algIds[dex]->parameters.Length = 0; } } algIds[num_cms_types] = NULL; } ortn = SecAsn1EncodeItem(coder, &localAuthPack, KRB5_AuthPackTemplate, &ber); if(ortn) { ourRtn = ENOMEM; goto errOut; } if(pkiCssmDataToKrb5Data(&ber, auth_pack)) { ourRtn = ENOMEM; } else { auth_pack->magic = KV5M_AUTHENTICATOR; ourRtn = 0; } errOut: SecAsn1CoderRelease(coder); return ourRtn; }
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; }
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; }
/* * 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; }
certId->issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH; certId->issuerNameHash.Data = (uint8_t *)CFDataGetBytePtr(issuerNameDigest); certId->issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH; certId->issuerPubKeyHash.Data = (uint8_t *)CFDataGetBytePtr(issuerPubKeyDigest); certId->serialNumber.Length = CFDataGetLength(serial); certId->serialNumber.Data = (uint8_t *)CFDataGetBytePtr(serial); /* Build top level request with one entry in requestList, no signature, and no optional extensions. */ tbs->version = &vers; tbs->requestList = reqArray; /* Encode the request. */ require_noerr(SecAsn1CoderCreate(&coder), errOut); SecAsn1Item encoded; require_noerr(SecAsn1EncodeItem(coder, &signedReq, kSecAsn1OCSPSignedRequestTemplate, &encoded), errOut); der = CFDataCreate(kCFAllocatorDefault, encoded.Data, encoded.Length); errOut: if (coder) SecAsn1CoderRelease(coder); CFReleaseSafe(issuerNameDigest); CFReleaseSafe(serial); CFReleaseSafe(issuerPubKeyDigest); return der; } SecOCSPRequestRef SecOCSPRequestCreate(SecCertificateRef certificate, SecCertificateRef issuer) {