import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,48 @@
#! gmake
#
# 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/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export

View file

@ -0,0 +1,35 @@
# 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/.
{
'includes': [
'../../../../coreconf/config.gypi'
],
'targets': [
{
'target_name': 'pkixchecker',
'type': 'static_library',
'sources': [
'pkix_basicconstraintschecker.c',
'pkix_certchainchecker.c',
'pkix_crlchecker.c',
'pkix_ekuchecker.c',
'pkix_expirationchecker.c',
'pkix_namechainingchecker.c',
'pkix_nameconstraintschecker.c',
'pkix_ocspchecker.c',
'pkix_policychecker.c',
'pkix_revocationchecker.c',
'pkix_revocationmethod.c',
'pkix_signaturechecker.c',
'pkix_targetcertchecker.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
]
}
],
'variables': {
'module': 'nss'
}
}

View file

@ -0,0 +1,15 @@
#
# 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/.
#
# Override TARGETS variable so that only static libraries
# are specifed as dependencies within rules.mk.
#
TARGETS = $(LIBRARY)
SHARED_LIBRARY =
IMPORT_LIBRARY =
PROGRAM =

View file

@ -0,0 +1,37 @@
# 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/.
{
'includes': [
'../../../../coreconf/config.gypi'
],
'targets': [
{
'target_name': 'lib_libpkix_pkix_checker_exports',
'type': 'none',
'copies': [
{
'files': [
'pkix_basicconstraintschecker.h',
'pkix_certchainchecker.h',
'pkix_crlchecker.h',
'pkix_ekuchecker.h',
'pkix_expirationchecker.h',
'pkix_namechainingchecker.h',
'pkix_nameconstraintschecker.h',
'pkix_ocspchecker.h',
'pkix_policychecker.h',
'pkix_revocationchecker.h',
'pkix_revocationmethod.h',
'pkix_signaturechecker.h',
'pkix_targetcertchecker.h'
],
'destination': '<(nss_private_dist_dir)/<(module)'
}
]
}
],
'variables': {
'module': 'nss'
}
}

View file

@ -0,0 +1,45 @@
#
# 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/.
CORE_DEPTH = ../../../..
EXPORTS = \
$(NULL)
PRIVATE_EXPORTS = \
pkix_basicconstraintschecker.h \
pkix_certchainchecker.h \
pkix_crlchecker.h \
pkix_ekuchecker.h \
pkix_expirationchecker.h \
pkix_namechainingchecker.h \
pkix_nameconstraintschecker.h \
pkix_ocspchecker.h \
pkix_policychecker.h \
pkix_revocationmethod.h \
pkix_revocationchecker.h \
pkix_signaturechecker.h \
pkix_targetcertchecker.h \
$(NULL)
MODULE = nss
CSRCS = \
pkix_basicconstraintschecker.c \
pkix_certchainchecker.c \
pkix_crlchecker.c \
pkix_ekuchecker.c \
pkix_expirationchecker.c \
pkix_namechainingchecker.c \
pkix_nameconstraintschecker.c \
pkix_ocspchecker.c \
pkix_revocationmethod.c \
pkix_revocationchecker.c \
pkix_policychecker.c \
pkix_signaturechecker.c \
pkix_targetcertchecker.c \
$(NULL)
LIBRARY_NAME = pkixchecker

View file

@ -0,0 +1,306 @@
/* 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/. */
/*
* pkix_basicconstraintschecker.c
*
* Functions for basic constraints validation
*
*/
#include "pkix_basicconstraintschecker.h"
/* --Private-BasicConstraintsCheckerState-Functions------------------------- */
/*
* FUNCTION: pkix_BasicConstraintsCheckerState_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_BasicConstraintsCheckerState_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
pkix_BasicConstraintsCheckerState *state = NULL;
PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
"pkix_BasicConstraintsCheckerState_Destroy");
PKIX_NULLCHECK_ONE(object);
/* Check that this object is a basic constraints checker state */
PKIX_CHECK(pkix_CheckType
(object, PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, plContext),
PKIX_OBJECTNOTBASICCONSTRAINTSCHECKERSTATE);
state = (pkix_BasicConstraintsCheckerState *)object;
PKIX_DECREF(state->basicConstraintsOID);
cleanup:
PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
}
/*
* FUNCTION: pkix_BasicConstraintsCheckerState_RegisterSelf
* DESCRIPTION:
* Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
"pkix_BasicConstraintsCheckerState_RegisterSelf");
entry.description = "BasicConstraintsCheckerState";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(pkix_BasicConstraintsCheckerState);
entry.destructor = pkix_BasicConstraintsCheckerState_Destroy;
entry.equalsFunction = NULL;
entry.hashcodeFunction = NULL;
entry.toStringFunction = NULL;
entry.comparator = NULL;
entry.duplicateFunction = NULL;
systemClasses[PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE] = entry;
PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
}
/*
* FUNCTION: pkix_BasicConstraintsCheckerState_Create
* DESCRIPTION:
*
* Creates a new BasicConstraintsCheckerState using the number of certs in
* the chain represented by "certsRemaining" and stores it at "pState".
*
* PARAMETERS:
* "certsRemaining"
* Number of certificates in the chain.
* "pState"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a BasicConstraintsCheckerState Error if the function fails in a
* non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
static PKIX_Error *
pkix_BasicConstraintsCheckerState_Create(
PKIX_UInt32 certsRemaining,
pkix_BasicConstraintsCheckerState **pState,
void *plContext)
{
pkix_BasicConstraintsCheckerState *state = NULL;
PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
"pkix_BasicConstraintsCheckerState_Create");
PKIX_NULLCHECK_ONE(pState);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE,
sizeof (pkix_BasicConstraintsCheckerState),
(PKIX_PL_Object **)&state,
plContext),
PKIX_COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT);
/* initialize fields */
state->certsRemaining = certsRemaining;
state->maxPathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_BASICCONSTRAINTS_OID,
&state->basicConstraintsOID,
plContext),
PKIX_OIDCREATEFAILED);
*pState = state;
state = NULL;
cleanup:
PKIX_DECREF(state);
PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
}
/* --Private-BasicConstraintsChecker-Functions------------------------------ */
/*
* FUNCTION: pkix_BasicConstraintsChecker_Check
* (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
*/
PKIX_Error *
pkix_BasicConstraintsChecker_Check(
PKIX_CertChainChecker *checker,
PKIX_PL_Cert *cert,
PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */
void **pNBIOContext,
void *plContext)
{
PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
pkix_BasicConstraintsCheckerState *state = NULL;
PKIX_Boolean caFlag = PKIX_FALSE;
PKIX_Int32 pathLength = 0;
PKIX_Int32 maxPathLength_now;
PKIX_Boolean isSelfIssued = PKIX_FALSE;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Check");
PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
*pNBIOContext = NULL; /* we never block on pending I/O */
PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
(checker, (PKIX_PL_Object **)&state, plContext),
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
state->certsRemaining--;
if (state->certsRemaining != 0) {
PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
(cert, &basicConstraints, plContext),
PKIX_CERTGETBASICCONSTRAINTSFAILED);
/* get CA Flag and path length */
if (basicConstraints != NULL) {
PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
(basicConstraints,
&caFlag,
plContext),
PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
if (caFlag == PKIX_TRUE) {
PKIX_CHECK
(PKIX_PL_BasicConstraints_GetPathLenConstraint
(basicConstraints,
&pathLength,
plContext),
PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED);
}
}else{
caFlag = PKIX_FALSE;
pathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
}
PKIX_CHECK(pkix_IsCertSelfIssued
(cert,
&isSelfIssued,
plContext),
PKIX_ISCERTSELFISSUEDFAILED);
maxPathLength_now = state->maxPathLength;
if (isSelfIssued != PKIX_TRUE) {
/* Not last CA Cert, but maxPathLength is down to zero */
if (maxPathLength_now == 0) {
PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDLN);
}
if (caFlag == PKIX_FALSE) {
PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDCA);
}
if (maxPathLength_now > 0) { /* can be unlimited (-1) */
maxPathLength_now--;
}
}
if (caFlag == PKIX_TRUE) {
if (maxPathLength_now == PKIX_UNLIMITED_PATH_CONSTRAINT){
maxPathLength_now = pathLength;
} else {
/* If pathLength is not specified, don't set */
if (pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) {
maxPathLength_now =
(maxPathLength_now > pathLength)?
pathLength:maxPathLength_now;
}
}
}
state->maxPathLength = maxPathLength_now;
}
/* Remove Basic Constraints Extension OID from list */
if (unresolvedCriticalExtensions != NULL) {
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticalExtensions,
(PKIX_PL_Object *) state->basicConstraintsOID,
plContext),
PKIX_LISTREMOVEFAILED);
}
PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
(checker, (PKIX_PL_Object *)state, plContext),
PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
cleanup:
PKIX_DECREF(state);
PKIX_DECREF(basicConstraints);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_BasicConstraintsChecker_Initialize
* DESCRIPTION:
* Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_BasicConstraintsChecker_Initialize(
PKIX_UInt32 certsRemaining,
PKIX_CertChainChecker **pChecker,
void *plContext)
{
pkix_BasicConstraintsCheckerState *state = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Initialize");
PKIX_NULLCHECK_ONE(pChecker);
PKIX_CHECK(pkix_BasicConstraintsCheckerState_Create
(certsRemaining, &state, plContext),
PKIX_BASICCONSTRAINTSCHECKERSTATECREATEFAILED);
PKIX_CHECK(PKIX_CertChainChecker_Create
(pkix_BasicConstraintsChecker_Check,
PKIX_FALSE,
PKIX_FALSE,
NULL,
(PKIX_PL_Object *)state,
pChecker,
plContext),
PKIX_CERTCHAINCHECKERCHECKFAILED);
cleanup:
PKIX_DECREF(state);
PKIX_RETURN(CERTCHAINCHECKER);
}

View file

@ -0,0 +1,42 @@
/* 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/. */
/*
* pkix_basicconstraintschecker.h
*
* Header file for basic constraints checker.
*
*/
#ifndef _PKIX_BASICCONSTRAINTSCHECKER_H
#define _PKIX_BASICCONSTRAINTSCHECKER_H
#include "pkix_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct pkix_BasicConstraintsCheckerStateStruct \
pkix_BasicConstraintsCheckerState;
struct pkix_BasicConstraintsCheckerStateStruct{
PKIX_PL_OID *basicConstraintsOID;
PKIX_Int32 certsRemaining;
PKIX_Int32 maxPathLength;
};
PKIX_Error *
pkix_BasicConstraintsChecker_Initialize(
PKIX_UInt32 numCerts,
PKIX_CertChainChecker **pChecker,
void *plContext);
PKIX_Error *
pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_BASICCONSTRAINTSCHECKER_H */

View file

