Index: mozilla/security/nss/lib/certhigh/ocspsig.c |
=================================================================== |
--- mozilla/security/nss/lib/certhigh/ocspsig.c (revision 191424) |
+++ mozilla/security/nss/lib/certhigh/ocspsig.c (working copy) |
@@ -1,550 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
- |
-#include "plarena.h" |
- |
-#include "seccomon.h" |
-#include "secitem.h" |
-#include "secasn1.h" |
-#include "secder.h" |
-#include "cert.h" |
-#include "secerr.h" |
-#include "secoid.h" |
-#include "sechash.h" |
-#include "keyhi.h" |
-#include "cryptohi.h" |
-#include "ocsp.h" |
-#include "ocspti.h" |
-#include "ocspi.h" |
-#include "pk11pub.h" |
- |
- |
-extern const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[]; |
-extern const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[]; |
-extern const SEC_ASN1Template ocsp_OCSPResponseTemplate[]; |
- |
-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 const SEC_ASN1Template mySEC_EnumeratedTemplate[] = { |
- { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) } |
-}; |
- |
-static const SEC_ASN1Template mySEC_PointerToEnumeratedTemplate[] = { |
- { SEC_ASN1_POINTER, 0, mySEC_EnumeratedTemplate } |
-}; |
- |
-static const SEC_ASN1Template ocsp_EncodeRevokedInfoTemplate[] = { |
- { SEC_ASN1_GENERALIZED_TIME, |
- offsetof(ocspRevokedInfo, revocationTime) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC| 0, |
- offsetof(ocspRevokedInfo, revocationReason), |
- mySEC_PointerToEnumeratedTemplate }, |
- { 0 } |
-}; |
- |
-static const SEC_ASN1Template ocsp_PointerToEncodeRevokedInfoTemplate[] = { |
- { SEC_ASN1_POINTER, 0, |
- ocsp_EncodeRevokedInfoTemplate } |
-}; |
- |
-static const SEC_ASN1Template mySEC_NullTemplate[] = { |
- { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) } |
-}; |
- |
-static const SEC_ASN1Template ocsp_CertStatusTemplate[] = { |
- { SEC_ASN1_CHOICE, offsetof(ocspCertStatus, certStatusType), |
- 0, sizeof(ocspCertStatus) }, |
- { SEC_ASN1_CONTEXT_SPECIFIC | 0, |
- 0, mySEC_NullTemplate, ocspCertStatus_good }, |
- { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | |
- SEC_ASN1_CONTEXT_SPECIFIC | 1, |
- offsetof(ocspCertStatus, certStatusInfo.revokedInfo), |
- ocsp_PointerToEncodeRevokedInfoTemplate, ocspCertStatus_revoked }, |
- { SEC_ASN1_CONTEXT_SPECIFIC | 2, |
- 0, mySEC_NullTemplate, ocspCertStatus_unknown }, |
- { 0 } |
-}; |
- |
-static const SEC_ASN1Template mySECOID_AlgorithmIDTemplate[] = { |
- { SEC_ASN1_SEQUENCE, |
- 0, NULL, sizeof(SECAlgorithmID) }, |
- { SEC_ASN1_OBJECT_ID, |
- offsetof(SECAlgorithmID,algorithm), }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, |
- offsetof(SECAlgorithmID,parameters), }, |
- { 0, } |
-}; |
- |
-static const SEC_ASN1Template mySEC_AnyTemplate[] = { |
- { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) } |
-}; |
- |
-static const SEC_ASN1Template mySEC_SequenceOfAnyTemplate[] = { |
- { SEC_ASN1_SEQUENCE_OF, 0, mySEC_AnyTemplate } |
-}; |
- |
-static const SEC_ASN1Template mySEC_PointerToSequenceOfAnyTemplate[] = { |
- { SEC_ASN1_POINTER, 0, mySEC_SequenceOfAnyTemplate } |
-}; |
- |
-static const SEC_ASN1Template mySEC_IntegerTemplate[] = { |
- { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) } |
-}; |
- |
-static const SEC_ASN1Template mySEC_PointerToIntegerTemplate[] = { |
- { SEC_ASN1_POINTER, 0, mySEC_IntegerTemplate } |
-}; |
- |
-static const SEC_ASN1Template mySEC_GeneralizedTimeTemplate[] = { |
- { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)} |
-}; |
- |
-static const SEC_ASN1Template mySEC_PointerToGeneralizedTimeTemplate[] = { |
- { SEC_ASN1_POINTER, 0, mySEC_GeneralizedTimeTemplate } |
-}; |
- |
-static const SEC_ASN1Template ocsp_myCertIDTemplate[] = { |
- { SEC_ASN1_SEQUENCE, |
- 0, NULL, sizeof(CERTOCSPCertID) }, |
- { SEC_ASN1_INLINE, |
- offsetof(CERTOCSPCertID, hashAlgorithm), |
- mySECOID_AlgorithmIDTemplate }, |
- { SEC_ASN1_OCTET_STRING, |
- offsetof(CERTOCSPCertID, issuerNameHash) }, |
- { SEC_ASN1_OCTET_STRING, |
- offsetof(CERTOCSPCertID, issuerKeyHash) }, |
- { SEC_ASN1_INTEGER, |
- offsetof(CERTOCSPCertID, serialNumber) }, |
- { 0 } |
-}; |
- |
-static const SEC_ASN1Template myCERT_CertExtensionTemplate[] = { |
- { SEC_ASN1_SEQUENCE, |
- 0, NULL, sizeof(CERTCertExtension) }, |
- { SEC_ASN1_OBJECT_ID, |
- offsetof(CERTCertExtension,id) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ |
- offsetof(CERTCertExtension,critical) }, |
- { SEC_ASN1_OCTET_STRING, |
- offsetof(CERTCertExtension,value) }, |
- { 0, } |
-}; |
- |
-static const SEC_ASN1Template myCERT_SequenceOfCertExtensionTemplate[] = { |
- { SEC_ASN1_SEQUENCE_OF, 0, myCERT_CertExtensionTemplate } |
-}; |
- |
-static const SEC_ASN1Template myCERT_PointerToSequenceOfCertExtensionTemplate[] = { |
- { SEC_ASN1_POINTER, 0, myCERT_SequenceOfCertExtensionTemplate } |
-}; |
- |
-static const SEC_ASN1Template ocsp_mySingleResponseTemplate[] = { |
- { SEC_ASN1_SEQUENCE, |
- 0, NULL, sizeof(CERTOCSPSingleResponse) }, |
- { SEC_ASN1_POINTER, |
- offsetof(CERTOCSPSingleResponse, certID), |
- ocsp_myCertIDTemplate }, |
- { SEC_ASN1_ANY, |
- offsetof(CERTOCSPSingleResponse, derCertStatus) }, |
- { SEC_ASN1_GENERALIZED_TIME, |
- offsetof(CERTOCSPSingleResponse, thisUpdate) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, |
- offsetof(CERTOCSPSingleResponse, nextUpdate), |
- mySEC_PointerToGeneralizedTimeTemplate }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, |
- offsetof(CERTOCSPSingleResponse, singleExtensions), |
- myCERT_PointerToSequenceOfCertExtensionTemplate }, |
- { 0 } |
-}; |
- |
-static const SEC_ASN1Template ocsp_myResponseDataTemplate[] = { |
- { SEC_ASN1_SEQUENCE, |
- 0, NULL, sizeof(ocspResponseData) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */ |
- SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, |
- offsetof(ocspResponseData, version), |
- mySEC_PointerToIntegerTemplate }, |
- { SEC_ASN1_ANY, |
- offsetof(ocspResponseData, derResponderID) }, |
- { SEC_ASN1_GENERALIZED_TIME, |
- offsetof(ocspResponseData, producedAt) }, |
- { SEC_ASN1_SEQUENCE_OF, |
- offsetof(ocspResponseData, responses), |
- ocsp_mySingleResponseTemplate }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, |
- offsetof(ocspResponseData, responseExtensions), |
- myCERT_PointerToSequenceOfCertExtensionTemplate }, |
- { 0 } |
-}; |
- |
- |
-static const SEC_ASN1Template ocsp_EncodeBasicOCSPResponseTemplate[] = { |
- { SEC_ASN1_SEQUENCE, |
- 0, NULL, sizeof(ocspBasicOCSPResponse) }, |
- { SEC_ASN1_POINTER, |
- offsetof(ocspBasicOCSPResponse, tbsResponseData), |
- ocsp_myResponseDataTemplate }, |
- { SEC_ASN1_INLINE, |
- offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm), |
- mySECOID_AlgorithmIDTemplate }, |
- { SEC_ASN1_BIT_STRING, |
- offsetof(ocspBasicOCSPResponse, responseSignature.signature) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, |
- offsetof(ocspBasicOCSPResponse, responseSignature.derCerts), |
- mySEC_PointerToSequenceOfAnyTemplate }, |
- { 0 } |
-}; |
- |
-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; |
-} |
- |
-CERTOCSPSingleResponse* |
-CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena, |
- CERTOCSPCertID *id, |
- PRTime thisUpdate, |
- const PRTime *nextUpdate) |
-{ |
- ocspCertStatus * cs; |
- if (!arena) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- cs = ocsp_CreateCertStatus(arena, ocspCertStatus_good, 0); |
- if (!cs) |
- return NULL; |
- return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); |
-} |
- |
-CERTOCSPSingleResponse* |
-CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena, |
- CERTOCSPCertID *id, |
- PRTime thisUpdate, |
- const PRTime *nextUpdate) |
-{ |
- ocspCertStatus * cs; |
- if (!arena) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- cs = ocsp_CreateCertStatus(arena, ocspCertStatus_unknown, 0); |
- if (!cs) |
- return NULL; |
- return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); |
-} |
- |
-CERTOCSPSingleResponse* |
-CERT_CreateOCSPSingleResponseRevoked( |
- PLArenaPool *arena, |
- CERTOCSPCertID *id, |
- PRTime thisUpdate, |
- const PRTime *nextUpdate, |
- PRTime revocationTime, |
- const CERTCRLEntryReasonCode* revocationReason) |
-{ |
- ocspCertStatus * cs; |
- /* revocationReason is not yet supported, so it must be NULL. */ |
- if (!arena || revocationReason) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- cs = ocsp_CreateCertStatus(arena, ocspCertStatus_revoked, revocationTime); |
- if (!cs) |
- return NULL; |
- return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); |
-} |
- |
-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 || !responderCert || !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; |
- rid->responderIDType = responderIDType; |
- if (responderIDType == ocspResponderID_byName) { |
- responderIDTemplate = ocsp_ResponderIDByNameTemplate; |
- if (CERT_CopyName(tmpArena, &rid->responderIDValue.name, |
- &responderCert->subject) != SECSuccess) |
- goto done; |
- } |
- else { |
- responderIDTemplate = ocsp_ResponderIDByKeyTemplate; |
- if (!CERT_GetSPKIDigest(tmpArena, responderCert, SEC_OID_SHA1, |
- &rid->responderIDValue.keyHash)) |
- goto done; |
- } |
- |
- if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, |
- responderIDTemplate)) |
- 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; |
- |
- privKey = PK11_FindKeyByAnyCert(responderCert, wincx); |
- if (!privKey) |
- goto done; |
- |
- algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1); |
- if (algID == SEC_OID_UNKNOWN) |
- goto done; |
- |
- if (SEC_SignData(&br->responseSignature.signature, |
- br->tbsResponseDataDER.data, br->tbsResponseDataDER.len, |
- privKey, algID) |
- != SECSuccess) |
- goto done; |
- |
- /* convert len-in-bytes to len-in-bits */ |
- br->responseSignature.signature.len = br->responseSignature.signature.len << 3; |
- |
- /* br->responseSignature.signature wasn't allocated from arena, |
- * we must free it when done. */ |
- |
- if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorithm, algID, 0) |
- != SECSuccess) |
- goto done; |
- |
- if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br, |
- ocsp_EncodeBasicOCSPResponseTemplate)) |
- goto done; |
- |
- rb->responseTypeTag = SEC_OID_PKIX_OCSP_BASIC_RESPONSE; |
- |
- od = SECOID_FindOIDByTag(rb->responseTypeTag); |
- if (!od) |
- goto done; |
- |
- rb->responseType = od->oid; |
- rb->decodedResponse.basic = br; |
- |
- response->arena = tmpArena; |
- response->responseBytes = rb; |
- response->statusValue = ocspResponse_successful; |
- |
- if (!SEC_ASN1EncodeInteger(tmpArena, &response->responseStatus, |
- response->statusValue)) |
- goto done; |
- |
- result = SEC_ASN1EncodeItem(arena, NULL, response, ocsp_OCSPResponseTemplate); |
- |
-done: |
- if (privKey) |
- SECKEY_DestroyPrivateKey(privKey); |
- if (br->responseSignature.signature.data) |
- SECITEM_FreeItem(&br->responseSignature.signature, PR_FALSE); |
- PORT_FreeArena(tmpArena, PR_FALSE); |
- |
- return result; |
-} |
- |
-static const SEC_ASN1Template ocsp_OCSPErrorResponseTemplate[] = { |
- { SEC_ASN1_SEQUENCE, |
- 0, NULL, sizeof(CERTOCSPResponse) }, |
- { SEC_ASN1_ENUMERATED, |
- offsetof(CERTOCSPResponse, responseStatus) }, |
- { 0, 0, |
- mySEC_NullTemplate }, |
- { 0 } |
-}; |
- |
-SECItem* |
-CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error) |
-{ |
- CERTOCSPResponse response; |
- SECItem *result = NULL; |
- |
- switch (error) { |
- case SEC_ERROR_OCSP_MALFORMED_REQUEST: |
- response.statusValue = ocspResponse_malformedRequest; |
- break; |
- case SEC_ERROR_OCSP_SERVER_ERROR: |
- response.statusValue = ocspResponse_internalError; |
- break; |
- case SEC_ERROR_OCSP_TRY_SERVER_LATER: |
- response.statusValue = ocspResponse_tryLater; |
- break; |
- case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG: |
- response.statusValue = ocspResponse_sigRequired; |
- break; |
- case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST: |
- response.statusValue = ocspResponse_unauthorized; |
- break; |
- default: |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- |
- if (!SEC_ASN1EncodeInteger(NULL, &response.responseStatus, |
- response.statusValue)) |
- return NULL; |
- |
- result = SEC_ASN1EncodeItem(arena, NULL, &response, |
- ocsp_OCSPErrorResponseTemplate); |
- |
- SECITEM_FreeItem(&response.responseStatus, PR_FALSE); |
- |
- return result; |
-} |