ocsp.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,187 行 · 第 1/5 页
C
2,187 行
* XXX This should set an error, but since it is only temporary and * since PSM will not initially provide a way to turn on signing of * requests anyway, I figure we can just skip defining an error that * will be obsolete in the next release. When we are prepared to * put signing of requests back in, this entire check will go away, * and later in this function we will need to allocate a signature * structure for the request, fill in the "derCerts" field in it, * save the signerCert there, as well as fill in the "requestorName" * field of the tbsRequest. */ if (signerCert != NULL) { return NULL; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { goto loser; } request = PORT_ArenaZNew(arena, CERTOCSPRequest); if (request == NULL) { goto loser; } request->arena = arena; tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest); if (tbsRequest == NULL) { goto loser; } request->tbsRequest = tbsRequest; /* version 1 is the default, so we need not fill in a version number */ /* * Now create the list of single requests, one for each cert. */ tbsRequest->requestList = ocsp_CreateSingleRequestList(arena, certList, time, addServiceLocator); if (tbsRequest->requestList == NULL) { goto loser; } return request;loser: if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } return NULL;}/* * FUNCTION: CERT_AddOCSPAcceptableResponses * Add the AcceptableResponses extension to an OCSP Request. * INPUTS: * CERTOCSPRequest *request * The request to which the extension should be added. * ... * A list (of one or more) of SECOidTag -- each of the response types * to be added. The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE. * (This marks the end of the list, and it must be specified because a * client conforming to the OCSP standard is required to handle the basic * response type.) The OIDs are not checked in any way. * RETURN: * SECSuccess if the extension is added; SECFailure if anything goes wrong. * All errors are internal or low-level problems (e.g. no memory). */void SetRequestExts(void *object, CERTCertExtension **exts){ CERTOCSPRequest *request = (CERTOCSPRequest *)object; request->tbsRequest->requestExtensions = exts;}SECStatusCERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request, ...){ void *extHandle; va_list ap; int i, count; SECOidTag responseType; SECOidData *responseOid; SECItem **acceptableResponses = NULL; SECStatus rv = SECFailure; extHandle = request->tbsRequest->extensionHandle; if (extHandle == NULL) { extHandle = cert_StartExtensions(request, request->arena, SetRequestExts); if (extHandle == NULL) goto loser; } /* Count number of OIDS going into the extension value. */ count = 0; va_start(ap, request); do { count++; responseType = va_arg(ap, SECOidTag); } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE); va_end(ap); acceptableResponses = PORT_NewArray(SECItem *, count + 1); if (acceptableResponses == NULL) goto loser; va_start(ap, request); for (i = 0; i < count; i++) { responseType = va_arg(ap, SECOidTag); responseOid = SECOID_FindOIDByTag(responseType); acceptableResponses[i] = &(responseOid->oid); } va_end(ap); acceptableResponses[i] = NULL; rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE, &acceptableResponses, PR_FALSE, SEC_SequenceOfObjectIDTemplate); if (rv != SECSuccess) goto loser; PORT_Free(acceptableResponses); if (request->tbsRequest->extensionHandle == NULL) request->tbsRequest->extensionHandle = extHandle; return SECSuccess;loser: if (acceptableResponses != NULL) PORT_Free(acceptableResponses); if (extHandle != NULL) (void) CERT_FinishExtensions(extHandle); return rv;}/* * FUNCTION: CERT_DestroyOCSPRequest * Frees an OCSP Request structure. * INPUTS: * CERTOCSPRequest *request * Pointer to CERTOCSPRequest to be freed. * RETURN: * No return value; no errors. */voidCERT_DestroyOCSPRequest(CERTOCSPRequest *request){ if (request == NULL) return; if (request->tbsRequest != NULL) { if (request->tbsRequest->requestorName != NULL) CERT_DestroyGeneralNameList(request->tbsRequest->requestorName); if (request->tbsRequest->extensionHandle != NULL) (void) CERT_FinishExtensions(request->tbsRequest->extensionHandle); } if (request->optionalSignature != NULL) { if (request->optionalSignature->cert != NULL) CERT_DestroyCertificate(request->optionalSignature->cert); /* * XXX Need to free derCerts? Or do they come out of arena? * (Currently we never fill in derCerts, which is why the * answer is not obvious. Once we do, add any necessary code * here and remove this comment.) */ } /* * We should actually never have a request without an arena, * but check just in case. (If there isn't one, there is not * much we can do about it...) */ PORT_Assert(request->arena != NULL); if (request->arena != NULL) PORT_FreeArena(request->arena, PR_FALSE);}/* * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy): *//* * Helper function for encoding or decoding a ResponderID -- based on the * given type, return the associated template for that choice. */static const SEC_ASN1Template *ocsp_ResponderIDTemplateByType(ocspResponderIDType responderIDType){ const SEC_ASN1Template *responderIDTemplate; switch (responderIDType) { case ocspResponderID_byName: responderIDTemplate = ocsp_ResponderIDByNameTemplate; break; case ocspResponderID_byKey: responderIDTemplate = ocsp_ResponderIDByKeyTemplate; break; case ocspResponderID_other: default: PORT_Assert(responderIDType == ocspResponderID_other); responderIDTemplate = ocsp_ResponderIDOtherTemplate; break; } return responderIDTemplate;}/* * Helper function for encoding or decoding a CertStatus -- based on the * given type, return the associated template for that choice. */static const SEC_ASN1Template *ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType){ const SEC_ASN1Template *certStatusTemplate; switch (certStatusType) { case ocspCertStatus_good: certStatusTemplate = ocsp_CertStatusGoodTemplate; break; case ocspCertStatus_revoked: certStatusTemplate = ocsp_CertStatusRevokedTemplate; break; case ocspCertStatus_unknown: certStatusTemplate = ocsp_CertStatusUnknownTemplate; break; case ocspCertStatus_other: default: PORT_Assert(certStatusType == ocspCertStatus_other); certStatusTemplate = ocsp_CertStatusOtherTemplate; break; } return certStatusTemplate;}/* * Helper function for decoding a certStatus -- turn the actual DER tag * into our local translation. */static ocspCertStatusTypeocsp_CertStatusTypeByTag(int derTag){ ocspCertStatusType certStatusType; switch (derTag) { case 0: certStatusType = ocspCertStatus_good; break; case 1: certStatusType = ocspCertStatus_revoked; break; case 2: certStatusType = ocspCertStatus_unknown; break; default: certStatusType = ocspCertStatus_other; break; } return certStatusType;}/* * Helper function for decoding SingleResponses -- they each contain * a status which is encoded as CHOICE, which needs to be decoded "by hand". * * Note -- on error, this routine does not release the memory it may * have allocated; it expects its caller to do that. */static SECStatusocsp_FinishDecodingSingleResponses(PRArenaPool *arena, CERTOCSPSingleResponse **responses){ ocspCertStatus *certStatus; ocspCertStatusType certStatusType; const SEC_ASN1Template *certStatusTemplate; int derTag; int i; SECStatus rv = SECFailure; if (responses == NULL) /* nothing to do */ return SECSuccess; for (i = 0; responses[i] != NULL; i++) { /* * The following assert points out internal errors (problems in * the template definitions or in the ASN.1 decoder itself, etc.). */ PORT_Assert(responses[i]->derCertStatus.data != NULL); derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK; certStatusType = ocsp_CertStatusTypeByTag(derTag); certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType); certStatus = PORT_ArenaZAlloc(arena, sizeof(ocspCertStatus)); if (certStatus == NULL) { goto loser; } rv = SEC_ASN1DecodeItem(arena, certStatus, certStatusTemplate, &responses[i]->derCertStatus); if (rv != SECSuccess) { if (PORT_GetError() == SEC_ERROR_BAD_DER) PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); goto loser; } certStatus->certStatusType = certStatusType; responses[i]->certStatus = certStatus; } return SECSuccess;loser: return rv;}/* * Helper function for decoding a responderID -- turn the actual DER tag * into our local translation. */static ocspResponderIDTypeocsp_ResponderIDTypeByTag(int derTag){ ocspResponderIDType responderIDType; switch (derTag) { case 1: responderIDType = ocspResponderID_byName; break; case 2: responderIDType = ocspResponderID_byKey; break; default: responderIDType = ocspResponderID_other; break; } return responderIDType;}/* * Decode "src" as a BasicOCSPResponse, returning the result. */static ocspBasicOCSPResponse *ocsp_DecodeBasicOCSPResponse(PRArenaPool *arena, SECItem *src){ void *mark; ocspBasicOCSPResponse *basicResponse; ocspResponseData *responseData; ocspResponderID *responderID; ocspResponderIDType responderIDType; const SEC_ASN1Template *responderIDTemplate; int derTag; SECStatus rv; mark = PORT_ArenaMark(arena); basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse)); if (basicResponse == NULL) { goto loser; } rv = SEC_ASN1DecodeItem(arena, basicResponse, ocsp_BasicOCSPResponseTemplate, src); if (rv != SECSuccess) { if (PORT_GetError() == SEC_ERROR_BAD_DER) PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); goto loser; } responseData = basicResponse->tbsResponseData; /* * The following asserts point out internal errors (problems in * the template definitions or in the ASN.1 decoder itself, etc.). */ PORT_Assert(responseData != NULL); PORT_Assert(responseData->derResponderID.data != NULL); /* * XXX Because responderID is a CHOICE, which is not currently handled * by our ASN.1 decoder, we have to decode it "by hand". */ derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK; responderIDType = ocsp_ResponderIDTypeByTag(derTag); responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType); responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID)); if (responderID == NULL) { goto loser; } rv = SEC_ASN1DecodeItem(arena, responderID, responderIDTemplate, &responseData->derResponderID); if (rv != SECSuccess) { if (PORT_GetError() == SEC_ERROR_BAD_DER) PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); goto loser; } responderID->responderIDType = responderIDType; responseData->responderID = responderID; /* * XXX Each SingleResponse also contains a CHOICE, which has to be * fixed up by hand. */ rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses); if (rv != SECSuccess) { goto loser; } PORT_ArenaUnmark(arena, mark); return basicResponse;loser: PORT_ArenaRelease(arena, mark); return NULL;}/* * Decode the responseBytes based on the responseType found in "rbytes", * leaving the resulting translated/decoded information in there as well. */static SECStatusocsp_DecodeResponseBytes(PRArenaPool *arena, ocspResponseBytes *rbytes){ PORT_Assert(rbytes != NULL); /* internal error, really */ if (rbytes == NULL) PORT_SetError(SEC_ERROR_INVALID_ARGS); /* XXX set better error? */ rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType); switch (rbytes->responseTypeTag) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?