@ -0,0 +1,322 @@
/* 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/. */
/*
* pkix_certchainchecker.c
*
* CertChainChecker Object Functions
*
*/
#include "pkix_certchainchecker.h"
/* --Private-Functions-------------------------------------------- */
/*
* FUNCTION: pkix_CertChainChecker_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_CertChainChecker_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
PKIX_CertChainChecker *checker = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_Destroy");
PKIX_NULLCHECK_ONE(object);
/* Check that this object is a cert chain checker */
PKIX_CHECK(pkix_CheckType
(object, PKIX_CERTCHAINCHECKER_TYPE, plContext),
PKIX_OBJECTNOTCERTCHAINCHECKER);
checker = (PKIX_CertChainChecker *)object;
PKIX_DECREF(checker->extensions);
PKIX_DECREF(checker->state);
cleanup:
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_CertChainChecker_Duplicate
* (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_CertChainChecker_Duplicate(
PKIX_PL_Object *object,
PKIX_PL_Object **pNewObject,
void *plContext)
{
PKIX_CertChainChecker *checker = NULL;
PKIX_CertChainChecker *checkerDuplicate = NULL;
PKIX_List *extensionsDuplicate = NULL;
PKIX_PL_Object *stateDuplicate = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_Duplicate");
PKIX_NULLCHECK_TWO(object, pNewObject);
PKIX_CHECK(pkix_CheckType
(object, PKIX_CERTCHAINCHECKER_TYPE, plContext),
PKIX_OBJECTNOTCERTCHAINCHECKER);
checker = (PKIX_CertChainChecker *)object;
if (checker->extensions){
PKIX_CHECK(PKIX_PL_Object_Duplicate
((PKIX_PL_Object *)checker->extensions,
(PKIX_PL_Object **)&extensionsDuplicate,
plContext),
PKIX_OBJECTDUPLICATEFAILED);
}
if (checker->state){
PKIX_CHECK(PKIX_PL_Object_Duplicate
((PKIX_PL_Object *)checker->state,
(PKIX_PL_Object **)&stateDuplicate,
plContext),
PKIX_OBJECTDUPLICATEFAILED);
}
PKIX_CHECK(PKIX_CertChainChecker_Create
(checker->checkCallback,
checker->forwardChecking,
checker->isForwardDirectionExpected,
extensionsDuplicate,
stateDuplicate,
&checkerDuplicate,
plContext),
PKIX_CERTCHAINCHECKERCREATEFAILED);
*pNewObject = (PKIX_PL_Object *)checkerDuplicate;
cleanup:
PKIX_DECREF(extensionsDuplicate);
PKIX_DECREF(stateDuplicate);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_CertChainChecker_RegisterSelf
* DESCRIPTION:
* Registers PKIX_CERTCHAINCHECKER_TYPE and its related functions with
* systemClasses[]
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_CertChainChecker_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_RegisterSelf");
entry.description = "CertChainChecker";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(PKIX_CertChainChecker);
entry.destructor = pkix_CertChainChecker_Destroy;
entry.equalsFunction = NULL;
entry.hashcodeFunction = NULL;
entry.toStringFunction = NULL;
entry.comparator = NULL;
entry.duplicateFunction = pkix_CertChainChecker_Duplicate;
systemClasses[PKIX_CERTCHAINCHECKER_TYPE] = entry;
PKIX_RETURN(CERTCHAINCHECKER);
}
/* --Public-Functions--------------------------------------------- */
/*
* FUNCTION: PKIX_CertChainChecker_Create (see comments in pkix_checker.h)
*/
PKIX_Error *
PKIX_CertChainChecker_Create(
PKIX_CertChainChecker_CheckCallback callback,
PKIX_Boolean forwardCheckingSupported,
PKIX_Boolean isForwardDirectionExpected,
PKIX_List *list, /* list of PKIX_PL_OID */
PKIX_PL_Object *initialState,
PKIX_CertChainChecker **pChecker,
void *plContext)
{
PKIX_CertChainChecker *checker = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CertChainChecker_Create");
PKIX_NULLCHECK_ONE(pChecker);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_CERTCHAINCHECKER_TYPE,
sizeof (PKIX_CertChainChecker),
(PKIX_PL_Object **)&checker,
plContext),
PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
/* initialize fields */
checker->checkCallback = callback;
checker->forwardChecking = forwardCheckingSupported;
checker->isForwardDirectionExpected = isForwardDirectionExpected;
PKIX_INCREF(list);
checker->extensions = list;
PKIX_INCREF(initialState);
checker->state = initialState;
*pChecker = checker;
checker = NULL;
cleanup:
PKIX_DECREF(checker);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: PKIX_CertChainChecker_GetCheckCallback
* (see comments in pkix_checker.h)
*/
PKIX_Error *
PKIX_CertChainChecker_GetCheckCallback(
PKIX_CertChainChecker *checker,
PKIX_CertChainChecker_CheckCallback *pCallback,
void *plContext)
{
PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CertChainChecker_GetCheckCallback");
PKIX_NULLCHECK_TWO(checker, pCallback);
*pCallback = checker->checkCallback;
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: PKIX_CertChainChecker_IsForwardCheckingSupported
* (see comments in pkix_checker.h)
*/
PKIX_Error *
PKIX_CertChainChecker_IsForwardCheckingSupported(
PKIX_CertChainChecker *checker,
PKIX_Boolean *pForwardCheckingSupported,
void *plContext)
{
PKIX_ENTER
(CERTCHAINCHECKER,
"PKIX_CertChainChecker_IsForwardCheckingSupported");
PKIX_NULLCHECK_TWO(checker, pForwardCheckingSupported);
*pForwardCheckingSupported = checker->forwardChecking;
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: PKIX_CertChainChecker_IsForwardDirectionExpected
* (see comments in pkix_checker.h)
*/
PKIX_Error *
PKIX_CertChainChecker_IsForwardDirectionExpected(
PKIX_CertChainChecker *checker,
PKIX_Boolean *pForwardDirectionExpected,
void *plContext)
{
PKIX_ENTER
(CERTCHAINCHECKER,
"PKIX_CertChainChecker_IsForwardDirectionExpected");
PKIX_NULLCHECK_TWO(checker, pForwardDirectionExpected);
*pForwardDirectionExpected = checker->isForwardDirectionExpected;
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: PKIX_CertChainChecker_GetCertChainCheckerState
* (see comments in pkix_checker.h)
*/
PKIX_Error *
PKIX_CertChainChecker_GetCertChainCheckerState(
PKIX_CertChainChecker *checker,
PKIX_PL_Object **pCertChainCheckerState,
void *plContext)
{
PKIX_ENTER(CERTCHAINCHECKER,
"PKIX_CertChainChecker_GetCertChainCheckerState");
PKIX_NULLCHECK_TWO(checker, pCertChainCheckerState);
PKIX_INCREF(checker->state);
*pCertChainCheckerState = checker->state;
cleanup:
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: PKIX_CertChainChecker_SetCertChainCheckerState
* (see comments in pkix_checker.h)
*/
PKIX_Error *
PKIX_CertChainChecker_SetCertChainCheckerState(
PKIX_CertChainChecker *checker,
PKIX_PL_Object *certChainCheckerState,
void *plContext)
{
PKIX_ENTER(CERTCHAINCHECKER,
"PKIX_CertChainChecker_SetCertChainCheckerState");
PKIX_NULLCHECK_ONE(checker);
/* DecRef old contents */
PKIX_DECREF(checker->state);
PKIX_INCREF(certChainCheckerState);
checker->state = certChainCheckerState;
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)checker, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
cleanup:
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: PKIX_CertChainChecker_GetSupportedExtensions
* (see comments in pkix_checker.h)
*/
PKIX_Error *
PKIX_CertChainChecker_GetSupportedExtensions(
PKIX_CertChainChecker *checker,
PKIX_List **pExtensions, /* list of PKIX_PL_OID */
void *plContext)
{
PKIX_ENTER(CERTCHAINCHECKER,
"PKIX_CertChainChecker_GetSupportedExtensions");
PKIX_NULLCHECK_TWO(checker, pExtensions);
PKIX_INCREF(checker->extensions);
*pExtensions = checker->extensions;
cleanup:
PKIX_RETURN(CERTCHAINCHECKER);
}

View file

@ -0,0 +1,36 @@
/* 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/. */
/*
* pkix_certchainchecker.h
*
* CertChainChecker Object Type Definition
*
*/
#ifndef _PKIX_CERTCHAINCHECKER_H
#define _PKIX_CERTCHAINCHECKER_H
#include "pkix_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
struct PKIX_CertChainCheckerStruct {
PKIX_CertChainChecker_CheckCallback checkCallback;
PKIX_List *extensions;
PKIX_PL_Object *state;
PKIX_Boolean forwardChecking;
PKIX_Boolean isForwardDirectionExpected;
};
/* see source file for function documentation */
PKIX_Error *pkix_CertChainChecker_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_CERTCHAINCHECKER_H */

View file

@ -0,0 +1,438 @@
/* 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/. */
/*
* pkix_defaultcrlchecker.c
*
* Functions for default CRL Checkers
*
*/
#include "pkix.h"
#include "pkix_crlchecker.h"
#include "pkix_tools.h"
/* --Private-CRLChecker-Data-and-Types------------------------------- */
typedef struct pkix_CrlCheckerStruct {
/* RevocationMethod is the super class of CrlChecker. */
pkix_RevocationMethod method;
PKIX_List *certStores; /* list of CertStore */
PKIX_PL_VerifyCallback crlVerifyFn;
} pkix_CrlChecker;
/* --Private-CRLChecker-Functions----------------------------------- */
/*
* FUNCTION: pkix_CrlCheckerstate_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_CrlChecker_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
pkix_CrlChecker *state = NULL;
PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Destroy");
PKIX_NULLCHECK_ONE(object);
/* Check that this object is a default CRL checker state */
PKIX_CHECK(
pkix_CheckType(object, PKIX_CRLCHECKER_TYPE, plContext),
PKIX_OBJECTNOTCRLCHECKER);
state = (pkix_CrlChecker *)object;
PKIX_DECREF(state->certStores);
cleanup:
PKIX_RETURN(CRLCHECKER);
}
/*
* FUNCTION: pkix_CrlChecker_RegisterSelf
*
* DESCRIPTION:
* Registers PKIX_CRLCHECKER_TYPE and its related functions
* with systemClasses[]
*
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_CrlChecker_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLCHECKER_TYPE];
PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_RegisterSelf");
entry->description = "CRLChecker";
entry->typeObjectSize = sizeof(pkix_CrlChecker);
entry->destructor = pkix_CrlChecker_Destroy;
PKIX_RETURN(CRLCHECKER);
}
/*
* FUNCTION: pkix_CrlChecker_Create
*
* DESCRIPTION:
* Allocate and initialize CRLChecker state data.
*
* PARAMETERS
* "certStores"
* Address of CertStore List to be stored in state. Must be non-NULL.
* "testDate"
* Address of PKIX_PL_Date to be checked. May be NULL.
* "trustedPubKey"
* Trusted Anchor Public Key for verifying first Cert in the chain.
* Must be non-NULL.
* "certsRemaining"
* Number of certificates remaining in the chain.
* "nistCRLPolicyEnabled"
* If enabled, enforce nist crl policy.
* "pChecker"
* Address of CRLChecker that is returned. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
*
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
*
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a DefaultCrlChecker Error if the function fails in a
* non-fatal way.
* Returns a Fatal Error
*/
PKIX_Error *
pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType,
PKIX_UInt32 flags,
PKIX_UInt32 priority,
pkix_LocalRevocationCheckFn localRevChecker,
pkix_ExternalRevocationCheckFn externalRevChecker,
PKIX_List *certStores,
PKIX_PL_VerifyCallback crlVerifyFn,
pkix_RevocationMethod **pChecker,
void *plContext)
{
pkix_CrlChecker *crlChecker = NULL;
PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Create");
PKIX_NULLCHECK_TWO(certStores, pChecker);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_CRLCHECKER_TYPE,
sizeof (pkix_CrlChecker),
(PKIX_PL_Object **)&crlChecker,
plContext),
PKIX_COULDNOTCREATECRLCHECKEROBJECT);
pkixErrorResult = pkix_RevocationMethod_Init(
(pkix_RevocationMethod*)crlChecker, methodType, flags, priority,
localRevChecker, externalRevChecker, plContext);
if (pkixErrorResult) {
goto cleanup;
}
/* Initialize fields */
PKIX_INCREF(certStores);
crlChecker->certStores = certStores;
crlChecker->crlVerifyFn = crlVerifyFn;
*pChecker = (pkix_RevocationMethod*)crlChecker;
crlChecker = NULL;
cleanup:
PKIX_DECREF(crlChecker);
PKIX_RETURN(CRLCHECKER);
}
/* --Private-CRLChecker-Functions------------------------------------ */
/*
* FUNCTION: pkix_CrlChecker_CheckLocal
*
* DESCRIPTION:
* Check if the Cert has been revoked based the CRLs data. This function
* maintains the checker state to be current.
*
* PARAMETERS
* "checker"
* Address of CertChainChecker which has the state data.
* Must be non-NULL.
* "cert"
* Address of Certificate that is to be validated. Must be non-NULL.
* "unreslvdCrtExts"
* A List OIDs. Not **yet** used in this checker function.
* "plContext"
* Platform-specific context pointer.
*
* THREAD SAFETY:
* Not Thread Safe
* (see Thread Safety Definitions in Programmer's Guide)
*
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a CertChainChecker Error if the function fails in a non-fatal way.
* Returns a Fatal Error
*/
PKIX_Error *
pkix_CrlChecker_CheckLocal(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_Boolean chainVerificationState,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *pReasonCode,
void *plContext)
{
PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn;
PKIX_CertStore *certStore = NULL;
pkix_CrlChecker *state = NULL;
PKIX_UInt32 crlStoreIndex = 0;
PKIX_UInt32 numCrlStores = 0;
PKIX_Boolean storeIsLocal = PKIX_FALSE;
PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckLocal");
PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, checkerObject);
state = (pkix_CrlChecker*)checkerObject;
PKIX_CHECK(
PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
PKIX_LISTGETLENGTHFAILED);
for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
PKIX_CHECK(
PKIX_List_GetItem(state->certStores, crlStoreIndex,
(PKIX_PL_Object **)&certStore,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(
PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
plContext),
PKIX_CERTSTOREGETLOCALFLAGFAILED);
if (storeIsLocal) {
PKIX_CHECK(
PKIX_CertStore_GetCrlCheckerFn(certStore,
&storeCheckRevocationFn,
plContext),
PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
if (storeCheckRevocationFn) {
PKIX_CHECK(
(*storeCheckRevocationFn)(certStore, cert, issuer,
/* delay sig check if building
* a chain by not specifying the time*/
chainVerificationState ? date : NULL,
/* crl downloading is not done. */
PKIX_FALSE,
pReasonCode, &revStatus, plContext),
PKIX_CERTSTORECRLCHECKFAILED);
if (revStatus == PKIX_RevStatus_Revoked) {
break;
}
}
}
PKIX_DECREF(certStore);
} /* while */
cleanup:
*pRevStatus = revStatus;
PKIX_DECREF(certStore);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_CrlChecker_CheckRemote
*
* DESCRIPTION:
* Check if the Cert has been revoked based the CRLs data. This function
* maintains the checker state to be current.
*
* PARAMETERS
* "checker"
* Address of CertChainChecker which has the state data.
* Must be non-NULL.
* "cert"
* Address of Certificate that is to be validated. Must be non-NULL.
* "unreslvdCrtExts"
* A List OIDs. Not **yet** used in this checker function.
* "plContext"
* Platform-specific context pointer.
*
* THREAD SAFETY:
* Not Thread Safe
* (see Thread Safety Definitions in Programmer's Guide)
*
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a CertChainChecker Error if the function fails in a non-fatal way.
* Returns a Fatal Error
*/
PKIX_Error *
pkix_CrlChecker_CheckExternal(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *pReasonCode,
void **pNBIOContext,
void *plContext)
{
PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL;
PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL;
PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
PKIX_CertStore *certStore = NULL;
PKIX_CertStore *localStore = NULL;
PKIX_CRLSelector *crlSelector = NULL;
PKIX_PL_X500Name *issuerName = NULL;
pkix_CrlChecker *state = NULL;
PKIX_UInt32 crlStoreIndex = 0;
PKIX_UInt32 numCrlStores = 0;
PKIX_Boolean storeIsLocal = PKIX_FALSE;
PKIX_List *crlList = NULL;
PKIX_List *dpList = NULL;
void *nbioContext = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal");
PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext);
nbioContext = *pNBIOContext;
*pNBIOContext = NULL; /* prepare for Error exit */
state = (pkix_CrlChecker*)checkerObject;
PKIX_CHECK(
PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
PKIX_LISTGETLENGTHFAILED);
/* Find a cert store that is capable of storing crls */
for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
PKIX_CHECK(
PKIX_List_GetItem(state->certStores, crlStoreIndex,
(PKIX_PL_Object **)&certStore,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(
PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
plContext),
PKIX_CERTSTOREGETLOCALFLAGFAILED);
if (storeIsLocal) {
PKIX_CHECK(
PKIX_CertStore_GetImportCrlCallback(certStore,
&storeImportCrlFn,
plContext),
PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
PKIX_CHECK(
PKIX_CertStore_GetCrlCheckerFn(certStore,
&storeCheckRevocationFn,
plContext),
PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
if (storeImportCrlFn && storeCheckRevocationFn) {
localStore = certStore;
certStore = NULL;
break;
}
}
PKIX_DECREF(certStore);
} /* while */
/* Report unknown status if we can not check crl in one of the
* local stores. */
if (!localStore) {
PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND);
}
PKIX_CHECK(
PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext),
PKIX_CERTCHECKKEYUSAGEFAILED);
PKIX_CHECK(
PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext),
PKIX_CERTGETCRLDPFAILED);
if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
(!dpList || !dpList->length)) {
goto cleanup;
}
PKIX_CHECK(
PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext),
PKIX_CERTGETISSUERFAILED);
PKIX_CHECK(
PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext),
PKIX_CRLCHECKERSETSELECTORFAILED);
/* Fetch crl and store in a local cert store */
for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) {
PKIX_CertStore_CRLCallback getCrlsFn;
PKIX_CHECK(
PKIX_List_GetItem(state->certStores, crlStoreIndex,
(PKIX_PL_Object **)&certStore,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(
PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn,
plContext),
PKIX_CERTSTOREGETCRLCALLBACKFAILED);
PKIX_CHECK(
(*getCrlsFn)(certStore, crlSelector, &nbioContext,
&crlList, plContext),
PKIX_GETCRLSFAILED);
PKIX_CHECK(
(*storeImportCrlFn)(localStore, issuerName, crlList, plContext),
PKIX_CERTSTOREFAILTOIMPORTCRLLIST);
PKIX_CHECK(
(*storeCheckRevocationFn)(certStore, cert, issuer, date,
/* done with crl downloading */
PKIX_TRUE,
pReasonCode, &revStatus, plContext),
PKIX_CERTSTORECRLCHECKFAILED);
if (revStatus != PKIX_RevStatus_NoInfo) {
break;
}
PKIX_DECREF(crlList);
PKIX_DECREF(certStore);
} /* while */
cleanup:
/* Update return flags */
if (revStatus == PKIX_RevStatus_NoInfo &&
((dpList && dpList->length > 0) ||
(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) &&
methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
revStatus = PKIX_RevStatus_Revoked;
}
*pRevStatus = revStatus;
PKIX_DECREF(dpList);
PKIX_DECREF(crlList);
PKIX_DECREF(certStore);
PKIX_DECREF(issuerName);
PKIX_DECREF(localStore);
PKIX_DECREF(crlSelector);
PKIX_RETURN(CERTCHAINCHECKER);
}

View file

@ -0,0 +1,68 @@
/* 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/. */
/*
* pkix_defaultcrlchecker.h
*
* Header file for default CRL function
*
*/
#ifndef _PKIX_CRLCHECKER_H
#define _PKIX_CRLCHECKER_H
#include "pkixt.h"
#include "pkix_revocationmethod.h"
#include "pkix_crlsel.h"
#ifdef __cplusplus
extern "C" {
#endif
/* NOTE: nbio logic removed. Will be replaced later. */
PKIX_Error *
pkix_CrlChecker_CheckLocal(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_Boolean chainVerificationState,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *reasonCode,
void *plContext);
PKIX_Error *
pkix_CrlChecker_CheckExternal(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *reasonCode,
void **pNBIOContext,
void *plContext);
PKIX_Error *
pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType,
PKIX_UInt32 flags,
PKIX_UInt32 priority,
pkix_LocalRevocationCheckFn localRevChecker,
pkix_ExternalRevocationCheckFn externalRevChecker,
PKIX_List *certStores,
PKIX_PL_VerifyCallback crlVerifyFn,
pkix_RevocationMethod **pChecker,
void *plContext);
PKIX_Error *
pkix_CrlChecker_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_CRLCHECKER_H */

View file

@ -0,0 +1,328 @@
/* 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/. */
/*
* pkix_ekuchecker.c
*
* User Defined ExtenedKeyUsage Function Definitions
*
*/
#include "pkix_ekuchecker.h"
SECOidTag ekuOidStrings[] = {
PKIX_KEY_USAGE_SERVER_AUTH_OID,
PKIX_KEY_USAGE_CLIENT_AUTH_OID,
PKIX_KEY_USAGE_CODE_SIGN_OID,
PKIX_KEY_USAGE_EMAIL_PROTECT_OID,
PKIX_KEY_USAGE_TIME_STAMP_OID,
PKIX_KEY_USAGE_OCSP_RESPONDER_OID,
PKIX_UNKNOWN_OID
};
typedef struct pkix_EkuCheckerStruct {
PKIX_List *requiredExtKeyUsageOids;
PKIX_PL_OID *ekuOID;
} pkix_EkuChecker;
/*
* FUNCTION: pkix_EkuChecker_Destroy
* (see comments for PKIX_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_EkuChecker_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
pkix_EkuChecker *ekuCheckerState = NULL;
PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Destroy");
PKIX_NULLCHECK_ONE(object);
PKIX_CHECK(pkix_CheckType(object, PKIX_EKUCHECKER_TYPE, plContext),
PKIX_OBJECTNOTANEKUCHECKERSTATE);
ekuCheckerState = (pkix_EkuChecker *)object;
PKIX_DECREF(ekuCheckerState->ekuOID);
PKIX_DECREF(ekuCheckerState->requiredExtKeyUsageOids);
cleanup:
PKIX_RETURN(EKUCHECKER);
}
/*
* FUNCTION: pkix_EkuChecker_RegisterSelf
*
* DESCRIPTION:
* Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related
* functions with systemClasses[]
*
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_EkuChecker_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry *entry = &systemClasses[PKIX_EKUCHECKER_TYPE];
PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_RegisterSelf");
entry->description = "EkuChecker";
entry->typeObjectSize = sizeof(pkix_EkuChecker);
entry->destructor = pkix_EkuChecker_Destroy;
PKIX_RETURN(EKUCHECKER);
}
/*
* FUNCTION: pkix_EkuChecker_Create
* DESCRIPTION:
*
* Creates a new Extend Key Usage CheckerState using "params" to retrieve
* application specified EKU for verification and stores it at "pState".
*
* PARAMETERS:
* "params"
* a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of
* Extended Key Usage OIDs specified by application can be retrieved for
* verification.
* "pState"
* Address where state pointer will be stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a UserDefinedModules Error if the function fails in a
* non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
static PKIX_Error *
pkix_EkuChecker_Create(
PKIX_ProcessingParams *params,
pkix_EkuChecker **pState,
void *plContext)
{
pkix_EkuChecker *state = NULL;
PKIX_CertSelector *certSelector = NULL;
PKIX_ComCertSelParams *comCertSelParams = NULL;
PKIX_List *requiredOids = NULL;
PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Create");
PKIX_NULLCHECK_TWO(params, pState);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_EKUCHECKER_TYPE,
sizeof (pkix_EkuChecker),
(PKIX_PL_Object **)&state,
plContext),
PKIX_COULDNOTCREATEEKUCHECKERSTATEOBJECT);
PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
(params, &certSelector, plContext),
PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
if (certSelector != NULL) {
/* Get initial EKU OIDs from ComCertSelParams, if set */
PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
(certSelector, &comCertSelParams, plContext),
PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
if (comCertSelParams != NULL) {
PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
(comCertSelParams, &requiredOids, plContext),
PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
}
}
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_EXTENDEDKEYUSAGE_OID,
&state->ekuOID,
plContext),
PKIX_OIDCREATEFAILED);
state->requiredExtKeyUsageOids = requiredOids;
requiredOids = NULL;
*pState = state;
state = NULL;
cleanup:
PKIX_DECREF(certSelector);
PKIX_DECREF(comCertSelParams);
PKIX_DECREF(requiredOids);
PKIX_DECREF(state);
PKIX_RETURN(EKUCHECKER);
}
/*
* FUNCTION: pkix_EkuChecker_Check
* DESCRIPTION:
*
* This function determines the Extended Key Usage OIDs specified by the
* application is included in the Extended Key Usage OIDs of this "cert".
*
* PARAMETERS:
* "checker"
* Address of CertChainChecker which has the state data.
* Must be non-NULL.
* "cert"
* Address of Certificate that is to be validated. Must be non-NULL.
* "unresolvedCriticalExtensions"
* A List OIDs. The OID for Extended Key Usage is removed.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a UserDefinedModules Error if the function fails in
* a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
static PKIX_Error *
pkix_EkuChecker_Check(
PKIX_CertChainChecker *checker,
PKIX_PL_Cert *cert,
PKIX_List *unresolvedCriticalExtensions,
void **pNBIOContext,
void *plContext)
{
pkix_EkuChecker *state = NULL;
PKIX_List *requiredExtKeyUsageList = NULL;
PKIX_List *certExtKeyUsageList = NULL;
PKIX_PL_OID *ekuOid = NULL;
PKIX_Boolean isContained = PKIX_FALSE;
PKIX_UInt32 numItems = 0;
PKIX_UInt32 i;
PKIX_Boolean checkResult = PKIX_TRUE;
PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check");
PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
*pNBIOContext = NULL; /* no non-blocking IO */
PKIX_CHECK(
PKIX_CertChainChecker_GetCertChainCheckerState
(checker, (PKIX_PL_Object **)&state, plContext),
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
requiredExtKeyUsageList = state->requiredExtKeyUsageOids;
if (requiredExtKeyUsageList == NULL) {
goto cleanup;
}
PKIX_CHECK(
PKIX_List_GetLength(requiredExtKeyUsageList, &numItems,
plContext),
PKIX_LISTGETLENGTHFAILED);
if (numItems == 0) {
goto cleanup;
}
PKIX_CHECK(
PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList,
plContext),
PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
if (certExtKeyUsageList == NULL) {
goto cleanup;
}
for (i = 0; i < numItems; i++) {
PKIX_CHECK(
PKIX_List_GetItem(requiredExtKeyUsageList, i,
(PKIX_PL_Object **)&ekuOid, plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(
pkix_List_Contains(certExtKeyUsageList,
(PKIX_PL_Object *)ekuOid,
&isContained,
plContext),
PKIX_LISTCONTAINSFAILED);
PKIX_DECREF(ekuOid);
if (isContained != PKIX_TRUE) {
checkResult = PKIX_FALSE;
goto cleanup;
}
}
cleanup:
if (!pkixErrorResult && checkResult == PKIX_FALSE) {
pkixErrorReceived = PKIX_TRUE;
pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED;
}
PKIX_DECREF(ekuOid);
PKIX_DECREF(certExtKeyUsageList);
PKIX_DECREF(state);
PKIX_RETURN(EKUCHECKER);
}
/*
* FUNCTION: pkix_EkuChecker_Initialize
* (see comments in pkix_sample_modules.h)
*/
PKIX_Error *
PKIX_EkuChecker_Create(
PKIX_ProcessingParams *params,
PKIX_CertChainChecker **pEkuChecker,
void *plContext)
{
pkix_EkuChecker *state = NULL;
PKIX_List *critExtOIDsList = NULL;
PKIX_ENTER(EKUCHECKER, "PKIX_EkuChecker_Initialize");
PKIX_NULLCHECK_ONE(params);
/*
* This function and functions in this file provide an example of how
* an application defined checker can be hooked into libpkix.
*/
PKIX_CHECK(pkix_EkuChecker_Create
(params, &state, plContext),
PKIX_EKUCHECKERSTATECREATEFAILED);
PKIX_CHECK(PKIX_List_Create(&critExtOIDsList, plContext),
PKIX_LISTCREATEFAILED);
PKIX_CHECK(PKIX_List_AppendItem
(critExtOIDsList,
(PKIX_PL_Object *)state->ekuOID,
plContext),
PKIX_LISTAPPENDITEMFAILED);
PKIX_CHECK(PKIX_CertChainChecker_Create
(pkix_EkuChecker_Check,
PKIX_TRUE, /* forwardCheckingSupported */
PKIX_FALSE, /* forwardDirectionExpected */
critExtOIDsList,
(PKIX_PL_Object *) state,
pEkuChecker,
plContext),
PKIX_CERTCHAINCHECKERCREATEFAILED);
cleanup:
PKIX_DECREF(critExtOIDsList);
PKIX_DECREF(state);
PKIX_RETURN(EKUCHECKER);
}

View file

@ -0,0 +1,92 @@
/* 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/. */
/*
* pkix_ekuchecker.h
*
* User Defined Object Type Extended Key Usage Definition
*
*/
#ifndef _PKIX_EKUCHECKER_H
#define _PKIX_EKUCHECKER_H
#include "pkix_pl_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* FUNCTION: PKIX_PL_EkuChecker_Create
*
* DESCRIPTION:
* Create a CertChainChecker with EkuCheckerState and add it into
* PKIX_ProcessingParams object.
*
* PARAMETERS
* "params"
* a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of
* Extended Key Usage OIDs specified by application can be retrieved for
* verification.
* "ekuChecker"
* Address of created ekuchecker.
* "plContext"
* Platform-specific context pointer.
*
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
*
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a UserDefinedModules Error if the function fails in a non-fatal
* way.
* Returns a Fatal Error
*/
PKIX_Error *
PKIX_EkuChecker_Create(
PKIX_ProcessingParams *params,
PKIX_CertChainChecker **ekuChecker,
void *plContext);
/*
* FUNCTION: PKIX_PL_EkuChecker_GetRequiredEku
*
* DESCRIPTION:
* This function retrieves application specified ExtenedKeyUsage(s) from
* ComCertSetparams and converts its OID representations to SECCertUsageEnum.
* The result is stored and returned in bit mask at "pRequiredExtKeyUsage".
*
* PARAMETERS
* "certSelector"
* a PKIX_CertSelector links to PKIX_ComCertSelParams where a list of
* Extended Key Usage OIDs specified by application can be retrieved for
* verification. Must be non-NULL.
* "pRequiredExtKeyUsage"
* Address where the result is returned. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
*
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
*
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a UserDefinedModules Error if the function fails in a non-fatal
* way.
* Returns a Fatal Error
*/
PKIX_Error *
pkix_EkuChecker_GetRequiredEku(
PKIX_CertSelector *certSelector,
PKIX_UInt32 *pRequiredExtKeyUsage,
void *plContext);
/* see source file for function documentation */
PKIX_Error *pkix_EkuChecker_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_PL_EKUCHECKER_H */

View file

@ -0,0 +1,113 @@
/* 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/. */
/*
* pkix_expirationchecker.c
*
* Functions for expiration validation
*
*/
#include "pkix_expirationchecker.h"
/* --Private-Functions-------------------------------------------- */
/*
* FUNCTION: pkix_ExpirationChecker_Check
* (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
*/
PKIX_Error *
pkix_ExpirationChecker_Check(
PKIX_CertChainChecker *checker,
PKIX_PL_Cert *cert,
PKIX_List *unresolvedCriticalExtensions,
void **pNBIOContext,
void *plContext)
{
PKIX_PL_Date *testDate = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_ExpirationChecker_Check");
PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
*pNBIOContext = NULL; /* we never block on pending I/O */
PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
(checker, (PKIX_PL_Object **)&testDate, plContext),
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
PKIX_CHECK(PKIX_PL_Cert_CheckValidity(cert, testDate, plContext),
PKIX_CERTCHECKVALIDITYFAILED);
cleanup:
PKIX_DECREF(testDate);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_ExpirationChecker_Initialize
* DESCRIPTION:
*
* Creates a new CertChainChecker and stores it at "pChecker", where it will
* used by pkix_ExpirationChecker_Check to check that the certificate has not
* expired with respect to the Date pointed to by "testDate." If "testDate"
* is NULL, then the CertChainChecker will check that a certificate has not
* expired with respect to the current date and time.
*
* PARAMETERS:
* "testDate"
* Address of Date representing the point in time at which the cert is to
* be validated. If "testDate" is NULL, the current date and time is used.
* "pChecker"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a CertChainChecker Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
PKIX_Error *
pkix_ExpirationChecker_Initialize(
PKIX_PL_Date *testDate,
PKIX_CertChainChecker **pChecker,
void *plContext)
{
PKIX_PL_Date *myDate = NULL;
PKIX_PL_Date *nowDate = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_ExpirationChecker_Initialize");
PKIX_NULLCHECK_ONE(pChecker);
/* if testDate is NULL, we use the current time */
if (!testDate){
PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
(NULL, &nowDate, plContext),
PKIX_DATECREATEUTCTIMEFAILED);
myDate = nowDate;
} else {
myDate = testDate;
}
PKIX_CHECK(PKIX_CertChainChecker_Create
(pkix_ExpirationChecker_Check,
PKIX_TRUE,
PKIX_FALSE,
NULL,
(PKIX_PL_Object *)myDate,
pChecker,
plContext),
PKIX_CERTCHAINCHECKERCREATEFAILED);
cleanup:
PKIX_DECREF(nowDate);
PKIX_RETURN(CERTCHAINCHECKER);
}

View file

@ -0,0 +1,30 @@
/* 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/. */
/*
* pkix_expirationchecker.h
*
* Header file for validate expiration function
*
*/
#ifndef _PKIX_EXPIRATIONCHECKER_H
#define _PKIX_EXPIRATIONCHECKER_H
#include "pkix_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
PKIX_Error *
pkix_ExpirationChecker_Initialize(
PKIX_PL_Date *testDate,
PKIX_CertChainChecker **pChecker,
void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_EXPIRATIONCHECKER_H */

View file

@ -0,0 +1,121 @@
/* 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/. */
/*
* pkix_namechainingchecker.c
*
* Functions for name chaining validation
*
*/
#include "pkix_namechainingchecker.h"
/* --Private-Functions-------------------------------------------- */
/*
* FUNCTION: pkix_NameChainingChecker_Check
* (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
*/
PKIX_Error *
pkix_NameChainingChecker_Check(
PKIX_CertChainChecker *checker,
PKIX_PL_Cert *cert,
PKIX_List *unresolvedCriticalExtensions,
void **pNBIOContext,
void *plContext)
{
PKIX_PL_X500Name *prevSubject = NULL;
PKIX_PL_X500Name *currIssuer = NULL;
PKIX_PL_X500Name *currSubject = NULL;
PKIX_Boolean result;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameChainingChecker_Check");
PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
*pNBIOContext = NULL; /* we never block on pending I/O */
PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
(checker, (PKIX_PL_Object **)&prevSubject, plContext),
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &currIssuer, plContext),
PKIX_CERTGETISSUERFAILED);
if (prevSubject){
PKIX_CHECK(PKIX_PL_X500Name_Match
(prevSubject, currIssuer, &result, plContext),
PKIX_X500NAMEMATCHFAILED);
if (!result){
PKIX_ERROR(PKIX_NAMECHAININGCHECKFAILED);
}
} else {
PKIX_ERROR(PKIX_NAMECHAININGCHECKFAILED);
}
PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &currSubject, plContext),
PKIX_CERTGETSUBJECTFAILED);
PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
(checker, (PKIX_PL_Object *)currSubject, plContext),
PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
cleanup:
PKIX_DECREF(prevSubject);
PKIX_DECREF(currIssuer);
PKIX_DECREF(currSubject);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_NameChainingChecker_Initialize
* DESCRIPTION:
*
* Creates a new CertChainChecker and stores it at "pChecker", where it will
* be used by pkix_NameChainingChecker_Check to check that the issuer name
* of the certificate matches the subject name in the checker's state. The
* X500Name pointed to by "trustedCAName" is used to initialize the checker's
* state.
*
* PARAMETERS:
* "trustedCAName"
* Address of X500Name representing the trusted CA Name used to
* initialize the state of this checker. Must be non-NULL.
* "pChecker"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a CertChainChecker Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
PKIX_Error *
pkix_NameChainingChecker_Initialize(
PKIX_PL_X500Name *trustedCAName,
PKIX_CertChainChecker **pChecker,
void *plContext)
{
PKIX_ENTER(CERTCHAINCHECKER, "PKIX_NameChainingChecker_Initialize");
PKIX_NULLCHECK_TWO(pChecker, trustedCAName);
PKIX_CHECK(PKIX_CertChainChecker_Create
(pkix_NameChainingChecker_Check,
PKIX_FALSE,
PKIX_FALSE,
NULL,
(PKIX_PL_Object *)trustedCAName,
pChecker,
plContext),
PKIX_CERTCHAINCHECKERCREATEFAILED);
cleanup:
PKIX_RETURN(CERTCHAINCHECKER);
}

