mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-13 23:17:57 +00:00
36000fce8e
--HG-- rename : security/coreconf/AIX.mk => security/nss/coreconf/AIX.mk rename : security/coreconf/Android.mk => security/nss/coreconf/Android.mk rename : security/coreconf/BSD_OS.mk => security/nss/coreconf/BSD_OS.mk rename : security/coreconf/BeOS.mk => security/nss/coreconf/BeOS.mk rename : security/coreconf/Darwin.mk => security/nss/coreconf/Darwin.mk rename : security/coreconf/FreeBSD.mk => security/nss/coreconf/FreeBSD.mk rename : security/coreconf/HP-UX.mk => security/nss/coreconf/HP-UX.mk rename : security/coreconf/HP-UXA.09.03.mk => security/nss/coreconf/HP-UXA.09.03.mk rename : security/coreconf/HP-UXA.09.07.mk => security/nss/coreconf/HP-UXA.09.07.mk rename : security/coreconf/HP-UXA.09.mk => security/nss/coreconf/HP-UXA.09.mk rename : security/coreconf/HP-UXB.10.01.mk => security/nss/coreconf/HP-UXB.10.01.mk rename : security/coreconf/HP-UXB.10.10.mk => security/nss/coreconf/HP-UXB.10.10.mk rename : security/coreconf/HP-UXB.10.20.mk => security/nss/coreconf/HP-UXB.10.20.mk rename : security/coreconf/HP-UXB.10.30.mk => security/nss/coreconf/HP-UXB.10.30.mk rename : security/coreconf/HP-UXB.10.mk => security/nss/coreconf/HP-UXB.10.mk rename : security/coreconf/HP-UXB.11.00.mk => security/nss/coreconf/HP-UXB.11.00.mk rename : security/coreconf/HP-UXB.11.11.mk => security/nss/coreconf/HP-UXB.11.11.mk rename : security/coreconf/HP-UXB.11.20.mk => security/nss/coreconf/HP-UXB.11.20.mk rename : security/coreconf/HP-UXB.11.22.mk => security/nss/coreconf/HP-UXB.11.22.mk rename : security/coreconf/HP-UXB.11.23.mk => security/nss/coreconf/HP-UXB.11.23.mk rename : security/coreconf/HP-UXB.11.mk => security/nss/coreconf/HP-UXB.11.mk rename : security/coreconf/IRIX.mk => security/nss/coreconf/IRIX.mk rename : security/coreconf/IRIX5.2.mk => security/nss/coreconf/IRIX5.2.mk rename : security/coreconf/IRIX5.3.mk => security/nss/coreconf/IRIX5.3.mk rename : security/coreconf/IRIX5.mk => security/nss/coreconf/IRIX5.mk rename : security/coreconf/IRIX6.2.mk => security/nss/coreconf/IRIX6.2.mk rename : security/coreconf/IRIX6.3.mk => security/nss/coreconf/IRIX6.3.mk rename : security/coreconf/IRIX6.5.mk => security/nss/coreconf/IRIX6.5.mk rename : security/coreconf/IRIX6.mk => security/nss/coreconf/IRIX6.mk rename : security/coreconf/Linux.mk => security/nss/coreconf/Linux.mk rename : security/coreconf/Makefile => security/nss/coreconf/Makefile rename : security/coreconf/NCR3.0.mk => security/nss/coreconf/NCR3.0.mk rename : security/coreconf/NEC4.2.mk => security/nss/coreconf/NEC4.2.mk rename : security/coreconf/NetBSD.mk => security/nss/coreconf/NetBSD.mk rename : security/coreconf/OS2.mk => security/nss/coreconf/OS2.mk rename : security/coreconf/OSF1.mk => security/nss/coreconf/OSF1.mk rename : security/coreconf/OSF1V3.0.mk => security/nss/coreconf/OSF1V2.0.mk rename : security/coreconf/OSF1V3.0.mk => security/nss/coreconf/OSF1V3.0.mk rename : security/coreconf/OSF1V3.2.mk => security/nss/coreconf/OSF1V3.2.mk rename : security/coreconf/OSF1V4.0.mk => security/nss/coreconf/OSF1V4.0.mk rename : security/coreconf/OSF1V4.0B.mk => security/nss/coreconf/OSF1V4.0B.mk rename : security/coreconf/OSF1V4.0D.mk => security/nss/coreconf/OSF1V4.0D.mk rename : security/coreconf/OSF1V5.0.mk => security/nss/coreconf/OSF1V5.0.mk rename : security/coreconf/OSF1V5.1.mk => security/nss/coreconf/OSF1V5.1.mk rename : security/coreconf/OpenBSD.mk => security/nss/coreconf/OpenBSD.mk rename : security/coreconf/OpenUNIX.mk => security/nss/coreconf/OpenUNIX.mk rename : security/coreconf/QNX.mk => security/nss/coreconf/QNX.mk rename : security/coreconf/README => security/nss/coreconf/README rename : security/coreconf/RISCOS.mk => security/nss/coreconf/RISCOS.mk rename : security/coreconf/ReliantUNIX.mk => security/nss/coreconf/ReliantUNIX.mk rename : security/coreconf/ReliantUNIX5.4.mk => security/nss/coreconf/ReliantUNIX5.4.mk rename : security/coreconf/SCOOS5.0.mk => security/nss/coreconf/SCOOS5.0.mk rename : security/coreconf/SCO_SV3.2.mk => security/nss/coreconf/SCO_SV3.2.mk rename : security/coreconf/SunOS4.1.3_U1.mk => security/nss/coreconf/SunOS4.1.3_U1.mk rename : security/coreconf/UNIX.mk => security/nss/coreconf/UNIX.mk rename : security/coreconf/UNIXWARE2.1.mk => security/nss/coreconf/UNIXWARE2.1.mk rename : security/coreconf/WIN95.mk => security/nss/coreconf/WIN95.mk rename : security/coreconf/WINNT.mk => security/nss/coreconf/WINNT.mk rename : security/coreconf/arch.mk => security/nss/coreconf/arch.mk rename : security/coreconf/command.mk => security/nss/coreconf/command.mk rename : security/coreconf/coreconf.pl => security/nss/coreconf/coreconf.pl rename : security/coreconf/cpdist.pl => security/nss/coreconf/cpdist.pl rename : security/coreconf/headers.mk => security/nss/coreconf/headers.mk rename : security/coreconf/import.pl => security/nss/coreconf/import.pl rename : security/coreconf/jdk.mk => security/nss/coreconf/jdk.mk rename : security/coreconf/jniregen.pl => security/nss/coreconf/jniregen.pl rename : security/coreconf/location.mk => security/nss/coreconf/location.mk rename : security/coreconf/mkdepend/Makefile => security/nss/coreconf/mkdepend/Makefile rename : security/coreconf/mkdepend/cppsetup.c => security/nss/coreconf/mkdepend/cppsetup.c rename : security/coreconf/mkdepend/def.h => security/nss/coreconf/mkdepend/def.h rename : security/coreconf/mkdepend/ifparser.c => security/nss/coreconf/mkdepend/ifparser.c rename : security/coreconf/mkdepend/ifparser.h => security/nss/coreconf/mkdepend/ifparser.h rename : security/coreconf/mkdepend/imakemdep.h => security/nss/coreconf/mkdepend/imakemdep.h rename : security/coreconf/mkdepend/include.c => security/nss/coreconf/mkdepend/include.c rename : security/coreconf/mkdepend/main.c => security/nss/coreconf/mkdepend/main.c rename : security/coreconf/mkdepend/mkdepend.man => security/nss/coreconf/mkdepend/mkdepend.man rename : security/coreconf/mkdepend/parse.c => security/nss/coreconf/mkdepend/parse.c rename : security/coreconf/mkdepend/pr.c => security/nss/coreconf/mkdepend/pr.c rename : security/coreconf/module.mk => security/nss/coreconf/module.mk rename : security/coreconf/nsinstall/Makefile => security/nss/coreconf/nsinstall/Makefile rename : security/coreconf/nsinstall/nsinstall.c => security/nss/coreconf/nsinstall/nsinstall.c rename : security/coreconf/nsinstall/pathsub.c => security/nss/coreconf/nsinstall/pathsub.c rename : security/coreconf/nsinstall/pathsub.h => security/nss/coreconf/nsinstall/pathsub.h rename : security/coreconf/nsinstall/sunos4.h => security/nss/coreconf/nsinstall/sunos4.h rename : security/coreconf/outofdate.pl => security/nss/coreconf/outofdate.pl rename : security/coreconf/prefix.mk => security/nss/coreconf/prefix.mk rename : security/coreconf/release.pl => security/nss/coreconf/release.pl rename : security/coreconf/rules.mk => security/nss/coreconf/rules.mk rename : security/coreconf/ruleset.mk => security/nss/coreconf/ruleset.mk rename : security/coreconf/source.mk => security/nss/coreconf/source.mk rename : security/coreconf/suffix.mk => security/nss/coreconf/suffix.mk rename : security/coreconf/tree.mk => security/nss/coreconf/tree.mk rename : security/coreconf/version.mk => security/nss/coreconf/version.mk rename : security/coreconf/version.pl => security/nss/coreconf/version.pl rename : security/dbm/config/config.mk => security/nss/lib/dbm/config/config.mk rename : dbm/include/cdefs.h => security/nss/lib/dbm/include/cdefs.h rename : dbm/include/extern.h => security/nss/lib/dbm/include/extern.h rename : dbm/include/hash.h => security/nss/lib/dbm/include/hash.h rename : dbm/include/search.h => security/nss/lib/dbm/include/hsearch.h rename : dbm/include/mcom_db.h => security/nss/lib/dbm/include/mcom_db.h rename : dbm/include/mpool.h => security/nss/lib/dbm/include/mpool.h rename : dbm/include/ncompat.h => security/nss/lib/dbm/include/ncompat.h rename : dbm/include/page.h => security/nss/lib/dbm/include/page.h rename : dbm/include/queue.h => security/nss/lib/dbm/include/queue.h rename : dbm/include/search.h => security/nss/lib/dbm/include/search.h rename : dbm/include/winfile.h => security/nss/lib/dbm/include/winfile.h rename : dbm/src/db.c => security/nss/lib/dbm/src/db.c rename : security/dbm/src/dirent.c => security/nss/lib/dbm/src/dirent.c rename : security/dbm/src/dirent.h => security/nss/lib/dbm/src/dirent.h rename : dbm/src/h_bigkey.c => security/nss/lib/dbm/src/h_bigkey.c rename : dbm/src/h_func.c => security/nss/lib/dbm/src/h_func.c rename : dbm/src/h_log2.c => security/nss/lib/dbm/src/h_log2.c rename : dbm/src/h_page.c => security/nss/lib/dbm/src/h_page.c rename : dbm/src/hash.c => security/nss/lib/dbm/src/hash.c rename : dbm/src/hash_buf.c => security/nss/lib/dbm/src/hash_buf.c rename : dbm/src/memmove.c => security/nss/lib/dbm/src/memmove.c rename : dbm/src/mktemp.c => security/nss/lib/dbm/src/mktemp.c rename : dbm/src/snprintf.c => security/nss/lib/dbm/src/snprintf.c rename : dbm/src/strerror.c => security/nss/lib/dbm/src/strerror.c rename : dbm/tests/dbmtest.pkg => security/nss/lib/dbm/tests/dbmtest.pkg rename : dbm/tests/lots.c => security/nss/lib/dbm/tests/lots.c extra : rebase_source : 119dad5f824e8e760182047fd32e2a0d0f944172 extra : amend_source : 98e24aa51f9044d9091a26f013b643925e8f9dcf
601 lines
19 KiB
C
601 lines
19 KiB
C
/* 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);
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
else {
|
|
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;
|
|
}
|