ocspCertStatus* ocsp_CreateCertStatus(PLArenaPool *arena, ocspCertStatusType status, PRTime revocationTime) { ocspCertStatus *cs; if (!arena) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } switch (status) { case ocspCertStatus_good: case ocspCertStatus_unknown: case ocspCertStatus_revoked: break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } cs = PORT_ArenaZNew(arena, ocspCertStatus); if (!cs) return NULL; cs->certStatusType = status; switch (status) { case ocspCertStatus_good: cs->certStatusInfo.goodInfo = SECITEM_AllocItem(arena, NULL, 0); if (!cs->certStatusInfo.goodInfo) return NULL; break; case ocspCertStatus_unknown: cs->certStatusInfo.unknownInfo = SECITEM_AllocItem(arena, NULL, 0); if (!cs->certStatusInfo.unknownInfo) return NULL; break; case ocspCertStatus_revoked: cs->certStatusInfo.revokedInfo = PORT_ArenaZNew(arena, ocspRevokedInfo); if (!cs->certStatusInfo.revokedInfo) return NULL; cs->certStatusInfo.revokedInfo->revocationReason = SECITEM_AllocItem(arena, NULL, 0); if (!cs->certStatusInfo.revokedInfo->revocationReason) return NULL; if (DER_TimeToGeneralizedTimeArena(arena, &cs->certStatusInfo.revokedInfo->revocationTime, revocationTime) != SECSuccess) return NULL; break; default: PORT_Assert(PR_FALSE); } return cs; }
static CERTOCSPSingleResponse* ocsp_CreateSingleResponse(PLArenaPool *arena, CERTOCSPCertID *id, ocspCertStatus *status, PRTime thisUpdate, const PRTime *nextUpdate) { CERTOCSPSingleResponse *sr; if (!arena || !id || !status) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } sr = PORT_ArenaZNew(arena, CERTOCSPSingleResponse); if (!sr) return NULL; sr->arena = arena; sr->certID = id; sr->certStatus = status; if (DER_TimeToGeneralizedTimeArena(arena, &sr->thisUpdate, thisUpdate) != SECSuccess) return NULL; sr->nextUpdate = NULL; if (nextUpdate) { sr->nextUpdate = SECITEM_AllocItem(arena, NULL, 0); if (!sr->nextUpdate) return NULL; if (DER_TimeToGeneralizedTimeArena(arena, sr->nextUpdate, *nextUpdate) != SECSuccess) return NULL; } sr->singleExtensions = PORT_ArenaNewArray(arena, CERTCertExtension*, 1); if (!sr->singleExtensions) return NULL; sr->singleExtensions[0] = NULL; if (!SEC_ASN1EncodeItem(arena, &sr->derCertStatus, status, ocsp_CertStatusTemplate)) return NULL; return sr; }
SECStatus DER_TimeToGeneralizedTime(SECItem *dst, int64 gmttime) { return DER_TimeToGeneralizedTimeArena(NULL, dst, gmttime); }
/* responderCert == 0 means: * create a response with an invalid signature (for testing purposes) */ SECItem* CERT_CreateEncodedOCSPSuccessResponse( PLArenaPool *arena, CERTCertificate *responderCert, CERTOCSPResponderIDType responderIDType, PRTime producedAt, CERTOCSPSingleResponse **responses, void *wincx) { PLArenaPool *tmpArena; ocspResponseData *rd = NULL; ocspResponderID *rid = NULL; const SEC_ASN1Template *responderIDTemplate = NULL; ocspBasicOCSPResponse *br = NULL; ocspResponseBytes *rb = NULL; CERTOCSPResponse *response = NULL; SECOidTag algID; SECOidData *od = NULL; SECKEYPrivateKey *privKey = NULL; SECItem *result = NULL; if (!arena || !responses) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } if (responderIDType != ocspResponderID_byName && responderIDType != ocspResponderID_byKey) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!tmpArena) return NULL; rd = PORT_ArenaZNew(tmpArena, ocspResponseData); if (!rd) goto done; rid = PORT_ArenaZNew(tmpArena, ocspResponderID); if (!rid) goto done; br = PORT_ArenaZNew(tmpArena, ocspBasicOCSPResponse); if (!br) goto done; rb = PORT_ArenaZNew(tmpArena, ocspResponseBytes); if (!rb) goto done; response = PORT_ArenaZNew(tmpArena, CERTOCSPResponse); if (!response) goto done; rd->version.data=NULL; rd->version.len=0; rd->responseExtensions = NULL; rd->responses = responses; if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt) != SECSuccess) goto done; if (!responderCert) { /* use invalid signature for testing purposes */ unsigned char dummyChar = 'd'; SECItem dummy; dummy.len = 1; dummy.data = &dummyChar; /* it's easier to produdce a keyHash out of nowhere, * than to produce an encoded subject, * so for our dummy response we always use byKey */ rid->responderIDType = ocspResponderID_byKey; if (!ocsp_DigestValue(tmpArena, SEC_OID_SHA1, &rid->responderIDValue.keyHash, &dummy)) goto done; if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, ocsp_ResponderIDByKeyTemplate)) goto done; br->tbsResponseData = rd; if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData, ocsp_myResponseDataTemplate)) goto done; br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); if (!br->responseSignature.derCerts) goto done; br->responseSignature.derCerts[0] = NULL; algID = SEC_GetSignatureAlgorithmOidTag(rsaKey, SEC_OID_SHA1); if (algID == SEC_OID_UNKNOWN) goto done; /* match the regular signature code, which doesn't use the arena */ if (!SECITEM_AllocItem(NULL, &br->responseSignature.signature, 1)) goto done; PORT_Memcpy(br->responseSignature.signature.data, &dummyChar, 1); /* convert len-in-bytes to len-in-bits */ br->responseSignature.signature.len = br->responseSignature.signature.len << 3; }