View file

@ -0,0 +1,30 @@
/* 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/. */
/*
* pkix_namechainingchecker.h
*
* Header file for name chaining checker.
*
*/
#ifndef _PKIX_NAMECHAININGCHECKER_H
#define _PKIX_NAMECHAININGCHECKER_H
#include "pkix_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
PKIX_Error *
pkix_NameChainingChecker_Initialize(
PKIX_PL_X500Name *trustedCAName,
PKIX_CertChainChecker **pChecker,
void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_NAMECHAININGCHECKER_H */

View file

@ -0,0 +1,308 @@
/* 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/. */
/*
* pkix_nameconstraintschecker.c
*
* Functions for Name Constraints Checkers
*
*/
#include "pkix_nameconstraintschecker.h"
/* --Private-NameConstraintsCheckerState-Functions---------------------- */
/*
* FUNCTION: pkix_NameConstraintsCheckerstate_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_NameConstraintsCheckerState_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
pkix_NameConstraintsCheckerState *state = NULL;
PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
"pkix_NameConstraintsCheckerState_Destroy");
PKIX_NULLCHECK_ONE(object);
/* Check that object type */
PKIX_CHECK(pkix_CheckType
(object, PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE, plContext),
PKIX_OBJECTNOTNAMECONSTRAINTSCHECKERSTATE);
state = (pkix_NameConstraintsCheckerState *)object;
PKIX_DECREF(state->nameConstraints);
PKIX_DECREF(state->nameConstraintsOID);
cleanup:
PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
}
/*
* FUNCTION: pkix_NameConstraintsCheckerState_RegisterSelf
*
* DESCRIPTION:
* Registers PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE and its related
* functions with systemClasses[]
*
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_NameConstraintsCheckerState_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
"pkix_NameConstraintsCheckerState_RegisterSelf");
entry.description = "NameConstraintsCheckerState";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(pkix_NameConstraintsCheckerState);
entry.destructor = pkix_NameConstraintsCheckerState_Destroy;
entry.equalsFunction = NULL;
entry.hashcodeFunction = NULL;
entry.toStringFunction = NULL;
entry.comparator = NULL;
entry.duplicateFunction = NULL;
systemClasses[PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE] = entry;
PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
}
/*
* FUNCTION: pkix_NameConstraintsCheckerState_Create
*
* DESCRIPTION:
* Allocate and initialize NameConstraintsChecker state data.
*
* PARAMETERS
* "nameConstraints"
* Address of NameConstraints to be stored in state. May be NULL.
* "numCerts"
* Number of certificates in the validation chain. This data is used
* to identify end-entity.
* "pCheckerState"
* Address of NameConstraintsCheckerState that is returned. Must be
* non-NULL.
* "plContext" - Platform-specific context pointer.
*
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
*
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a CERTNAMECONSTRAINTSCHECKERSTATE Error if the function fails in
* a non-fatal way.
* Returns a Fatal Error
*/
static PKIX_Error *
pkix_NameConstraintsCheckerState_Create(
PKIX_PL_CertNameConstraints *nameConstraints,
PKIX_UInt32 numCerts,
pkix_NameConstraintsCheckerState **pCheckerState,
void *plContext)
{
pkix_NameConstraintsCheckerState *state = NULL;
PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
"pkix_NameConstraintsCheckerState_Create");
PKIX_NULLCHECK_ONE(pCheckerState);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE,
sizeof (pkix_NameConstraintsCheckerState),
(PKIX_PL_Object **)&state,
plContext),
PKIX_COULDNOTCREATENAMECONSTRAINTSCHECKERSTATEOBJECT);
/* Initialize fields */
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_NAMECONSTRAINTS_OID,
&state->nameConstraintsOID,
plContext),
PKIX_OIDCREATEFAILED);
PKIX_INCREF(nameConstraints);
state->nameConstraints = nameConstraints;
state->certsRemaining = numCerts;
*pCheckerState = state;
state = NULL;
cleanup:
PKIX_DECREF(state);
PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
}
/* --Private-NameConstraintsChecker-Functions------------------------- */
/*
* FUNCTION: pkix_NameConstraintsChecker_Check
* (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
*/
static PKIX_Error *
pkix_NameConstraintsChecker_Check(
PKIX_CertChainChecker *checker,
PKIX_PL_Cert *cert,
PKIX_List *unresolvedCriticalExtensions,
void **pNBIOContext,
void *plContext)
{
pkix_NameConstraintsCheckerState *state = NULL;
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
PKIX_PL_CertNameConstraints *mergedNameConstraints = NULL;
PKIX_Boolean selfIssued = PKIX_FALSE;
PKIX_Boolean lastCert = PKIX_FALSE;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Check");
PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
*pNBIOContext = NULL; /* we never block on pending I/O */
PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
(checker, (PKIX_PL_Object **)&state, plContext),
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
state->certsRemaining--;
lastCert = state->certsRemaining == 0;
/* Get status of self issued */
PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
PKIX_ISCERTSELFISSUEDFAILED);
/* Check on non self-issued and if so only for last cert */
if (selfIssued == PKIX_FALSE ||
(selfIssued == PKIX_TRUE && lastCert)) {
PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints
(cert, state->nameConstraints, lastCert,
plContext),
PKIX_CERTCHECKNAMECONSTRAINTSFAILED);
}
if (!lastCert) {
PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
(cert, &nameConstraints, plContext),
PKIX_CERTGETNAMECONSTRAINTSFAILED);
/* Merge with previous name constraints kept in state */
if (nameConstraints != NULL) {
if (state->nameConstraints == NULL) {
state->nameConstraints = nameConstraints;
} else {
PKIX_CHECK(PKIX_PL_Cert_MergeNameConstraints
(nameConstraints,
state->nameConstraints,
&mergedNameConstraints,
plContext),
PKIX_CERTMERGENAMECONSTRAINTSFAILED);
PKIX_DECREF(nameConstraints);
PKIX_DECREF(state->nameConstraints);
state->nameConstraints = mergedNameConstraints;
}
/* Remove Name Constraints Extension OID from list */
if (unresolvedCriticalExtensions != NULL) {
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticalExtensions,
(PKIX_PL_Object *)state->nameConstraintsOID,
plContext),
PKIX_LISTREMOVEFAILED);
}
}
}
PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
(checker, (PKIX_PL_Object *)state, plContext),
PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
cleanup:
PKIX_DECREF(state);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_NameConstraintsChecker_Initialize
*
* DESCRIPTION:
* Create a CertChainChecker with a NameConstraintsCheckerState. The
* NameConstraintsCheckerState is created with "trustedNC" and "numCerts"
* as its initial state. The CertChainChecker for the NameConstraints is
* returned at address of "pChecker".
*
* PARAMETERS
* "trustedNC"
* The NameConstraints from trusted anchor Cert is stored at "trustedNC"
* for initialization. May be NULL.
* "numCerts"
* Number of certificates in the validation chain. This data is used
* to identify end-entity.
* "pChecker"
* Address of CertChainChecker to bo created and returned.
* Must be non-NULL.
* "plContext" - Platform-specific context pointer.
*
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
*
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a CERTCHAINCHECKER Error if the function fails in a non-fatal way.
* Returns a Fatal Error
*/
PKIX_Error *
pkix_NameConstraintsChecker_Initialize(
PKIX_PL_CertNameConstraints *trustedNC,
PKIX_UInt32 numCerts,
PKIX_CertChainChecker **pChecker,
void *plContext)
{
pkix_NameConstraintsCheckerState *state = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Initialize");
PKIX_NULLCHECK_ONE(pChecker);
PKIX_CHECK(pkix_NameConstraintsCheckerState_Create
(trustedNC, numCerts, &state, plContext),
PKIX_NAMECONSTRAINTSCHECKERSTATECREATEFAILED);
PKIX_CHECK(PKIX_CertChainChecker_Create
(pkix_NameConstraintsChecker_Check,
PKIX_FALSE,
PKIX_FALSE,
NULL,
(PKIX_PL_Object *) state,
pChecker,
plContext),
PKIX_CERTCHAINCHECKERCREATEFAILED);
cleanup:
PKIX_DECREF(state);
PKIX_RETURN(CERTCHAINCHECKER);
}

View file

@ -0,0 +1,43 @@
/* 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/. */
/*
* pkix_nameconstraintschecker.h
*
* Header file for validate Name Constraints Checker function
*
*/
#ifndef _PKIX_NAMECONSTRAINTSCHECKER_H
#define _PKIX_NAMECONSTRAINTSCHECKER_H
#include "pkix_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct pkix_NameConstraintsCheckerState \
pkix_NameConstraintsCheckerState;
struct pkix_NameConstraintsCheckerState {
PKIX_PL_CertNameConstraints *nameConstraints;
PKIX_PL_OID *nameConstraintsOID;
PKIX_UInt32 certsRemaining;
};
PKIX_Error *
pkix_NameConstraintsChecker_Initialize(
PKIX_PL_CertNameConstraints *trustedNC,
PKIX_UInt32 numCerts,
PKIX_CertChainChecker **pChecker,
void *plContext);
PKIX_Error *
pkix_NameConstraintsCheckerState_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_NAMECONSTRAINTSCHECKER_H */

View file

@ -0,0 +1,419 @@
/* 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/. */
/*
* pkix_ocspchecker.c
*
* OcspChecker Object Functions
*
*/
#include "pkix_ocspchecker.h"
#include "pkix_pl_ocspcertid.h"
#include "pkix_error.h"
/* --Private-Data-and-Types--------------------------------------- */
typedef struct pkix_OcspCheckerStruct {
/* RevocationMethod is the super class of OcspChecker. */
pkix_RevocationMethod method;
PKIX_PL_VerifyCallback certVerifyFcn;
} pkix_OcspChecker;
/* --Private-Functions-------------------------------------------- */
/*
* FUNCTION: pkix_OcspChecker_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_OcspChecker_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
return NULL;
}
/*
* FUNCTION: pkix_OcspChecker_RegisterSelf
* DESCRIPTION:
* Registers PKIX_OCSPCHECKER_TYPE and its related functions with
* systemClasses[]
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_OcspChecker_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry* entry = &systemClasses[PKIX_OCSPCHECKER_TYPE];
PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_RegisterSelf");
entry->description = "OcspChecker";
entry->typeObjectSize = sizeof(pkix_OcspChecker);
entry->destructor = pkix_OcspChecker_Destroy;
PKIX_RETURN(OCSPCHECKER);
}
/*
* FUNCTION: pkix_OcspChecker_Create
*/
PKIX_Error *
pkix_OcspChecker_Create(PKIX_RevocationMethodType methodType,
PKIX_UInt32 flags,
PKIX_UInt32 priority,
pkix_LocalRevocationCheckFn localRevChecker,
pkix_ExternalRevocationCheckFn externalRevChecker,
PKIX_PL_VerifyCallback verifyFn,
pkix_RevocationMethod **pChecker,
void *plContext)
{
pkix_OcspChecker *method = NULL;
PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_Create");
PKIX_NULLCHECK_ONE(pChecker);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_OCSPCHECKER_TYPE,
sizeof (pkix_OcspChecker),
(PKIX_PL_Object **)&method,
plContext),
PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
pkixErrorResult = pkix_RevocationMethod_Init(
(pkix_RevocationMethod*)method, methodType, flags, priority,
localRevChecker, externalRevChecker, plContext);
if (pkixErrorResult) {
goto cleanup;
}
method->certVerifyFcn = (PKIX_PL_VerifyCallback)verifyFn;
*pChecker = (pkix_RevocationMethod*)method;
method = NULL;
cleanup:
PKIX_DECREF(method);
PKIX_RETURN(OCSPCHECKER);
}
/*
* FUNCTION: pkix_OcspChecker_MapResultCodeToRevStatus
*/
PKIX_RevocationStatus
pkix_OcspChecker_MapResultCodeToRevStatus(SECErrorCodes resultCode)
{
switch (resultCode) {
case SEC_ERROR_REVOKED_CERTIFICATE:
return PKIX_RevStatus_Revoked;
default:
return PKIX_RevStatus_NoInfo;
}
}
/* --Public-Functions--------------------------------------------- */
/*
* FUNCTION: pkix_OcspChecker_Check (see comments in pkix_checker.h)
*/
/*
* The OCSPChecker is created in an idle state, and remains in this state until
* either (a) the default Responder has been set and enabled, and a Check
* request is received with no responder specified, or (b) a Check request is
* received with a specified responder. A request message is constructed and
* given to the HttpClient. If non-blocking I/O is used the client may return
* with WOULDBLOCK, in which case the OCSPChecker returns the WOULDBLOCK
* condition to its caller in turn. On a subsequent call the I/O is resumed.
* When a response is received it is decoded and the results provided to the
* caller.
*
*/
PKIX_Error *
pkix_OcspChecker_CheckLocal(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_Boolean chainVerificationState,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *pReasonCode,
void *plContext)
{
PKIX_PL_OcspCertID *cid = NULL;
PKIX_Boolean hasFreshStatus = PKIX_FALSE;
PKIX_Boolean statusIsGood = PKIX_FALSE;
SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckLocal");
PKIX_CHECK(
PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
plContext),
PKIX_OCSPCERTIDCREATEFAILED);
if (!cid) {
goto cleanup;
}
PKIX_CHECK(
PKIX_PL_OcspCertID_GetFreshCacheStatus(cid, date,
&hasFreshStatus,
&statusIsGood,
&resultCode,
plContext),
PKIX_OCSPCERTIDGETFRESHCACHESTATUSFAILED);
if (hasFreshStatus) {
if (statusIsGood) {
revStatus = PKIX_RevStatus_Success;
resultCode = 0;
} else {
revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
}
}
cleanup:
*pRevStatus = revStatus;
/* ocsp carries only tree statuses: good, bad, and unknown.
* revStatus is used to pass them. reasonCode is always set
* to be unknown. */
*pReasonCode = crlEntryReasonUnspecified;
PKIX_DECREF(cid);
PKIX_RETURN(OCSPCHECKER);
}
/*
* The OCSPChecker is created in an idle state, and remains in this state until
* either (a) the default Responder has been set and enabled, and a Check
* request is received with no responder specified, or (b) a Check request is
* received with a specified responder. A request message is constructed and
* given to the HttpClient. When a response is received it is decoded and the
* results provided to the caller.
*
* During the most recent enhancement of this function, it has been found that
* it doesn't correctly implement non-blocking I/O.
*
* The nbioContext is used in two places, for "response-obtaining" and
* for "response-verification".
*
* However, if this function gets called to resume, it always
* repeats the "request creation" and "response fetching" steps!
* As a result, the earlier operation is never resumed.
*/
PKIX_Error *
pkix_OcspChecker_CheckExternal(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *pReasonCode,
void **pNBIOContext,
void *plContext)
{
SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
PKIX_Boolean uriFound = PKIX_FALSE;
PKIX_Boolean passed = PKIX_TRUE;
pkix_OcspChecker *checker = NULL;
PKIX_PL_OcspCertID *cid = NULL;
PKIX_PL_OcspRequest *request = NULL;
PKIX_PL_OcspResponse *response = NULL;
PKIX_PL_Date *validity = NULL;
PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
void *nbioContext = NULL;
enum { stageGET, stagePOST } currentStage;
PRBool retry = PR_FALSE;
PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckExternal");
PKIX_CHECK(
pkix_CheckType((PKIX_PL_Object*)checkerObject,
PKIX_OCSPCHECKER_TYPE, plContext),
PKIX_OBJECTNOTOCSPCHECKER);
checker = (pkix_OcspChecker *)checkerObject;
PKIX_CHECK(
PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
plContext),
PKIX_OCSPCERTIDCREATEFAILED);
/* create request */
PKIX_CHECK(
pkix_pl_OcspRequest_Create(cert, cid, validity, NULL,
methodFlags, &uriFound, &request,
plContext),
PKIX_OCSPREQUESTCREATEFAILED);
if (uriFound == PKIX_FALSE) {
/* no caching for certs lacking URI */
resultCode = 0;
goto cleanup;
}
if (methodFlags & CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP) {
/* Do not try HTTP GET, only HTTP POST */
currentStage = stagePOST;
} else {
/* Try HTTP GET first, falling back to POST */
currentStage = stageGET;
}
do {
const char *method;
passed = PKIX_TRUE;
retry = PR_FALSE;
if (currentStage == stageGET) {
method = "GET";
} else {
PORT_Assert(currentStage == stagePOST);
method = "POST";
}
/* send request and create a response object */
PKIX_CHECK_NO_GOTO(
pkix_pl_OcspResponse_Create(request, method, NULL,
checker->certVerifyFcn,
&nbioContext,
&response,
plContext),
PKIX_OCSPRESPONSECREATEFAILED);
if (pkixErrorResult) {
passed = PKIX_FALSE;
}
if (passed && nbioContext != 0) {
*pNBIOContext = nbioContext;
goto cleanup;
}
if (passed){
PKIX_CHECK_NO_GOTO(
pkix_pl_OcspResponse_Decode(response, &passed,
&resultCode, plContext),
PKIX_OCSPRESPONSEDECODEFAILED);
if (pkixErrorResult) {
passed = PKIX_FALSE;
}
}
if (passed){
PKIX_CHECK_NO_GOTO(
pkix_pl_OcspResponse_GetStatus(response, &passed,
&resultCode, plContext),
PKIX_OCSPRESPONSEGETSTATUSRETURNEDANERROR);
if (pkixErrorResult) {
passed = PKIX_FALSE;
}
}
if (passed){
PKIX_CHECK_NO_GOTO(
pkix_pl_OcspResponse_VerifySignature(response, cert,
procParams, &passed,
&nbioContext, plContext),
PKIX_OCSPRESPONSEVERIFYSIGNATUREFAILED);
if (pkixErrorResult) {
passed = PKIX_FALSE;
} else {
if (nbioContext != 0) {
*pNBIOContext = nbioContext;
goto cleanup;
}
}
}
if (!passed && currentStage == stagePOST) {
/* We won't retry a POST failure, so it's final.
* Because the following block with its call to
* pkix_pl_OcspResponse_GetStatusForCert
* will take care of caching good or bad state,
* but we only execute that next block if there hasn't
* been a failure yet, we must cache the POST
* failure now.
*/
if (cid && cid->certID) {
/* Caching MIGHT consume the cid. */
PKIX_Error *err;
err = PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
cid, plContext);
if (err) {
PKIX_PL_Object_DecRef((PKIX_PL_Object*)err, plContext);
}
}
}
if (passed){
PKIX_Boolean allowCachingOfFailures =
(currentStage == stagePOST) ? PKIX_TRUE : PKIX_FALSE;
PKIX_CHECK_NO_GOTO(
pkix_pl_OcspResponse_GetStatusForCert(cid, response,
allowCachingOfFailures,
date,
&passed, &resultCode,
plContext),
PKIX_OCSPRESPONSEGETSTATUSFORCERTFAILED);
if (pkixErrorResult) {
passed = PKIX_FALSE;
} else if (passed == PKIX_FALSE) {
revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
} else {
revStatus = PKIX_RevStatus_Success;
}
}
if (currentStage == stageGET && revStatus != PKIX_RevStatus_Success &&
revStatus != PKIX_RevStatus_Revoked) {
/* we'll retry */
PKIX_DECREF(response);
retry = PR_TRUE;
currentStage = stagePOST;
revStatus = PKIX_RevStatus_NoInfo;
if (pkixErrorResult) {
PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
plContext);
pkixErrorResult = NULL;
}
}
} while (retry);
cleanup:
if (revStatus == PKIX_RevStatus_NoInfo && (uriFound ||
methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
revStatus = PKIX_RevStatus_Revoked;
}
*pRevStatus = revStatus;
/* ocsp carries only three statuses: good, bad, and unknown.
* revStatus is used to pass them. reasonCode is always set
* to be unknown. */
*pReasonCode = crlEntryReasonUnspecified;
PKIX_DECREF(cid);
PKIX_DECREF(request);
PKIX_DECREF(response);
PKIX_RETURN(OCSPCHECKER);
}

View file

@ -0,0 +1,67 @@
/* 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/. */
/*
* pkix_ocspchecker.h
*
* OcspChecker Object Type Definition
*
*/
#ifndef _PKIX_OCSPCHECKER_H
#define _PKIX_OCSPCHECKER_H
#include "pkix_tools.h"
#include "pkix_revocationmethod.h"
#ifdef __cplusplus
extern "C" {
#endif
/* NOTE: nbio logic removed. Will be replaced later. */
PKIX_Error *
pkix_OcspChecker_CheckLocal(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_Boolean chainVerificationState,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *reasonCode,
void *plContext);
PKIX_Error *
pkix_OcspChecker_CheckExternal(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *reasonCode,
void **pNBIOContext,
void *plContext);
PKIX_Error *
pkix_OcspChecker_Create(PKIX_RevocationMethodType methodType,
PKIX_UInt32 flags,
PKIX_UInt32 priority,
pkix_LocalRevocationCheckFn localRevChecker,
pkix_ExternalRevocationCheckFn externalRevChecker,
PKIX_PL_VerifyCallback certVerifyFn,
pkix_RevocationMethod **pChecker,
void *plContext);
/* see source file for function documentation */
PKIX_Error *pkix_OcspChecker_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_OCSPCHECKER_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,73 @@
/* 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/. */
/*
* pkix_policychecker.h
*
* Header file for policy checker.
*
*/
#ifndef _PKIX_POLICYCHECKER_H
#define _PKIX_POLICYCHECKER_H
#include "pkix_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct PKIX_PolicyCheckerStateStruct PKIX_PolicyCheckerState;
struct PKIX_PolicyCheckerStateStruct{
PKIX_PL_OID *certPoliciesExtension; /* const */
PKIX_PL_OID *policyMappingsExtension; /* const */
PKIX_PL_OID *policyConstraintsExtension; /* const */
PKIX_PL_OID *inhibitAnyPolicyExtension; /* const */
PKIX_PL_OID *anyPolicyOID; /* const */
PKIX_Boolean initialIsAnyPolicy; /* const */
PKIX_PolicyNode *validPolicyTree;
PKIX_List *userInitialPolicySet; /* immutable */
PKIX_List *mappedUserInitialPolicySet;
PKIX_Boolean policyQualifiersRejected;
PKIX_Boolean initialPolicyMappingInhibit;
PKIX_Boolean initialExplicitPolicy;
PKIX_Boolean initialAnyPolicyInhibit;
PKIX_UInt32 explicitPolicy;
PKIX_UInt32 inhibitAnyPolicy;
PKIX_UInt32 policyMapping;
PKIX_UInt32 numCerts;
PKIX_UInt32 certsProcessed;
PKIX_PolicyNode *anyPolicyNodeAtBottom;
PKIX_PolicyNode *newAnyPolicyNode;
/*
* The following variables do not survive from one
* certificate to the next. They are needed at each
* level of recursive routines, any by placing them
* in the state object we can pass fewer arguments.
*/
PKIX_Boolean certPoliciesCritical;
PKIX_List *mappedPolicyOIDs;
};
PKIX_Error *
pkix_PolicyChecker_Initialize(
PKIX_List *initialPolicies,
PKIX_Boolean policyQualifiersRejected,
PKIX_Boolean initialPolicyMappingInhibit,
PKIX_Boolean initialExplicitPolicy,
PKIX_Boolean initialAnyPolicyInhibit,
PKIX_UInt32 numCerts,
PKIX_CertChainChecker **pChecker,
void *plContext);
/* --Private-Functions-------------------------------------------- */
PKIX_Error *
pkix_PolicyCheckerState_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_POLICYCHECKER_H */

View file

@ -0,0 +1,475 @@
/* 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/. */
/*
* pkix_revocationchecker.c
*
* RevocationChecker Object Functions
*
*/
#include "pkix_revocationchecker.h"
#include "pkix_tools.h"
/* --Private-Functions-------------------------------------------- */
/*
* FUNCTION: pkix_RevocationChecker_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_RevocationChecker_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
PKIX_RevocationChecker *checker = NULL;
PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_Destroy");
PKIX_NULLCHECK_ONE(object);
/* Check that this object is a revocation checker */
PKIX_CHECK(pkix_CheckType
(object, PKIX_REVOCATIONCHECKER_TYPE, plContext),
PKIX_OBJECTNOTREVOCATIONCHECKER);
checker = (PKIX_RevocationChecker *)object;
PKIX_DECREF(checker->leafMethodList);
PKIX_DECREF(checker->chainMethodList);
cleanup:
PKIX_RETURN(REVOCATIONCHECKER);
}
/*
* FUNCTION: pkix_RevocationChecker_Duplicate
* (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_RevocationChecker_Duplicate(
PKIX_PL_Object *object,
PKIX_PL_Object **pNewObject,
void *plContext)
{
PKIX_RevocationChecker *checker = NULL;
PKIX_RevocationChecker *checkerDuplicate = NULL;
PKIX_List *dupLeafList = NULL;
PKIX_List *dupChainList = NULL;
PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_Duplicate");
PKIX_NULLCHECK_TWO(object, pNewObject);
PKIX_CHECK(pkix_CheckType
(object, PKIX_REVOCATIONCHECKER_TYPE, plContext),
PKIX_OBJECTNOTCERTCHAINCHECKER);
checker = (PKIX_RevocationChecker *)object;
if (checker->leafMethodList){
PKIX_CHECK(PKIX_PL_Object_Duplicate
((PKIX_PL_Object *)checker->leafMethodList,
(PKIX_PL_Object **)&dupLeafList,
plContext),
PKIX_OBJECTDUPLICATEFAILED);
}
if (checker->chainMethodList){
PKIX_CHECK(PKIX_PL_Object_Duplicate
((PKIX_PL_Object *)checker->chainMethodList,
(PKIX_PL_Object **)&dupChainList,
plContext),
PKIX_OBJECTDUPLICATEFAILED);
}
PKIX_CHECK(
PKIX_RevocationChecker_Create(checker->leafMethodListFlags,
checker->chainMethodListFlags,
&checkerDuplicate,
plContext),
PKIX_REVOCATIONCHECKERCREATEFAILED);
checkerDuplicate->leafMethodList = dupLeafList;
checkerDuplicate->chainMethodList = dupChainList;
dupLeafList = NULL;
dupChainList = NULL;
*pNewObject = (PKIX_PL_Object *)checkerDuplicate;
cleanup:
PKIX_DECREF(dupLeafList);
PKIX_DECREF(dupChainList);
PKIX_RETURN(REVOCATIONCHECKER);
}
/*
* FUNCTION: pkix_RevocationChecker_RegisterSelf
* DESCRIPTION:
* Registers PKIX_REVOCATIONCHECKER_TYPE and its related functions with
* systemClasses[]
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_RevocationChecker_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_RegisterSelf");
entry.description = "RevocationChecker";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(PKIX_RevocationChecker);
entry.destructor = pkix_RevocationChecker_Destroy;
entry.equalsFunction = NULL;
entry.hashcodeFunction = NULL;
entry.toStringFunction = NULL;
entry.comparator = NULL;
entry.duplicateFunction = pkix_RevocationChecker_Duplicate;
systemClasses[PKIX_REVOCATIONCHECKER_TYPE] = entry;
PKIX_RETURN(REVOCATIONCHECKER);
}
/* Sort methods by their priorities (lower priority = higher preference) */
static PKIX_Error *
pkix_RevocationChecker_SortComparator(
PKIX_PL_Object *obj1,
PKIX_PL_Object *obj2,
PKIX_Int32 *pResult,
void *plContext)
{
pkix_RevocationMethod *method1 = NULL, *method2 = NULL;
PKIX_ENTER(BUILD, "pkix_RevocationChecker_SortComparator");
method1 = (pkix_RevocationMethod *)obj1;
method2 = (pkix_RevocationMethod *)obj2;
if (method1->priority < method2->priority) {
*pResult = -1;
} else if (method1->priority > method2->priority) {
*pResult = 1;
} else {
*pResult = 0;
}
PKIX_RETURN(BUILD);
}
/* --Public-Functions--------------------------------------------- */
/*
* FUNCTION: PKIX_RevocationChecker_Create (see comments in pkix_revchecker.h)
*/
PKIX_Error *
PKIX_RevocationChecker_Create(
PKIX_UInt32 leafMethodListFlags,
PKIX_UInt32 chainMethodListFlags,
PKIX_RevocationChecker **pChecker,
void *plContext)
{
PKIX_RevocationChecker *checker = NULL;
PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Create");
PKIX_NULLCHECK_ONE(pChecker);
PKIX_CHECK(
PKIX_PL_Object_Alloc(PKIX_REVOCATIONCHECKER_TYPE,
sizeof (PKIX_RevocationChecker),
(PKIX_PL_Object **)&checker,
plContext),
PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
checker->leafMethodListFlags = leafMethodListFlags;
checker->chainMethodListFlags = chainMethodListFlags;
checker->leafMethodList = NULL;
checker->chainMethodList = NULL;
*pChecker = checker;
checker = NULL;
cleanup:
PKIX_DECREF(checker);
PKIX_RETURN(REVOCATIONCHECKER);
}
/*
* FUNCTION: PKIX_RevocationChecker_CreateAndAddMethod
*/
PKIX_Error *
PKIX_RevocationChecker_CreateAndAddMethod(
PKIX_RevocationChecker *revChecker,
PKIX_ProcessingParams *params,
PKIX_RevocationMethodType methodType,
PKIX_UInt32 flags,
PKIX_UInt32 priority,
PKIX_PL_VerifyCallback verificationFn,
PKIX_Boolean isLeafMethod,
void *plContext)
{
PKIX_List **methodList = NULL;
PKIX_List *unsortedList = NULL;
PKIX_List *certStores = NULL;
pkix_RevocationMethod *method = NULL;
pkix_LocalRevocationCheckFn *localRevChecker = NULL;
pkix_ExternalRevocationCheckFn *externRevChecker = NULL;
PKIX_UInt32 miFlags;
PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_CreateAndAddMethod");
PKIX_NULLCHECK_ONE(revChecker);
/* If the caller has said "Either one is sufficient, then don't let the
* absence of any one method's info lead to an overall failure.
*/
miFlags = isLeafMethod ? revChecker->leafMethodListFlags
: revChecker->chainMethodListFlags;
if (miFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE)
flags &= ~PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;
switch (methodType) {
case PKIX_RevocationMethod_CRL:
localRevChecker = pkix_CrlChecker_CheckLocal;
externRevChecker = pkix_CrlChecker_CheckExternal;
PKIX_CHECK(
PKIX_ProcessingParams_GetCertStores(params, &certStores,
plContext),
PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
PKIX_CHECK(
pkix_CrlChecker_Create(methodType, flags, priority,
localRevChecker, externRevChecker,
certStores, verificationFn,
&method,
plContext),
PKIX_COULDNOTCREATECRLCHECKEROBJECT);
break;
case PKIX_RevocationMethod_OCSP:
localRevChecker = pkix_OcspChecker_CheckLocal;
externRevChecker = pkix_OcspChecker_CheckExternal;
PKIX_CHECK(
pkix_OcspChecker_Create(methodType, flags, priority,
localRevChecker, externRevChecker,
verificationFn,
&method,
plContext),
PKIX_COULDNOTCREATEOCSPCHECKEROBJECT);
break;
default:
PKIX_ERROR(PKIX_INVALIDREVOCATIONMETHOD);
}
if (isLeafMethod) {
methodList = &revChecker->leafMethodList;
} else {
methodList = &revChecker->chainMethodList;
}
if (*methodList == NULL) {
PKIX_CHECK(
PKIX_List_Create(methodList, plContext),
PKIX_LISTCREATEFAILED);
}
unsortedList = *methodList;
PKIX_CHECK(
PKIX_List_AppendItem(unsortedList, (PKIX_PL_Object*)method, plContext),
PKIX_LISTAPPENDITEMFAILED);
PKIX_CHECK(
pkix_List_BubbleSort(unsortedList,
pkix_RevocationChecker_SortComparator,
methodList, plContext),
PKIX_LISTBUBBLESORTFAILED);
cleanup:
PKIX_DECREF(method);
PKIX_DECREF(unsortedList);
PKIX_DECREF(certStores);
PKIX_RETURN(REVOCATIONCHECKER);
}
/*
* FUNCTION: PKIX_RevocationChecker_Check
*/
PKIX_Error *
PKIX_RevocationChecker_Check(
PKIX_PL_Cert *cert,
PKIX_PL_Cert *issuer,
PKIX_RevocationChecker *revChecker,
PKIX_ProcessingParams *procParams,
PKIX_Boolean chainVerificationState,
PKIX_Boolean testingLeafCert,
PKIX_RevocationStatus *pRevStatus,
PKIX_UInt32 *pReasonCode,
void **pNbioContext,
void *plContext)
{
PKIX_RevocationStatus overallStatus = PKIX_RevStatus_NoInfo;
PKIX_RevocationStatus methodStatus[PKIX_RevocationMethod_MAX];
PKIX_Boolean onlyUseRemoteMethods = PKIX_FALSE;
PKIX_UInt32 revFlags = 0;
PKIX_List *revList = NULL;
PKIX_PL_Date *date = NULL;
pkix_RevocationMethod *method = NULL;
void *nbioContext;
int tries;
PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Check");
PKIX_NULLCHECK_TWO(revChecker, procParams);
nbioContext = *pNbioContext;
*pNbioContext = NULL;
if (testingLeafCert) {
revList = revChecker->leafMethodList;
revFlags = revChecker->leafMethodListFlags;
} else {
revList = revChecker->chainMethodList;
revFlags = revChecker->chainMethodListFlags;
}
if (!revList) {
/* Return NoInfo status */
goto cleanup;
}
PORT_Memset(methodStatus, PKIX_RevStatus_NoInfo,
sizeof(PKIX_RevocationStatus) * PKIX_RevocationMethod_MAX);
date = procParams->date;
/* Need to have two loops if we testing all local info first:
* first we are going to test all local(cached) info
* second, all remote info(fetching) */
for (tries = 0;tries < 2;tries++) {
unsigned int methodNum = 0;
for (;methodNum < revList->length;methodNum++) {
PKIX_UInt32 methodFlags = 0;
PKIX_DECREF(method);
PKIX_CHECK(
PKIX_List_GetItem(revList, methodNum,
(PKIX_PL_Object**)&method, plContext),
PKIX_LISTGETITEMFAILED);
methodFlags = method->flags;
if (!(methodFlags & PKIX_REV_M_TEST_USING_THIS_METHOD)) {
/* Will not check with this method. Skipping... */
continue;
}
if (!onlyUseRemoteMethods &&
methodStatus[methodNum] == PKIX_RevStatus_NoInfo) {
PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
PKIX_CHECK_NO_GOTO(
(*method->localRevChecker)(cert, issuer, date,
method, procParams,
methodFlags,
chainVerificationState,
&revStatus,
(CERTCRLEntryReasonCode *)pReasonCode,
plContext),
PKIX_REVCHECKERCHECKFAILED);
methodStatus[methodNum] = revStatus;
if (revStatus == PKIX_RevStatus_Revoked) {
/* if error was generated use it as final error. */
overallStatus = PKIX_RevStatus_Revoked;
goto cleanup;
}
if (pkixErrorResult) {
/* Disregard errors. Only returned revStatus matters. */
PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
plContext);
pkixErrorResult = NULL;
}
}
if ((!(revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST) ||
onlyUseRemoteMethods) &&
chainVerificationState &&
methodStatus[methodNum] == PKIX_RevStatus_NoInfo) {
if (!(methodFlags & PKIX_REV_M_FORBID_NETWORK_FETCHING)) {
PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
PKIX_CHECK_NO_GOTO(
(*method->externalRevChecker)(cert, issuer, date,
method,
procParams, methodFlags,
&revStatus,
(CERTCRLEntryReasonCode *)pReasonCode,
&nbioContext, plContext),
PKIX_REVCHECKERCHECKFAILED);
methodStatus[methodNum] = revStatus;
if (revStatus == PKIX_RevStatus_Revoked) {
/* if error was generated use it as final error. */
overallStatus = PKIX_RevStatus_Revoked;
goto cleanup;
}
if (pkixErrorResult) {
/* Disregard errors. Only returned revStatus matters. */
PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
plContext);
pkixErrorResult = NULL;
}
} else if (methodFlags &
PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
/* Info is not in the local cache. Network fetching is not
* allowed. If need to fail on missing fresh info for the
* the method, then we should fail right here.*/
overallStatus = PKIX_RevStatus_Revoked;
goto cleanup;
}
}
/* If success and we should not check the next method, then
* return a success. */
if (methodStatus[methodNum] == PKIX_RevStatus_Success &&
!(methodFlags & PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO)) {
overallStatus = PKIX_RevStatus_Success;
goto cleanup;
}
} /* inner loop */
if (!onlyUseRemoteMethods &&
revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST &&
chainVerificationState) {
onlyUseRemoteMethods = PKIX_TRUE;
continue;
}
break;
} /* outer loop */
if (overallStatus == PKIX_RevStatus_NoInfo &&
chainVerificationState) {
/* The following check makes sence only for chain
* validation step, sinse we do not fetch info while
* in the process of finding trusted anchor.
* For chain building step it is enough to know, that
* the cert was not directly revoked by any of the
* methods. */
/* Still have no info. But one of the method could
* have returned success status(possible if CONTINUE
* TESTING ON FRESH INFO flag was used).
* If any of the methods have returned Success status,
* the overallStatus should be success. */
int methodNum = 0;
for (;methodNum < PKIX_RevocationMethod_MAX;methodNum++) {
if (methodStatus[methodNum] == PKIX_RevStatus_Success) {
overallStatus = PKIX_RevStatus_Success;
goto cleanup;
}
}
if (revFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE) {
overallStatus = PKIX_RevStatus_Revoked;
}
}
cleanup:
*pRevStatus = overallStatus;
PKIX_DECREF(method);
PKIX_RETURN(REVOCATIONCHECKER);
}

View file

@ -0,0 +1,151 @@
/* 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/. */
/*
* pkix_revocationchecker.h
*
* RevocationChecker Object Type Definition
*
*/
#ifndef _PKIX_REVOCATIONCHECKER_H
#define _PKIX_REVOCATIONCHECKER_H
#include "pkixt.h"
#include "certt.h"
#ifdef __cplusplus
extern "C" {
#endif
/* NOTE: nbio logistic removed. Will be replaced later. */
/*
* All Flags are prefixed by CERT_REV_M_, where _M_ indicates
* this is a method dependent flag.
*/
/*
* Whether or not to use a method for revocation testing.
* If set to "do not test", then all other flags are ignored.
*/
#define PKIX_REV_M_DO_NOT_TEST_USING_THIS_METHOD 0x00L
#define PKIX_REV_M_TEST_USING_THIS_METHOD 0x01L
/*
* Whether or not NSS is allowed to attempt to fetch fresh information
* from the network.
* (Although fetching will never happen if fresh information for the
* method is already locally available.)
*/
#define PKIX_REV_M_ALLOW_NETWORK_FETCHING 0x00L
#define PKIX_REV_M_FORBID_NETWORK_FETCHING 0x02L
/*
* Example for an implicit default source:
* The globally configured default OCSP responder.
* IGNORE means:
* ignore the implicit default source, whether it's configured or not.
* ALLOW means:
* if an implicit default source is configured,
* then it overrides any available or missing source in the cert.
* if no implicit default source is configured,
* then we continue to use what's available (or not available)
* in the certs.
*/
#define PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE 0x00L
#define PKIX_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE 0x04L /* OCSP only */
/*
* Defines the behavior if no fresh information is available,
* fetching from the network is allowed, but the source of revocation
* information is unknown (even after considering implicit sources,
* if allowed by other flags).
* SKIPT_TEST means:
* We ignore that no fresh information is available and
* skip this test.
* REQUIRE_INFO means:
* We still require that fresh information is available.
* Other flags define what happens on missing fresh info.
*/
#define PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE 0x00L
#define PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE 0x08L
/*
* Defines the behavior if we are unable to obtain fresh information.
* INGORE means:
* Return "cert status unknown"
* FAIL means:
* Return "cert revoked".
*/
#define PKIX_REV_M_IGNORE_MISSING_FRESH_INFO 0x00L
#define PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO 0x10L
/*
* What should happen if we were able to find fresh information using
* this method, and the data indicated the cert is good?
* STOP_TESTING means:
* Our success is sufficient, do not continue testing
* other methods.
* CONTINUE_TESTING means:
* We will continue and test the next allowed
* specified method.
*/
#define PKIX_REV_M_STOP_TESTING_ON_FRESH_INFO 0x00L
#define PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO 0x20L
/*
* All Flags are prefixed by PKIX_REV_MI_, where _MI_ indicates
* this is a method independent flag.
*/
/*
* This defines the order to checking.
* EACH_METHOD_SEPARATELY means:
* Do all tests related to a particular allowed method
* (both local information and network fetching) in a single step.
* Only after testing for a particular method is done,
* then switching to the next method will happen.
* ALL_LOCAL_INFORMATION_FIRST means:
* Start by testing the information for all allowed methods
* which are already locally available. Only after that is done
* consider to fetch from the network (as allowed by other flags).
*/
#define PKIX_REV_MI_TEST_EACH_METHOD_SEPARATELY 0x00L
#define PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST 0x01L
/*
* Use this flag to specify that it's necessary that fresh information
* is available for at least one of the allowed methods, but it's
* irrelevant which of the mechanisms succeeded.
* NO_OVERALL_INFO_REQUIREMENT means:
* We strictly follow the requirements for each individual method.
* REQUIRE_SOME_FRESH_INFO_AVAILABLE means:
* After the individual tests have been executed, we must have
* been able to find fresh information using at least one method.
* If we were unable to find fresh info, it's a failure.
*/
#define PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT 0x00L
#define PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE 0x02L
/* Defines check time for the cert, revocation methods lists and
* flags for leaf and chain certs revocation tests. */
struct PKIX_RevocationCheckerStruct {
PKIX_List *leafMethodList;
PKIX_List *chainMethodList;
PKIX_UInt32 leafMethodListFlags;
PKIX_UInt32 chainMethodListFlags;
};
/* see source file for function documentation */
PKIX_Error *pkix_RevocationChecker_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_REVOCATIONCHECKER_H */

View file

@ -0,0 +1,66 @@
/* 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/. */
/*
* pkix_revocationmethod.c
*
* RevocationMethod Object Functions
*
*/
#include "pkix_revocationmethod.h"
#include "pkix_tools.h"
/* Constructor of revocation method object. Does not create an object,
* but just initializez PKIX_RevocationMethodStruct fields. Object
* suppose to be already created. */
PKIX_Error *
pkix_RevocationMethod_Init(
pkix_RevocationMethod *method,
PKIX_RevocationMethodType methodType,
PKIX_UInt32 flags,
PKIX_UInt32 priority,
pkix_LocalRevocationCheckFn localRevChecker,
pkix_ExternalRevocationCheckFn externalRevChecker,
void *plContext)
{
PKIX_ENTER(REVOCATIONMETHOD, "PKIX_RevocationMethod_Init");
method->methodType = methodType;
method->flags = flags;
method->priority = priority;
method->localRevChecker = localRevChecker;
method->externalRevChecker = externalRevChecker;
PKIX_RETURN(REVOCATIONMETHOD);
}
/* Data duplication data. Not create an object. Only initializes fields
* in the new object by data from "object". */
PKIX_Error *
pkix_RevocationMethod_Duplicate(
PKIX_PL_Object *object,
PKIX_PL_Object *newObject,
void *plContext)
{
pkix_RevocationMethod *method = NULL;
PKIX_ENTER(REVOCATIONMETHOD, "pkix_RevocationMethod_Duplicate");
PKIX_NULLCHECK_TWO(object, newObject);
method = (pkix_RevocationMethod *)object;
PKIX_CHECK(
pkix_RevocationMethod_Init((pkix_RevocationMethod*)newObject,
method->methodType,
method->flags,
method->priority,
method->localRevChecker,
method->externalRevChecker,
plContext),
PKIX_COULDNOTCREATEREVOCATIONMETHODOBJECT);
cleanup:
PKIX_RETURN(REVOCATIONMETHOD);
}

View file

@ -0,0 +1,81 @@
/* 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/. */
/*
* pkix_revocationmethod.h
*
* RevocationMethod Object
*
*/
#ifndef _PKIX_REVOCATIONMETHOD_H
#define _PKIX_REVOCATIONMETHOD_H
#include "pkixt.h"
#include "pkix_revocationchecker.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct pkix_RevocationMethodStruct pkix_RevocationMethod;
/* Local revocation check function prototype definition.
* Revocation methods capable of checking revocation though local
* means(cache) should implement this prototype. */
typedef PKIX_Error *
pkix_LocalRevocationCheckFn(PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_Boolean chainVerificationState,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *reasonCode,
void *plContext);
/* External revocation check function prototype definition.
* Revocation methods that required external communications(crldp
* ocsp) shoult implement this prototype. */
typedef PKIX_Error *
pkix_ExternalRevocationCheckFn(PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer,
PKIX_PL_Date *date,
pkix_RevocationMethod *checkerObject,
PKIX_ProcessingParams *procParams,
PKIX_UInt32 methodFlags,
PKIX_RevocationStatus *pRevStatus,
CERTCRLEntryReasonCode *reasonCode,
void **pNBIOContext, void *plContext);
/* Revocation method structure assosiates revocation types with
* a set of flags on the method, a priority of the method (0
* corresponds to the highest priority), and method local/external
* checker functions. */
struct pkix_RevocationMethodStruct {
PKIX_RevocationMethodType methodType;
PKIX_UInt32 flags;
PKIX_UInt32 priority;
pkix_LocalRevocationCheckFn (*localRevChecker);
pkix_ExternalRevocationCheckFn (*externalRevChecker);
};
PKIX_Error *
pkix_RevocationMethod_Duplicate(PKIX_PL_Object *object,
PKIX_PL_Object *newObject,
void *plContext);
PKIX_Error *
pkix_RevocationMethod_Init(pkix_RevocationMethod *method,
PKIX_RevocationMethodType methodType,
PKIX_UInt32 flags,
PKIX_UInt32 priority,
pkix_LocalRevocationCheckFn localRevChecker,
pkix_ExternalRevocationCheckFn externalRevChecker,
void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_REVOCATIONMETHOD_H */

View file

@ -0,0 +1,443 @@
/* 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/. */
/*
* pkix_signaturechecker.c
*
* Functions for signature validation
*
*/
#include "pkix_signaturechecker.h"
/*
* FUNCTION: pkix_SignatureCheckerstate_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_SignatureCheckerState_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
pkix_SignatureCheckerState *state = NULL;
PKIX_ENTER(SIGNATURECHECKERSTATE,
"pkix_SignatureCheckerState_Destroy");
PKIX_NULLCHECK_ONE(object);
/* Check that this object is a signature checker state */
PKIX_CHECK(pkix_CheckType
(object, PKIX_SIGNATURECHECKERSTATE_TYPE, plContext),
PKIX_OBJECTNOTSIGNATURECHECKERSTATE);
state = (pkix_SignatureCheckerState *) object;
state->prevCertCertSign = PKIX_FALSE;
PKIX_DECREF(state->prevPublicKey);
PKIX_DECREF(state->prevPublicKeyList);
PKIX_DECREF(state->keyUsageOID);
cleanup:
PKIX_RETURN(SIGNATURECHECKERSTATE);
}
/*
* FUNCTION: pkix_SignatureCheckerState_RegisterSelf
*
* DESCRIPTION:
* Registers PKIX_SIGNATURECHECKERSTATE_TYPE and its related functions
* with systemClasses[]
*
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_SignatureCheckerState_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER(SIGNATURECHECKERSTATE,
"pkix_SignatureCheckerState_RegisterSelf");
entry.description = "SignatureCheckerState";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(pkix_SignatureCheckerState);
entry.destructor = pkix_SignatureCheckerState_Destroy;
entry.equalsFunction = NULL;
entry.hashcodeFunction = NULL;
entry.toStringFunction = NULL;
entry.comparator = NULL;
entry.duplicateFunction = NULL;
systemClasses[PKIX_SIGNATURECHECKERSTATE_TYPE] = entry;
PKIX_RETURN(SIGNATURECHECKERSTATE);
}
/*
* FUNCTION: pkix_SignatureCheckerState_Create
*
* DESCRIPTION:
* Allocate and initialize SignatureChecker state data.
*
* PARAMETERS
* "trustedPubKey"
* Address of trusted Anchor Public Key for verifying first Cert in the
* chain. Must be non-NULL.
* "certsRemaining"
* Number of certificates remaining in the chain.
* "pCheckerState"
* Address where SignatureCheckerState will be stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
*
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
*
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a SignatureCheckerState Error if the function fails in a
* non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
static PKIX_Error *
pkix_SignatureCheckerState_Create(
PKIX_PL_PublicKey *trustedPubKey,
PKIX_UInt32 certsRemaining,
pkix_SignatureCheckerState **pCheckerState,
void *plContext)
{
pkix_SignatureCheckerState *state = NULL;
PKIX_PL_OID *keyUsageOID = NULL;
PKIX_ENTER(SIGNATURECHECKERSTATE, "pkix_SignatureCheckerState_Create");
PKIX_NULLCHECK_TWO(trustedPubKey, pCheckerState);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_SIGNATURECHECKERSTATE_TYPE,
sizeof (pkix_SignatureCheckerState),
(PKIX_PL_Object **)&state,
plContext),
PKIX_COULDNOTCREATESIGNATURECHECKERSTATEOBJECT);
/* Initialize fields */
state->prevCertCertSign = PKIX_TRUE;
state->prevPublicKeyList = NULL;
state->certsRemaining = certsRemaining;
PKIX_INCREF(trustedPubKey);
state->prevPublicKey = trustedPubKey;
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_CERTKEYUSAGE_OID,
&keyUsageOID,
plContext),
PKIX_OIDCREATEFAILED);
state->keyUsageOID = keyUsageOID;
keyUsageOID = NULL;
*pCheckerState = state;
state = NULL;
cleanup:
PKIX_DECREF(keyUsageOID);
PKIX_DECREF(state);
PKIX_RETURN(SIGNATURECHECKERSTATE);
}
/* --Private-Functions-------------------------------------------- */
/*
* FUNCTION: pkix_SignatureChecker_Check
* (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
*/
PKIX_Error *
pkix_SignatureChecker_Check(
PKIX_CertChainChecker *checker,
PKIX_PL_Cert *cert,
PKIX_List *unresolvedCriticalExtensions,
void **pNBIOContext,
void *plContext)
{
pkix_SignatureCheckerState *state = NULL;
PKIX_PL_PublicKey *prevPubKey = NULL;
PKIX_PL_PublicKey *currPubKey = NULL;
PKIX_PL_PublicKey *newPubKey = NULL;
PKIX_PL_PublicKey *pKey = NULL;
PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
PKIX_Error *checkKeyUsageFail = NULL;
PKIX_Error *verifyFail = NULL;
PKIX_Boolean certVerified = PKIX_FALSE;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_SignatureChecker_Check");
PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
*pNBIOContext = NULL; /* we never block on pending I/O */
PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
(checker, (PKIX_PL_Object **)&state, plContext),
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
(state->certsRemaining)--;
PKIX_INCREF(state->prevPublicKey);
prevPubKey = state->prevPublicKey;
/*
* Previous Cert doesn't have CertSign bit on for signature
* verification and it is not a self-issued Cert so there is no
* old key saved. This is considered error.
*/
if (state->prevCertCertSign == PKIX_FALSE &&
state->prevPublicKeyList == NULL) {
PKIX_ERROR(PKIX_KEYUSAGEKEYCERTSIGNBITNOTON);
}
/* Previous Cert is valid for signature verification, try it first */
if (state->prevCertCertSign == PKIX_TRUE) {
verifyFail = PKIX_PL_Cert_VerifySignature
(cert, prevPubKey, plContext);
if (verifyFail == NULL) {
certVerified = PKIX_TRUE;
} else {
certVerified = PKIX_FALSE;
}
}
#ifdef NIST_TEST_4_5_4_AND_4_5_6
/*
* Following codes under this compiler flag is implemented for
* special cases of NIST tests 4.5.4 and 4.5.6. We are not sure
* we should handle these two tests as what is implemented so the
* codes are commented out, and the tests fails (for now).
* For Cert chain validation, our assumption is all the Certs on
* the chain are using its previous Cert's public key to decode
* its current key. But for thses two tests, keys are used not
* in this precedent order, we can either
* 1) Use what is implemented here: take in what Cert order NIST
* specified and for continuous self-issued Certs, stacking up
* their keys and tries all of them in FILO order.
* But this method breaks the idea of chain key presdency.
* 2) Use Build Chain facility: we will specify the valid Certs
* order (means key precedency is kept) and count on Build Chain
* to get the Certs that can fill for the needed keys. This may have
* performance impact.
* 3) Fetch Certs from CertStore: we will specifiy the valid Certs
* order and use CertSelector on SubjectName to get a list of
* candidates Certs to fill in for the needed keys.
* Anyhow, the codes are kept around just in case we want to use
* solution one...
*/
/* If failed and previous key is self-issued, try its old key(s) */
if (certVerified == PKIX_FALSE && state->prevPublicKeyList != NULL) {
/* Verify from keys on the list */
PKIX_CHECK(PKIX_List_GetLength
(state->prevPublicKeyList, &numKeys, plContext),
PKIX_LISTGETLENGTHFAILED);
for (i = numKeys - 1; i >= 0; i--) {
PKIX_CHECK(PKIX_List_GetItem
(state->prevPublicKeyList,
i,
(PKIX_PL_Object **) &pKey,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_DECREF(verifyFail);
verifyFail = PKIX_PL_Cert_VerifySignature
(cert, pKey, plContext);
if (verifyFail == NULL) {
certVerified = PKIX_TRUE;
break;
} else {
certVerified = PKIX_FALSE;
}
PKIX_DECREF(pKey);
}
}
#endif
if (certVerified == PKIX_FALSE) {
pkixErrorResult = verifyFail;
verifyFail = NULL;
PKIX_ERROR(PKIX_VALIDATIONFAILEDCERTSIGNATURECHECKING);
}
#ifdef NIST_TEST_4_5_4_AND_4_5_6
/*
* Check if Cert is self-issued. If so, the old key(s) is saved, in
* conjunction to the new key, for verifying CERT validity later.
*/
PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
PKIX_ISCERTSELFISSUEFAILED);
/*
* Check if Cert is self-issued. If so, the public key of the Cert
* that issues this Cert (old key) can be used together with this
* current key (new key) for key verification. If there are multiple
* self-issued certs, keys of those Certs (old keys) can also be used
* for key verification. Old key(s) is saved in a list (PrevPublickKey-
* List) and cleared when a Cert is no longer self-issued. PrevPublic-
* Key keep key of the previous Cert.
*/
if (selfIssued == PKIX_TRUE) {
/* Make sure previous Cert is valid for signature verification */
if (state->prevCertCertSign == PKIX_TRUE) {
if (state->prevPublicKeyList == NULL) {
PKIX_CHECK(PKIX_List_Create
(&state->prevPublicKeyList, plContext),
PKIX_LISTCREATEFALIED);
}
PKIX_CHECK(PKIX_List_AppendItem
(state->prevPublicKeyList,
(PKIX_PL_Object *) state->prevPublicKey,
plContext),
PKIX_LISTAPPENDITEMFAILED);
}
} else {
/* Not self-issued Cert any more, clear old key(s) saved */
PKIX_DECREF(state->prevPublicKeyList);
}
#endif
/* Save current key as prevPublicKey */
PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
(cert, &currPubKey, plContext),
PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
PKIX_CHECK(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
(currPubKey, prevPubKey, &newPubKey, plContext),
PKIX_PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED);
if (newPubKey == NULL){
PKIX_INCREF(currPubKey);
newPubKey = currPubKey;
}
PKIX_INCREF(newPubKey);
PKIX_DECREF(state->prevPublicKey);
state->prevPublicKey = newPubKey;
/* Save this Cert key usage CertSign bit */
if (state->certsRemaining != 0) {
checkKeyUsageFail = PKIX_PL_Cert_VerifyKeyUsage
(cert, PKIX_KEY_CERT_SIGN, plContext);
state->prevCertCertSign = (checkKeyUsageFail == NULL)?
PKIX_TRUE:PKIX_FALSE;
PKIX_DECREF(checkKeyUsageFail);
}
/* Remove Key Usage Extension OID from list */
if (unresolvedCriticalExtensions != NULL) {
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticalExtensions,
(PKIX_PL_Object *) state->keyUsageOID,
plContext),
PKIX_LISTREMOVEFAILED);
}
PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
(checker, (PKIX_PL_Object *)state, plContext),
PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
cleanup:
PKIX_DECREF(state);
PKIX_DECREF(pKey);
PKIX_DECREF(prevPubKey);
PKIX_DECREF(currPubKey);
PKIX_DECREF(newPubKey);
PKIX_DECREF(basicConstraints);
PKIX_DECREF(verifyFail);
PKIX_DECREF(checkKeyUsageFail);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_SignatureChecker_Initialize
* DESCRIPTION:
*
* Creates a new CertChainChecker and stores it at "pChecker", where it will
* be used by pkix_SignatureChecker_Check to check that the public key in
* the checker's state is able to successfully validate the certificate's
* signature. The PublicKey pointed to by "trustedPubKey" is used to
* initialize the checker's state.
*
* PARAMETERS:
* "trustedPubKey"
* Address of PublicKey representing the trusted public key used to
* initialize the state of this checker. Must be non-NULL.
* "certsRemaining"
* Number of certificates remaining in the chain.
* "pChecker"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a CertChainChecker Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
PKIX_Error *
pkix_SignatureChecker_Initialize(
PKIX_PL_PublicKey *trustedPubKey,
PKIX_UInt32 certsRemaining,
PKIX_CertChainChecker **pChecker,
void *plContext)
{
pkix_SignatureCheckerState* state = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "PKIX_SignatureChecker_Initialize");
PKIX_NULLCHECK_TWO(pChecker, trustedPubKey);
PKIX_CHECK(pkix_SignatureCheckerState_Create
(trustedPubKey, certsRemaining, &state, plContext),
PKIX_SIGNATURECHECKERSTATECREATEFAILED);
PKIX_CHECK(PKIX_CertChainChecker_Create
(pkix_SignatureChecker_Check,
PKIX_FALSE,
PKIX_FALSE,
NULL,
(PKIX_PL_Object *) state,
pChecker,
plContext),
PKIX_CERTCHAINCHECKERCREATEFAILED);
cleanup:
PKIX_DECREF(state);
PKIX_RETURN(CERTCHAINCHECKER);
}

View file

@ -0,0 +1,44 @@
/* 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/. */
/*
* pkix_signaturechecker.h
*
* Header file for validate signature function
*
*/
#ifndef _PKIX_SIGNATURECHECKER_H
#define _PKIX_SIGNATURECHECKER_H
#include "pkix_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct pkix_SignatureCheckerState pkix_SignatureCheckerState;
struct pkix_SignatureCheckerState {
PKIX_Boolean prevCertCertSign;
PKIX_UInt32 certsRemaining;
PKIX_PL_PublicKey *prevPublicKey; /* Subject PubKey of last cert */
PKIX_List *prevPublicKeyList; /* of PKIX_PL_PublicKey */
PKIX_PL_OID *keyUsageOID;
};
PKIX_Error *
pkix_SignatureChecker_Initialize(
PKIX_PL_PublicKey *trustedPubKey,
PKIX_UInt32 certsRemaining,
PKIX_CertChainChecker **pChecker,
void *plContext);
PKIX_Error *
pkix_SignatureCheckerState_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_SIGNATURECHECKER_H */

View file

@ -0,0 +1,516 @@
/* 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/. */
/*
* pkix_targetcertchecker.c
*
* Functions for target cert validation
*
*/
#include "pkix_targetcertchecker.h"
/* --Private-TargetCertCheckerState-Functions------------------------------- */
/*
* FUNCTION: pkix_TargetCertCheckerState_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_TargetCertCheckerState_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
pkix_TargetCertCheckerState *state = NULL;
PKIX_ENTER(TARGETCERTCHECKERSTATE,
"pkix_TargetCertCheckerState_Destroy");
PKIX_NULLCHECK_ONE(object);
/* Check that this object is a target cert checker state */
PKIX_CHECK(pkix_CheckType
(object, PKIX_TARGETCERTCHECKERSTATE_TYPE, plContext),
PKIX_OBJECTNOTTARGETCERTCHECKERSTATE);
state = (pkix_TargetCertCheckerState *)object;
PKIX_DECREF(state->certSelector);
PKIX_DECREF(state->extKeyUsageOID);
PKIX_DECREF(state->subjAltNameOID);
PKIX_DECREF(state->pathToNameList);
PKIX_DECREF(state->extKeyUsageList);
PKIX_DECREF(state->subjAltNameList);
cleanup:
PKIX_RETURN(TARGETCERTCHECKERSTATE);
}
/*
* FUNCTION: pkix_TargetCertCheckerState_RegisterSelf
* DESCRIPTION:
* Registers PKIX_TARGETCERTCHECKERSTATE_TYPE and its related functions with
* systemClasses[]
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_TargetCertCheckerState_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER(TARGETCERTCHECKERSTATE,
"pkix_TargetCertCheckerState_RegisterSelf");
entry.description = "TargetCertCheckerState";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(pkix_TargetCertCheckerState);
entry.destructor = pkix_TargetCertCheckerState_Destroy;
entry.equalsFunction = NULL;
entry.hashcodeFunction = NULL;
entry.toStringFunction = NULL;
entry.comparator = NULL;
entry.duplicateFunction = NULL;
systemClasses[PKIX_TARGETCERTCHECKERSTATE_TYPE] = entry;
PKIX_RETURN(TARGETCERTCHECKERSTATE);
}
/*
* FUNCTION: pkix_TargetCertCheckerState_Create
* DESCRIPTION:
*
* Creates a new TargetCertCheckerState using the CertSelector pointed to
* by "certSelector" and the number of certs represented by "certsRemaining"
* and stores it at "pState".
*
* PARAMETERS:
* "certSelector"
* Address of CertSelector representing the criteria against which the
* final certificate in a chain is to be matched. Must be non-NULL.
* "certsRemaining"
* Number of certificates remaining in the chain.
* "pState"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a TargetCertCheckerState Error if the function fails in a
* non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
PKIX_Error *
pkix_TargetCertCheckerState_Create(
PKIX_CertSelector *certSelector,
PKIX_UInt32 certsRemaining,
pkix_TargetCertCheckerState **pState,
void *plContext)
{
pkix_TargetCertCheckerState *state = NULL;
PKIX_ComCertSelParams *certSelectorParams = NULL;
PKIX_List *pathToNameList = NULL;
PKIX_List *extKeyUsageList = NULL;
PKIX_List *subjAltNameList = NULL;
PKIX_PL_OID *extKeyUsageOID = NULL;
PKIX_PL_OID *subjAltNameOID = NULL;
PKIX_Boolean subjAltNameMatchAll = PKIX_TRUE;
PKIX_ENTER(TARGETCERTCHECKERSTATE,
"pkix_TargetCertCheckerState_Create");
PKIX_NULLCHECK_ONE(pState);
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_EXTENDEDKEYUSAGE_OID,
&extKeyUsageOID,
plContext),
PKIX_OIDCREATEFAILED);
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_CERTSUBJALTNAME_OID,
&subjAltNameOID,
plContext),
PKIX_OIDCREATEFAILED);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_TARGETCERTCHECKERSTATE_TYPE,
sizeof (pkix_TargetCertCheckerState),
(PKIX_PL_Object **)&state,
plContext),
PKIX_COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT);
/* initialize fields */
if (certSelector != NULL) {
PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
(certSelector, &certSelectorParams, plContext),
PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED);
if (certSelectorParams != NULL) {
PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
(certSelectorParams,
&pathToNameList,
plContext),
PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
(certSelectorParams,
&extKeyUsageList,
plContext),
PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
(certSelectorParams,
&subjAltNameList,
plContext),
PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
(certSelectorParams,
&subjAltNameMatchAll,
plContext),
PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
}
}
state->certsRemaining = certsRemaining;
state->subjAltNameMatchAll = subjAltNameMatchAll;
PKIX_INCREF(certSelector);
state->certSelector = certSelector;
state->pathToNameList = pathToNameList;
pathToNameList = NULL;
state->extKeyUsageList = extKeyUsageList;
extKeyUsageList = NULL;
state->subjAltNameList = subjAltNameList;
subjAltNameList = NULL;
state->extKeyUsageOID = extKeyUsageOID;
extKeyUsageOID = NULL;
state->subjAltNameOID = subjAltNameOID;
subjAltNameOID = NULL;
*pState = state;
state = NULL;
cleanup:
PKIX_DECREF(extKeyUsageOID);
PKIX_DECREF(subjAltNameOID);
PKIX_DECREF(pathToNameList);
PKIX_DECREF(extKeyUsageList);
PKIX_DECREF(subjAltNameList);
PKIX_DECREF(state);
PKIX_DECREF(certSelectorParams);
PKIX_RETURN(TARGETCERTCHECKERSTATE);
}
/* --Private-TargetCertChecker-Functions------------------------------- */
/*
* FUNCTION: pkix_TargetCertChecker_Check
* (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
*/
PKIX_Error *
pkix_TargetCertChecker_Check(
PKIX_CertChainChecker *checker,
PKIX_PL_Cert *cert,
PKIX_List *unresolvedCriticalExtensions,
void **pNBIOContext,
void *plContext)
{
pkix_TargetCertCheckerState *state = NULL;
PKIX_CertSelector_MatchCallback certSelectorMatch = NULL;
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
PKIX_List *certSubjAltNames = NULL;
PKIX_List *certExtKeyUsageList = NULL;
PKIX_PL_GeneralName *name = NULL;
PKIX_PL_X500Name *certSubjectName = NULL;
PKIX_Boolean checkPassed = PKIX_FALSE;
PKIX_UInt32 numItems, i;
PKIX_UInt32 matchCount = 0;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Check");
PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
*pNBIOContext = NULL; /* we never block on pending I/O */
PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
(checker, (PKIX_PL_Object **)&state, plContext),
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
(state->certsRemaining)--;
if (state->pathToNameList != NULL) {
PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
(cert, &nameConstraints, plContext),
PKIX_CERTGETNAMECONSTRAINTSFAILED);
/*
* XXX We should either make the following call a public one
* so it is legal to call from the portability layer or we
* should try to create pathToNameList as CertNameConstraints
* then call the existing check function.
*/
PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
(state->pathToNameList,
nameConstraints,
&checkPassed,
plContext),
PKIX_CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED);
if (checkPassed != PKIX_TRUE) {
PKIX_ERROR(PKIX_VALIDATIONFAILEDPATHTONAMECHECKFAILED);
}
}
PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
(cert, &certSubjAltNames, plContext),
PKIX_CERTGETSUBJALTNAMESFAILED);
if (state->subjAltNameList != NULL && certSubjAltNames != NULL) {
PKIX_CHECK(PKIX_List_GetLength
(state->subjAltNameList, &numItems, plContext),
PKIX_LISTGETLENGTHFAILED);
for (i = 0; i < numItems; i++) {
PKIX_CHECK(PKIX_List_GetItem
(state->subjAltNameList,
i,
(PKIX_PL_Object **) &name,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(pkix_List_Contains
(certSubjAltNames,
(PKIX_PL_Object *) name,
&checkPassed,
plContext),
PKIX_LISTCONTAINSFAILED);
PKIX_DECREF(name);
if (checkPassed == PKIX_TRUE) {
if (state->subjAltNameMatchAll == PKIX_FALSE) {
matchCount = numItems;
break;
} else {
/* else continue checking next */
matchCount++;
}
}
}
if (matchCount != numItems) {
PKIX_ERROR(PKIX_SUBJALTNAMECHECKFAILED);
}
}
if (state->certsRemaining == 0) {
if (state->certSelector != NULL) {
PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
(state->certSelector,
&certSelectorMatch,
plContext),
PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
PKIX_CHECK(certSelectorMatch
(state->certSelector,
cert,
plContext),
PKIX_CERTSELECTORMATCHFAILED);
} else {
/* Check at least cert/key usages if target cert selector
* is not set. */
PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert,
PKIX_FALSE /* is chain cert*/,
plContext),
PKIX_CERTVERIFYCERTTYPEFAILED);
}
/*
* There are two Extended Key Usage Checkings
* available :
* 1) here at the targetcertchecker where we
* verify the Extended Key Usage OIDs application
* specifies via ComCertSelParams are included
* in Cert's Extended Key Usage OID's. Note,
* this is an OID to OID comparison and only last
* Cert is checked.
* 2) at user defined ekuchecker where checking
* is applied to all Certs on the chain and
* the NSS Extended Key Usage algorithm is
* used. In order to invoke this checking, not
* only does the ComCertSelparams needs to be
* set, the EKU initialize call is required to
* activate the checking.
*
* XXX We use the same ComCertSelParams Set/Get
* functions to set the parameters for both cases.
* We may want to separate them in the future.
*/
PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
(cert, &certExtKeyUsageList, plContext),
PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
if (state->extKeyUsageList != NULL &&
certExtKeyUsageList != NULL) {
PKIX_CHECK(PKIX_List_GetLength
(state->extKeyUsageList, &numItems, plContext),
PKIX_LISTGETLENGTHFAILED);
for (i = 0; i < numItems; i++) {
PKIX_CHECK(PKIX_List_GetItem
(state->extKeyUsageList,
i,
(PKIX_PL_Object **) &name,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(pkix_List_Contains
(certExtKeyUsageList,
(PKIX_PL_Object *) name,
&checkPassed,
plContext),
PKIX_LISTCONTAINSFAILED);
PKIX_DECREF(name);
if (checkPassed != PKIX_TRUE) {
PKIX_ERROR
(PKIX_EXTENDEDKEYUSAGECHECKINGFAILED);
}
}
}
} else {
/* Check key usage and cert type based on certificate usage. */
PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, PKIX_TRUE,
plContext),
PKIX_CERTVERIFYCERTTYPEFAILED);
}
/* Remove Critical Extension OID from list */
if (unresolvedCriticalExtensions != NULL) {
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticalExtensions,
(PKIX_PL_Object *) state->extKeyUsageOID,
plContext),
PKIX_LISTREMOVEFAILED);
PKIX_CHECK(PKIX_PL_Cert_GetSubject
(cert, &certSubjectName, plContext),
PKIX_CERTGETSUBJECTFAILED);
if (certSubjAltNames != NULL) {
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticalExtensions,
(PKIX_PL_Object *) state->subjAltNameOID,
plContext),
PKIX_LISTREMOVEFAILED);
}
}
cleanup:
PKIX_DECREF(name);
PKIX_DECREF(nameConstraints);
PKIX_DECREF(certSubjAltNames);
PKIX_DECREF(certExtKeyUsageList);
PKIX_DECREF(certSubjectName);
PKIX_DECREF(state);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_TargetCertChecker_Initialize
* DESCRIPTION:
*
* Creates a new CertChainChecker and stores it at "pChecker", where it will
* used by pkix_TargetCertChecker_Check to check that the final certificate
* of a chain meets the criteria of the CertSelector pointed to by
* "certSelector". The number of certs remaining in the chain, represented by
* "certsRemaining" is used to initialize the checker's state.
*
* PARAMETERS:
* "certSelector"
* Address of CertSelector representing the criteria against which the
* final certificate in a chain is to be matched. May be NULL.
* "certsRemaining"
* Number of certificates remaining in the chain.
* "pChecker"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a CertChainChecker Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
PKIX_Error *
pkix_TargetCertChecker_Initialize(
PKIX_CertSelector *certSelector,
PKIX_UInt32 certsRemaining,
PKIX_CertChainChecker **pChecker,
void *plContext)
{
pkix_TargetCertCheckerState *state = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Initialize");
PKIX_NULLCHECK_ONE(pChecker);
PKIX_CHECK(pkix_TargetCertCheckerState_Create
(certSelector, certsRemaining, &state, plContext),
PKIX_TARGETCERTCHECKERSTATECREATEFAILED);
PKIX_CHECK(PKIX_CertChainChecker_Create
(pkix_TargetCertChecker_Check,
PKIX_FALSE,
PKIX_FALSE,
NULL,
(PKIX_PL_Object *)state,
pChecker,
plContext),
PKIX_CERTCHAINCHECKERCREATEFAILED);
cleanup:
PKIX_DECREF(state);
PKIX_RETURN(CERTCHAINCHECKER);
}

View file

@ -0,0 +1,47 @@
/* 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/. */
/*
* pkix_targetcertchecker.h
*
* Header file for validate target cert function
*
*/
#ifndef _PKIX_TARGETCERTCHECKER_H
#define _PKIX_TARGETCERTCHECKER_H
#include "pkix_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct pkix_TargetCertCheckerState pkix_TargetCertCheckerState;
struct pkix_TargetCertCheckerState {
PKIX_CertSelector *certSelector;
PKIX_List *pathToNameList;
PKIX_List *extKeyUsageList; /* List of PKIX_PL_OID */
PKIX_List *subjAltNameList;
PKIX_Boolean subjAltNameMatchAll;
PKIX_UInt32 certsRemaining;
PKIX_PL_OID *extKeyUsageOID;
PKIX_PL_OID *subjAltNameOID;
};
PKIX_Error *
pkix_TargetCertChecker_Initialize(
PKIX_CertSelector *certSelector,
PKIX_UInt32 certsRemaining,
PKIX_CertChainChecker **pChecker,
void *plContext);
PKIX_Error *
pkix_TargetCertCheckerState_RegisterSelf(void *plContext);
#ifdef __cplusplus
}
#endif
#endif /* _PKIX_TARGETCERTCHECKER_H */