diff options
Diffstat (limited to 'security/nss/lib/libpkix/pkix')
101 files changed, 32506 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix/Makefile b/security/nss/lib/libpkix/pkix/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/Makefile @@ -0,0 +1,46 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/certsel/Makefile b/security/nss/lib/libpkix/pkix/certsel/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/certsel/Makefile @@ -0,0 +1,46 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/certsel/certsel.gyp b/security/nss/lib/libpkix/pkix/certsel/certsel.gyp new file mode 100644 index 0000000000..a7ff65ce76 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/certsel/certsel.gyp @@ -0,0 +1,24 @@ +# 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': 'pkixcertsel', + 'type': 'static_library', + 'sources': [ + 'pkix_certselector.c', + 'pkix_comcertselparams.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix/certsel/exports.gyp b/security/nss/lib/libpkix/pkix/certsel/exports.gyp new file mode 100644 index 0000000000..9cbd847e7c --- /dev/null +++ b/security/nss/lib/libpkix/pkix/certsel/exports.gyp @@ -0,0 +1,26 @@ +# 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_certsel_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_certselector.h', + 'pkix_comcertselparams.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/certsel/manifest.mn b/security/nss/lib/libpkix/pkix/certsel/manifest.mn new file mode 100644 index 0000000000..eb434bd531 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/certsel/manifest.mn @@ -0,0 +1,20 @@ +# +# 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 = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_certselector.h \ + pkix_comcertselparams.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_certselector.c \ + pkix_comcertselparams.c \ + $(NULL) + +LIBRARY_NAME = pkixcertsel +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c new file mode 100644 index 0000000000..89bddd98bc --- /dev/null +++ b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c @@ -0,0 +1,1637 @@ +/* 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_certselector.c + * + * CertSelector Object Functions + * + */ + +#include "pkix_certselector.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_CertSelector_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CertSelector_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_CertSelector *selector = NULL; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a cert selector */ + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSELECTOR_TYPE, plContext), + PKIX_OBJECTNOTCERTSELECTOR); + + selector = (PKIX_CertSelector *)object; + PKIX_DECREF(selector->params); + PKIX_DECREF(selector->context); + +cleanup: + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Duplicate + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CertSelector_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_CertSelector *certSelector = NULL; + PKIX_CertSelector *certSelectorDuplicate = NULL; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSELECTOR_TYPE, plContext), + PKIX_OBJECTNOTCERTSELECTOR); + + certSelector = (PKIX_CertSelector *)object; + + PKIX_CHECK(PKIX_CertSelector_Create + (certSelector->matchCallback, + certSelector->context, + &certSelectorDuplicate, + plContext), + PKIX_CERTSELECTORCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Object_Duplicate + ((PKIX_PL_Object *)certSelector->params, + (PKIX_PL_Object **)&certSelectorDuplicate->params, + plContext), + PKIX_OBJECTDUPLICATEFAILED); + + *pNewObject = (PKIX_PL_Object *)certSelectorDuplicate; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(certSelectorDuplicate); + } + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_BasicConstraint + * DESCRIPTION: + * + * Determines whether the Cert pointed to by "cert" matches the basic + * constraints criterion using the basic constraints field of the + * ComCertSelParams pointed to by "params". If the basic constraints field is + * -1, no basic constraints check is done and the Cert is considered to match + * the basic constraints criterion. If the Cert does not match the basic + * constraints criterion, an Error pointer is returned. + * + * In order to match against this criterion, there are several possibilities. + * + * 1) If the criterion's minimum path length is greater than or equal to zero, + * a certificate must include a BasicConstraints extension with a pathLen of + * at least this value. + * + * 2) If the criterion's minimum path length is -2, a certificate must be an + * end-entity certificate. + * + * 3) If the criterion's minimum path length is -1, no basic constraints check + * is done and all certificates are considered to match this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose basic constraints field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * OUTPUT PARAMETERS ON FAILURE: + * If the function returns a failure, + * the output parameters of this function are undefined. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_BasicConstraint( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CertBasicConstraints *basicConstraints = NULL; + PKIX_Boolean caFlag = PKIX_FALSE; /* EE Cert by default */ + PKIX_Int32 pathLength = 0; + PKIX_Int32 minPathLength = 0; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_BasicConstraint"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + *pResult = PKIX_TRUE; + + PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints + (params, &minPathLength, plContext), + PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED); + + /* If the minPathLength is unlimited (-1), no checking */ + if (minPathLength == PKIX_CERTSEL_ALL_MATCH_MIN_PATHLENGTH) { + goto cleanup; + } + + PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints + (cert, &basicConstraints, plContext), + PKIX_CERTGETBASICCONSTRAINTSFAILED); + + if (basicConstraints != NULL) { + PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag + (basicConstraints, &caFlag, plContext), + PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); + + PKIX_CHECK(PKIX_PL_BasicConstraints_GetPathLenConstraint + (basicConstraints, &pathLength, plContext), + PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED); + } + + /* + * if minPathLength >= 0, the cert must have a BasicConstraints ext and + * the pathLength in this cert + * BasicConstraints needs to be >= minPathLength. + */ + if (minPathLength >= 0){ + if ((!basicConstraints) || (caFlag == PKIX_FALSE)){ + PKIX_ERROR(PKIX_CERTNOTALLOWEDTOSIGNCERTIFICATES); + } else if ((pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) && + (pathLength < minPathLength)){ + PKIX_CERTSELECTOR_DEBUG + ("Basic Constraints path length match failed\n"); + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_PATHLENCONSTRAINTINVALID); + } + } + + /* if the minPathLength is -2, this cert must be an end-entity cert. */ + if (minPathLength == PKIX_CERTSEL_ENDENTITY_MIN_PATHLENGTH) { + if (caFlag == PKIX_TRUE) { + PKIX_CERTSELECTOR_DEBUG + ("Basic Constraints end-entity match failed\n"); + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_PATHLENCONSTRAINTINVALID); + } + } + +cleanup: + + PKIX_DECREF(basicConstraints); + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_Policies + * DESCRIPTION: + * + * Determines whether the Cert pointed to by "cert" matches the policy + * constraints specified in the ComCertsSelParams given by "params". + * If "params" specifies a policy constraint of NULL, all certificates + * match. If "params" specifies an empty list, "cert" must have at least + * some policy. Otherwise "cert" must include at least one of the + * policies in the list. See the description of PKIX_CertSelector in + * pkix_certsel.h for more. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose policy criterion (if any) is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_Policies( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 numConstraintPolicies = 0; + PKIX_UInt32 numCertPolicies = 0; + PKIX_UInt32 certPolicyIndex = 0; + PKIX_Boolean result = PKIX_FALSE; + PKIX_List *constraintPolicies = NULL; /* List of PKIX_PL_OID */ + PKIX_List *certPolicyInfos = NULL; /* List of PKIX_PL_CertPolicyInfo */ + PKIX_PL_CertPolicyInfo *policyInfo = NULL; + PKIX_PL_OID *polOID = NULL; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_Policies"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetPolicy + (params, &constraintPolicies, plContext), + PKIX_COMCERTSELPARAMSGETPOLICYFAILED); + + /* If constraintPolicies is NULL, all certificates "match" */ + if (constraintPolicies) { + PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation + (cert, &certPolicyInfos, plContext), + PKIX_CERTGETPOLICYINFORMATIONFAILED); + + /* No hope of a match if cert has no policies */ + if (!certPolicyInfos) { + PKIX_CERTSELECTOR_DEBUG("Certificate has no policies\n"); + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHPOLICIESFAILED); + } + + PKIX_CHECK(PKIX_List_GetLength + (constraintPolicies, &numConstraintPolicies, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numConstraintPolicies > 0) { + + PKIX_CHECK(PKIX_List_GetLength + (certPolicyInfos, &numCertPolicies, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (certPolicyIndex = 0; + ((!result) && (certPolicyIndex < numCertPolicies)); + certPolicyIndex++) { + + PKIX_CHECK(PKIX_List_GetItem + (certPolicyInfos, + certPolicyIndex, + (PKIX_PL_Object **)&policyInfo, + plContext), + PKIX_LISTGETELEMENTFAILED); + PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId + (policyInfo, &polOID, plContext), + PKIX_CERTPOLICYINFOGETPOLICYIDFAILED); + + PKIX_CHECK(pkix_List_Contains + (constraintPolicies, + (PKIX_PL_Object *)polOID, + &result, + plContext), + PKIX_LISTCONTAINSFAILED); + PKIX_DECREF(policyInfo); + PKIX_DECREF(polOID); + } + if (!result) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHPOLICIESFAILED); + } + } + } + +cleanup: + + PKIX_DECREF(constraintPolicies); + PKIX_DECREF(certPolicyInfos); + PKIX_DECREF(policyInfo); + PKIX_DECREF(polOID); + + PKIX_RETURN(CERTSELECTOR); + +} + +/* + * FUNCTION: pkix_CertSelector_Match_CertificateValid + * DESCRIPTION: + * + * Determines whether the Cert pointed to by "cert" matches the certificate + * validity criterion using the CertificateValid field of the + * ComCertSelParams pointed to by "params". If the CertificateValid field is + * NULL, no validity check is done and the Cert is considered to match + * the CertificateValid criterion. If the CertificateValid field specifies a + * Date prior to the notBefore field in the Cert, or greater than the notAfter + * field in the Cert, an Error is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose certValid field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_CertificateValid( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_Date *validityTime = NULL; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_CertificateValid"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid + (params, &validityTime, plContext), + PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED); + + /* If the validityTime is not set, all certificates are acceptable */ + if (validityTime) { + PKIX_CHECK(PKIX_PL_Cert_CheckValidity + (cert, validityTime, plContext), + PKIX_CERTCHECKVALIDITYFAILED); + } + +cleanup: + if (PKIX_ERROR_RECEIVED) { + *pResult = PKIX_FALSE; + } + PKIX_DECREF(validityTime); + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_NameConstraints + * DESCRIPTION: + * + * Determines whether the Cert pointed to by "cert" matches the name + * constraints criterion specified in the ComCertSelParams pointed to by + * "params". If the name constraints field is NULL, no name constraints check + * is done and the Cert is considered to match the name constraints criterion. + * If the Cert does not match the name constraints criterion, an Error pointer + * is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose name constraints field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_NameConstraints( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_NameConstraints"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetNameConstraints + (params, &nameConstraints, plContext), + PKIX_COMCERTSELPARAMSGETNAMECONSTRAINTSFAILED); + + if (nameConstraints != NULL) { + /* As only the end-entity certificate should have + * the common name constrained as if it was a dNSName, + * do not constrain the common name when building a + * forward path. + */ + PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints + (cert, nameConstraints, PKIX_FALSE, plContext), + PKIX_CERTCHECKNAMECONSTRAINTSFAILED); + } + +cleanup: + if (PKIX_ERROR_RECEIVED) { + *pResult = PKIX_FALSE; + } + + PKIX_DECREF(nameConstraints); + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_PathToNames + * DESCRIPTION: + * + * Determines whether the names at pathToNames in "params" complies with the + * NameConstraints pointed to by "cert". If the pathToNames field is NULL + * or there is no name constraints for this "cert", no checking is done + * and the Cert is considered to match the name constraints criterion. + * If the Cert does not match the name constraints criterion, an Error + * pointer is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose PathToNames field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_PathToNames( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_List *pathToNamesList = NULL; + PKIX_Boolean passed = PKIX_FALSE; + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_PathToNames"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames + (params, &pathToNamesList, plContext), + PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED); + + if (pathToNamesList != NULL) { + + PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints + (cert, &nameConstraints, plContext), + PKIX_CERTGETNAMECONSTRAINTSFAILED); + + if (nameConstraints != NULL) { + + PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace + (pathToNamesList, nameConstraints, &passed, plContext), + PKIX_CERTNAMECONSTRAINTSCHECKNAMESINNAMESPACEFAILED); + + if (passed != PKIX_TRUE) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHPATHTONAMESFAILED); + } + } + + } + +cleanup: + + PKIX_DECREF(nameConstraints); + PKIX_DECREF(pathToNamesList); + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_SubjAltNames + * DESCRIPTION: + * + * Determines whether the names at subjAltNames in "params" match with the + * SubjAltNames pointed to by "cert". If the subjAltNames field is NULL, + * no name checking is done and the Cert is considered to match the + * criterion. If the Cert does not match the criterion, an Error pointer + * is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose SubjAltNames field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_SubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_List *subjAltNamesList = NULL; + PKIX_List *certSubjAltNames = NULL; + PKIX_PL_GeneralName *name = NULL; + PKIX_Boolean checkPassed = PKIX_FALSE; + PKIX_Boolean matchAll = PKIX_TRUE; + PKIX_UInt32 i, numItems; + PKIX_UInt32 matchCount = 0; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjAltNames"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames + (params, &matchAll, plContext), + PKIX_COMCERTSELPARAMSGETMATCHALLSUBJALTNAMESFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames + (params, &subjAltNamesList, plContext), + PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED); + + if (subjAltNamesList != NULL) { + + PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames + (cert, &certSubjAltNames, plContext), + PKIX_CERTGETSUBJALTNAMESFAILED); + + if (certSubjAltNames == NULL) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED); + } + + PKIX_CHECK(PKIX_List_GetLength + (subjAltNamesList, &numItems, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (subjAltNamesList, + 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 (matchAll == PKIX_FALSE) { + /* one match is good enough */ + matchCount = numItems; + break; + } else { + /* else continue checking next */ + matchCount++; + } + + } + + } + + if (matchCount != numItems) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED); + } + } + +cleanup: + + PKIX_DECREF(name); + PKIX_DECREF(certSubjAltNames); + PKIX_DECREF(subjAltNamesList); + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_ExtendedKeyUsage + * DESCRIPTION: + * + * Determines whether the names at ExtKeyUsage in "params" matches with the + * ExtKeyUsage pointed to by "cert". If the ExtKeyUsage criterion or + * ExtKeyUsage in "cert" is NULL, no checking is done and the Cert is + * considered a match. If the Cert does not match, an Error pointer is + * returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose ExtKeyUsage field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_ExtendedKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_List *extKeyUsageList = NULL; + PKIX_List *certExtKeyUsageList = NULL; + PKIX_PL_OID *ekuOid = NULL; + PKIX_Boolean isContained = PKIX_FALSE; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_ExtendedKeyUsage"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage + (params, &extKeyUsageList, plContext), + PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); + + if (extKeyUsageList == NULL) { + goto cleanup; + } + + PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage + (cert, &certExtKeyUsageList, plContext), + PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); + + if (certExtKeyUsageList != NULL) { + + PKIX_CHECK(PKIX_List_GetLength + (extKeyUsageList, &numItems, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (extKeyUsageList, 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) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED); + } + } + } + +cleanup: + + PKIX_DECREF(ekuOid); + PKIX_DECREF(extKeyUsageList); + PKIX_DECREF(certExtKeyUsageList); + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_KeyUsage + * DESCRIPTION: + * + * Determines whether the bits at KeyUsage in "params" matches with the + * KeyUsage pointed to by "cert". If the KeyUsage in params is 0 + * no checking is done and the Cert is considered a match. If the Cert does + * not match, an Error pointer is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose ExtKeyUsage field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_KeyUsage( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 keyUsage = 0; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_KeyUsage"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage + (params, &keyUsage, plContext), + PKIX_COMCERTSELPARAMSGETKEYUSAGEFAILED); + + if (keyUsage != 0) { + + PKIX_CHECK(PKIX_PL_Cert_VerifyKeyUsage + (cert, keyUsage, plContext), + PKIX_CERTVERIFYKEYUSAGEFAILED); + + } + +cleanup: + if (PKIX_ERROR_RECEIVED) { + *pResult = PKIX_FALSE; + } + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_SubjKeyId + * DESCRIPTION: + * + * Determines whether the bytes at subjKeyId in "params" matches with the + * Subject Key Identifier pointed to by "cert". If the subjKeyId in params is + * set to NULL or the Cert doesn't have a Subject Key Identifier, no checking + * is done and the Cert is considered a match. If the Cert does not match, an + * Error pointer is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose subjKeyId field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_SubjKeyId( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_ByteArray *selSubjKeyId = NULL; + PKIX_PL_ByteArray *certSubjKeyId = NULL; + PKIX_Boolean equals = PKIX_FALSE; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjKeyId"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubjKeyIdentifier + (params, &selSubjKeyId, plContext), + PKIX_COMCERTSELPARAMSGETSUBJKEYIDENTIFIERFAILED); + + if (selSubjKeyId != NULL) { + + PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier + (cert, &certSubjKeyId, plContext), + PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED); + + if (certSubjKeyId == NULL) { + goto cleanup; + } + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)selSubjKeyId, + (PKIX_PL_Object *)certSubjKeyId, + &equals, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (equals == PKIX_FALSE) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJKEYIDFAILED); + } + } + +cleanup: + + PKIX_DECREF(selSubjKeyId); + PKIX_DECREF(certSubjKeyId); + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_AuthKeyId + * DESCRIPTION: + * + * Determines whether the bytes at authKeyId in "params" matches with the + * Authority Key Identifier pointed to by "cert". If the authKeyId in params + * is set to NULL, no checking is done and the Cert is considered a match. If + * the Cert does not match, an Error pointer is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose authKeyId field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_AuthKeyId( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_ByteArray *selAuthKeyId = NULL; + PKIX_PL_ByteArray *certAuthKeyId = NULL; + PKIX_Boolean equals = PKIX_FALSE; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_AuthKeyId"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetAuthorityKeyIdentifier + (params, &selAuthKeyId, plContext), + PKIX_COMCERTSELPARAMSGETAUTHORITYKEYIDENTIFIERFAILED); + + if (selAuthKeyId != NULL) { + + PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier + (cert, &certAuthKeyId, plContext), + PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); + + if (certAuthKeyId == NULL) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED); + } + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)selAuthKeyId, + (PKIX_PL_Object *)certAuthKeyId, + &equals, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (equals != PKIX_TRUE) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED); + } + } + +cleanup: + + PKIX_DECREF(selAuthKeyId); + PKIX_DECREF(certAuthKeyId); + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_SubjPKAlgId + * DESCRIPTION: + * + * Determines whether the OID at subjPKAlgId in "params" matches with the + * Subject Public Key Alg Id pointed to by "cert". If the subjPKAlgId in params + * is set to NULL, no checking is done and the Cert is considered a match. If + * the Cert does not match, an Error pointer is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose subjPKAlgId field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_SubjPKAlgId( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_OID *selPKAlgId = NULL; + PKIX_PL_OID *certPKAlgId = NULL; + PKIX_Boolean equals = PKIX_FALSE; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjPKAlgId"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubjPKAlgId + (params, &selPKAlgId, plContext), + PKIX_COMCERTSELPARAMSGETSUBJPKALGIDFAILED); + + if (selPKAlgId != NULL) { + + PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKeyAlgId + (cert, &certPKAlgId, plContext), + PKIX_CERTGETSUBJECTPUBLICKEYALGIDFAILED); + + if (certPKAlgId != NULL) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED); + } + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)selPKAlgId, + (PKIX_PL_Object *)certPKAlgId, + &equals, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (equals != PKIX_TRUE) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED); + } + } + +cleanup: + + PKIX_DECREF(selPKAlgId); + PKIX_DECREF(certPKAlgId); + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_Match_SubjPubKey + * DESCRIPTION: + * + * Determines whether the key at subjPubKey in "params" matches with the + * Subject Public Key pointed to by "cert". If the subjPubKey in params + * is set to NULL, no checking is done and the Cert is considered a match. If + * the Cert does not match, an Error pointer is returned. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams whose subPubKey field is used. + * Must be non-NULL. + * "cert" + * Address of Cert that is to be matched. Must be non-NULL. + * "pResult" + * Address of PKIX_Boolean that returns the match result. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_Match_SubjPubKey( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_PublicKey *selPK = NULL; + PKIX_PL_PublicKey *certPK = NULL; + PKIX_Boolean equals = PKIX_FALSE; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjPubKey"); + PKIX_NULLCHECK_THREE(params, cert, pResult); + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubjPubKey + (params, &selPK, plContext), + PKIX_COMCERTSELPARAMSGETSUBJPUBKEYFAILED); + + if (selPK != NULL) { + + PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey + (cert, &certPK, plContext), + PKIX_CERTGETSUBJECTPUBLICKEYFAILED); + + if (certPK == NULL) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED); + } + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)selPK, + (PKIX_PL_Object *)certPK, + &equals, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (equals != PKIX_TRUE) { + *pResult = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED); + } + } + +cleanup: + + PKIX_DECREF(selPK); + PKIX_DECREF(certPK); + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_DefaultMatch + * DESCRIPTION: + * + * This default match function determines whether the specified Cert pointed + * to by "cert" matches the criteria of the CertSelector pointed to by + * "selector". If the Cert does not match the CertSelector's + * criteria, an error will be thrown. + * + * This default match function understands how to process the most common + * parameters. Any common parameter that is not set is assumed to be disabled, + * which means this function will select all certificates without regard to + * that particular disabled parameter. For example, if the SerialNumber + * parameter is not set, this function will not filter out any certificate + * based on its serial number. As such, if no parameters are set, all are + * disabled and any certificate will match. If a parameter is disabled, its + * associated PKIX_ComCertSelParams_Get* function returns a default value. + * That value is -1 for PKIX_ComCertSelParams_GetBasicConstraints and + * PKIX_ComCertSelParams_GetVersion, 0 for PKIX_ComCertSelParams_GetKeyUsage, + * and NULL for all other Get functions. + * + * PARAMETERS: + * "selector" + * Address of CertSelector whose MatchCallback logic and parameters are + * to be used. Must be non-NULL. + * "cert" + * Address of Cert that is to be matched using "selector". + * Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertSelector 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_CertSelector_DefaultMatch( + PKIX_CertSelector *selector, + PKIX_PL_Cert *cert, + void *plContext) +{ + PKIX_ComCertSelParams *params = NULL; + PKIX_PL_X500Name *certSubject = NULL; + PKIX_PL_X500Name *selSubject = NULL; + PKIX_PL_X500Name *certIssuer = NULL; + PKIX_PL_X500Name *selIssuer = NULL; + PKIX_PL_BigInt *certSerialNumber = NULL; + PKIX_PL_BigInt *selSerialNumber = NULL; + PKIX_PL_Cert *selCert = NULL; + PKIX_PL_Date *selDate = NULL; + PKIX_UInt32 selVersion = 0xFFFFFFFF; + PKIX_UInt32 certVersion = 0; + PKIX_Boolean result = PKIX_TRUE; + PKIX_Boolean isLeafCert = PKIX_TRUE; + +#ifdef PKIX_BUILDDEBUG + PKIX_PL_String *certString = NULL; + void *certAscii = NULL; + PKIX_UInt32 certAsciiLen; +#endif + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_DefaultMatch"); + PKIX_NULLCHECK_TWO(selector, cert); + + PKIX_INCREF(selector->params); + params = selector->params; + + /* Are we looking for CAs? */ + PKIX_CHECK(PKIX_ComCertSelParams_GetLeafCertFlag + (params, &isLeafCert, plContext), + PKIX_COMCERTSELPARAMSGETLEAFCERTFLAGFAILED); + + if (params == NULL){ + goto cleanup; + } + + PKIX_CHECK(PKIX_ComCertSelParams_GetVersion + (params, &selVersion, plContext), + PKIX_COMCERTSELPARAMSGETVERSIONFAILED); + + if (selVersion != 0xFFFFFFFF){ + PKIX_CHECK(PKIX_PL_Cert_GetVersion + (cert, &certVersion, plContext), + PKIX_CERTGETVERSIONFAILED); + + if (selVersion != certVersion) { + PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTVERSIONFAILED); + } + } + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubject + (params, &selSubject, plContext), + PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); + + if (selSubject){ + PKIX_CHECK(PKIX_PL_Cert_GetSubject + (cert, &certSubject, plContext), + PKIX_CERTGETSUBJECTFAILED); + + if (certSubject){ + PKIX_CHECK(PKIX_PL_X500Name_Match + (selSubject, certSubject, &result, plContext), + PKIX_X500NAMEMATCHFAILED); + + if (result == PKIX_FALSE){ + PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSUBJECTFAILED); + } + } else { /* cert has no subject */ + PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSUBJECTFAILED); + } + } + + PKIX_CHECK(PKIX_ComCertSelParams_GetIssuer + (params, &selIssuer, plContext), + PKIX_COMCERTSELPARAMSGETISSUERFAILED); + + if (selIssuer){ + PKIX_CHECK(PKIX_PL_Cert_GetIssuer + (cert, &certIssuer, plContext), + PKIX_CERTGETISSUERFAILED); + + PKIX_CHECK(PKIX_PL_X500Name_Match + (selIssuer, certIssuer, &result, plContext), + PKIX_X500NAMEMATCHFAILED); + + if (result == PKIX_FALSE){ + PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTISSUERFAILED); + } + } + + PKIX_CHECK(PKIX_ComCertSelParams_GetSerialNumber + (params, &selSerialNumber, plContext), + PKIX_COMCERTSELPARAMSGETSERIALNUMBERFAILED); + + if (selSerialNumber){ + PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber + (cert, &certSerialNumber, plContext), + PKIX_CERTGETSERIALNUMBERFAILED); + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)selSerialNumber, + (PKIX_PL_Object *)certSerialNumber, + &result, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (result == PKIX_FALSE){ + PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSERIALNUMFAILED); + } + } + + PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate + (params, &selCert, plContext), + PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED); + + if (selCert){ + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *) selCert, + (PKIX_PL_Object *) cert, + &result, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (result == PKIX_FALSE){ + PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTOBJECTFAILED); + } + } + + PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid + (params, &selDate, plContext), + PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED); + + if (selDate){ + PKIX_CHECK(PKIX_PL_Cert_CheckValidity + (cert, selDate, plContext), + PKIX_CERTCHECKVALIDITYFAILED); + } + + PKIX_CHECK(pkix_CertSelector_Match_BasicConstraint + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHBASICCONSTRAINTFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_Policies + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHPOLICIESFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_CertificateValid + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHCERTIFICATEVALIDFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_NameConstraints + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHNAMECONSTRAINTSFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_PathToNames + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHPATHTONAMESFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_SubjAltNames + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED); + + /* Check key usage and cert type based on certificate usage. */ + PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, !isLeafCert, + plContext), + PKIX_CERTVERIFYCERTTYPEFAILED); + + /* Next two check are for user supplied additional KU and EKU. */ + PKIX_CHECK(pkix_CertSelector_Match_ExtendedKeyUsage + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_KeyUsage + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHKEYUSAGEFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_SubjKeyId + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHSUBJKEYIDFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_AuthKeyId + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_SubjPKAlgId + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED); + + PKIX_CHECK(pkix_CertSelector_Match_SubjPubKey + (params, cert, &result, plContext), + PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED); + + /* if we reach here, the cert has successfully matched criteria */ + + +#ifdef PKIX_BUILDDEBUG + + PKIX_CHECK(pkix_pl_Cert_ToString_Helper + (cert, PKIX_TRUE, &certString, plContext), + PKIX_CERTTOSTRINGHELPERFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (certString, + PKIX_ESCASCII, + &certAscii, + &certAsciiLen, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_CERTSELECTOR_DEBUG_ARG("Cert Selected:\n%s\n", certAscii); + +#endif + +cleanup: + +#ifdef PKIX_BUILDDEBUG + PKIX_DECREF(certString); + PKIX_FREE(certAscii); +#endif + + PKIX_DECREF(certSubject); + PKIX_DECREF(selSubject); + PKIX_DECREF(certIssuer); + PKIX_DECREF(selIssuer); + PKIX_DECREF(certSerialNumber); + PKIX_DECREF(selSerialNumber); + PKIX_DECREF(selCert); + PKIX_DECREF(selDate); + PKIX_DECREF(params); + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: pkix_CertSelector_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CERTSELECTOR_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_CertSelector_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_RegisterSelf"); + + entry.description = "CertSelector"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_CertSelector); + entry.destructor = pkix_CertSelector_Destroy; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = pkix_CertSelector_Duplicate; + + systemClasses[PKIX_CERTSELECTOR_TYPE] = entry; + + PKIX_RETURN(CERTSELECTOR); +} + +/* --Public-Functions--------------------------------------------- */ + + +/* + * FUNCTION: PKIX_CertSelector_Create (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_CertSelector_Create( + PKIX_CertSelector_MatchCallback callback, + PKIX_PL_Object *certSelectorContext, + PKIX_CertSelector **pSelector, + void *plContext) +{ + PKIX_CertSelector *selector = NULL; + + PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_Create"); + PKIX_NULLCHECK_ONE(pSelector); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTSELECTOR_TYPE, + sizeof (PKIX_CertSelector), + (PKIX_PL_Object **)&selector, + plContext), + PKIX_COULDNOTCREATECERTSELECTOROBJECT); + + /* + * if user specified a particular match callback, we use that one. + * otherwise, we use the default match implementation which + * understands how to process PKIX_ComCertSelParams + */ + + if (callback){ + selector->matchCallback = callback; + } else { + selector->matchCallback = pkix_CertSelector_DefaultMatch; + } + + /* initialize other fields */ + selector->params = NULL; + + PKIX_INCREF(certSelectorContext); + selector->context = certSelectorContext; + + *pSelector = selector; + +cleanup: + + PKIX_RETURN(CERTSELECTOR); + +} + +/* + * FUNCTION: PKIX_CertSelector_GetMatchCallback + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_CertSelector_GetMatchCallback( + PKIX_CertSelector *selector, + PKIX_CertSelector_MatchCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_GetMatchCallback"); + PKIX_NULLCHECK_TWO(selector, pCallback); + + *pCallback = selector->matchCallback; + + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: PKIX_CertSelector_GetCertSelectorContext + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_CertSelector_GetCertSelectorContext( + PKIX_CertSelector *selector, + PKIX_PL_Object **pCertSelectorContext, + void *plContext) +{ + PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_GetCertSelectorContext"); + PKIX_NULLCHECK_TWO(selector, pCertSelectorContext); + + PKIX_INCREF(selector->context); + + *pCertSelectorContext = selector->context; + +cleanup: + PKIX_RETURN(CERTSELECTOR); +} + +/* + * FUNCTION: PKIX_CertSelector_GetCommonCertSelectorParams + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_CertSelector_GetCommonCertSelectorParams( + PKIX_CertSelector *selector, + PKIX_ComCertSelParams **pParams, + void *plContext) +{ + PKIX_ENTER(CERTSELECTOR, + "PKIX_CertSelector_GetCommonCertSelectorParams"); + + PKIX_NULLCHECK_TWO(selector, pParams); + + PKIX_INCREF(selector->params); + *pParams = selector->params; + +cleanup: + PKIX_RETURN(CERTSELECTOR); + +} + +/* + * FUNCTION: PKIX_CertSelector_SetCommonCertSelectorParams + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_CertSelector_SetCommonCertSelectorParams( + PKIX_CertSelector *selector, + PKIX_ComCertSelParams *params, + void *plContext) +{ + PKIX_ENTER(CERTSELECTOR, + "PKIX_CertSelector_SetCommonCertSelectorParams"); + + PKIX_NULLCHECK_ONE(selector); + + PKIX_DECREF(selector->params); + PKIX_INCREF(params); + selector->params = params; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)selector, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(CERTSELECTOR); + +} + +/* + * FUNCTION: pkix_CertSelector_Select + * DESCRIPTION: + * + * This function applies the selector pointed to by "selector" to each Cert, + * in turn, in the List pointed to by "before", and creates a List containing + * all the Certs that matched, or passed the selection process, storing that + * List at "pAfter". If no Certs match, an empty List is stored at "pAfter". + * + * The List returned in "pAfter" is immutable. + * + * PARAMETERS: + * "selector" + * Address of CertSelelector to be applied to the List. Must be non-NULL. + * "before" + * Address of List that is to be filtered. Must be non-NULL. + * "pAfter" + * Address at which resulting List, possibly empty, is 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 CertSelector 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_CertSelector_Select( + PKIX_CertSelector *selector, + PKIX_List *before, + PKIX_List **pAfter, + void *plContext) +{ + PKIX_UInt32 numBefore = 0; + PKIX_UInt32 i = 0; + PKIX_List *filtered = NULL; + PKIX_PL_Cert *candidate = NULL; + + PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_Select"); + PKIX_NULLCHECK_THREE(selector, before, pAfter); + + PKIX_CHECK(PKIX_List_Create(&filtered, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(before, &numBefore, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numBefore; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (before, i, (PKIX_PL_Object **)&candidate, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK_ONLY_FATAL(selector->matchCallback + (selector, candidate, plContext), + PKIX_CERTSELECTORMATCHCALLBACKFAILED); + + if (!(PKIX_ERROR_RECEIVED)) { + + PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem + (filtered, + (PKIX_PL_Object *)candidate, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + pkixTempErrorReceived = PKIX_FALSE; + PKIX_DECREF(candidate); + } + + PKIX_CHECK(PKIX_List_SetImmutable(filtered, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + /* Don't throw away the list if one Cert was bad! */ + pkixTempErrorReceived = PKIX_FALSE; + + *pAfter = filtered; + filtered = NULL; + +cleanup: + + PKIX_DECREF(filtered); + PKIX_DECREF(candidate); + + PKIX_RETURN(CERTSELECTOR); + +} diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h new file mode 100644 index 0000000000..33b648354c --- /dev/null +++ b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h @@ -0,0 +1,41 @@ +/* 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_certselector.h + * + * CertSelector Object Type Definition + * + */ + +#ifndef _PKIX_CERTSELECTOR_H +#define _PKIX_CERTSELECTOR_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_CertSelectorStruct { + PKIX_CertSelector_MatchCallback matchCallback; + PKIX_ComCertSelParams *params; + PKIX_PL_Object *context; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_CertSelector_Select( + PKIX_CertSelector *selector, + PKIX_List *before, + PKIX_List **pAfter, + void *plContext); + +PKIX_Error *pkix_CertSelector_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_CERTSELECTOR_H */ diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c new file mode 100644 index 0000000000..a62f78d231 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c @@ -0,0 +1,1188 @@ +/* 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_comcertselparams.c + * + * ComCertSelParams Object Functions + * + */ + +#include "pkix_comcertselparams.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_ComCertSelParams_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ComCertSelParams_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ComCertSelParams *params = NULL; + + PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a comCertSelParams object */ + PKIX_CHECK(pkix_CheckType + (object, PKIX_COMCERTSELPARAMS_TYPE, plContext), + PKIX_OBJECTNOTCOMCERTSELPARAMS); + + params = (PKIX_ComCertSelParams *)object; + + PKIX_DECREF(params->subject); + PKIX_DECREF(params->policies); + PKIX_DECREF(params->cert); + PKIX_DECREF(params->nameConstraints); + PKIX_DECREF(params->pathToNames); + PKIX_DECREF(params->subjAltNames); + PKIX_DECREF(params->date); + PKIX_DECREF(params->extKeyUsage); + PKIX_DECREF(params->certValid); + PKIX_DECREF(params->issuer); + PKIX_DECREF(params->serialNumber); + PKIX_DECREF(params->authKeyId); + PKIX_DECREF(params->subjKeyId); + PKIX_DECREF(params->subjPubKey); + PKIX_DECREF(params->subjPKAlgId); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: pkix_ComCertSelParams_Duplicate + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ComCertSelParams_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_ComCertSelParams *params = NULL; + PKIX_ComCertSelParams *paramsDuplicate = NULL; + + PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_COMCERTSELPARAMS_TYPE, plContext), + PKIX_OBJECTNOTCOMCERTSELPARAMS); + + params = (PKIX_ComCertSelParams *)object; + + PKIX_CHECK(PKIX_ComCertSelParams_Create(¶msDuplicate, plContext), + PKIX_COMCERTSELPARAMSCREATEFAILED); + + paramsDuplicate->minPathLength = params->minPathLength; + paramsDuplicate->matchAllSubjAltNames = params->matchAllSubjAltNames; + + PKIX_DUPLICATE(params->subject, ¶msDuplicate->subject, plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE(params->policies, ¶msDuplicate->policies, plContext, + PKIX_OBJECTDUPLICATEFAILED); + + if (params->cert){ + PKIX_CHECK(PKIX_PL_Object_Duplicate + ((PKIX_PL_Object *)params->cert, + (PKIX_PL_Object **)¶msDuplicate->cert, + plContext), + PKIX_OBJECTDUPLICATEFAILED); + } + + PKIX_DUPLICATE + (params->nameConstraints, + ¶msDuplicate->nameConstraints, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->pathToNames, + ¶msDuplicate->pathToNames, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->subjAltNames, + ¶msDuplicate->subjAltNames, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + if (params->date){ + PKIX_CHECK(PKIX_PL_Object_Duplicate + ((PKIX_PL_Object *)params->date, + (PKIX_PL_Object **)¶msDuplicate->date, + plContext), + PKIX_OBJECTDUPLICATEFAILED); + } + + paramsDuplicate->keyUsage = params->keyUsage; + + PKIX_DUPLICATE(params->certValid, + ¶msDuplicate->certValid, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE(params->issuer, + ¶msDuplicate->issuer, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE(params->serialNumber, + ¶msDuplicate->serialNumber, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE(params->authKeyId, + ¶msDuplicate->authKeyId, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE(params->subjKeyId, + ¶msDuplicate->subjKeyId, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE(params->subjPubKey, + ¶msDuplicate->subjPubKey, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE(params->subjPKAlgId, + ¶msDuplicate->subjPKAlgId, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + paramsDuplicate->leafCertFlag = params->leafCertFlag; + + *pNewObject = (PKIX_PL_Object *)paramsDuplicate; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(paramsDuplicate); + } + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: pkix_ComCertSelParams_RegisterSelf + * DESCRIPTION: + * Registers PKIX_COMCERTSELPARAMS_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_ComCertSelParams_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry* entry = &systemClasses[PKIX_COMCERTSELPARAMS_TYPE]; + + PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_RegisterSelf"); + + entry->description = "ComCertSelParams"; + entry->typeObjectSize = sizeof(PKIX_ComCertSelParams); + entry->destructor = pkix_ComCertSelParams_Destroy; + entry->duplicateFunction = pkix_ComCertSelParams_Duplicate; + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* --Public-Functions--------------------------------------------- */ + + +/* + * FUNCTION: PKIX_ComCertSelParams_Create (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_Create( + PKIX_ComCertSelParams **pParams, + void *plContext) +{ + PKIX_ComCertSelParams *params = NULL; + + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_Create"); + PKIX_NULLCHECK_ONE(pParams); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_COMCERTSELPARAMS_TYPE, + sizeof (PKIX_ComCertSelParams), + (PKIX_PL_Object **)¶ms, + plContext), + PKIX_COULDNOTCREATECOMMONCERTSELPARAMSOBJECT); + + /* initialize fields */ + params->version = 0xFFFFFFFF; + params->minPathLength = -1; + params->matchAllSubjAltNames = PKIX_TRUE; + params->subject = NULL; + params->policies = NULL; + params->cert = NULL; + params->nameConstraints = NULL; + params->pathToNames = NULL; + params->subjAltNames = NULL; + params->extKeyUsage = NULL; + params->keyUsage = 0; + params->extKeyUsage = NULL; + params->keyUsage = 0; + params->date = NULL; + params->certValid = NULL; + params->issuer = NULL; + params->serialNumber = NULL; + params->authKeyId = NULL; + params->subjKeyId = NULL; + params->subjPubKey = NULL; + params->subjPKAlgId = NULL; + params->leafCertFlag = PKIX_FALSE; + + *pParams = params; + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); + +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubject (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetSubject( + PKIX_ComCertSelParams *params, + PKIX_PL_X500Name **pSubject, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubject"); + PKIX_NULLCHECK_TWO(params, pSubject); + + PKIX_INCREF(params->subject); + + *pSubject = params->subject; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubject (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetSubject( + PKIX_ComCertSelParams *params, + PKIX_PL_X500Name *subject, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubject"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->subject); + + PKIX_INCREF(subject); + + params->subject = subject; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + + +/* + * FUNCTION: PKIX_ComCertSelParams_GetBasicConstraints + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetBasicConstraints( + PKIX_ComCertSelParams *params, + PKIX_Int32 *pMinPathLength, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_GetBasicConstraints"); + PKIX_NULLCHECK_TWO(params, pMinPathLength); + + *pMinPathLength = params->minPathLength; + + PKIX_RETURN(COMCERTSELPARAMS); +} + + +/* + * FUNCTION: PKIX_ComCertSelParams_SetBasicConstraints + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetBasicConstraints( + PKIX_ComCertSelParams *params, + PKIX_Int32 minPathLength, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetBasicConstraints"); + PKIX_NULLCHECK_ONE(params); + + params->minPathLength = minPathLength; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + + +/* + * FUNCTION: PKIX_ComCertSelParams_GetPolicy (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetPolicy( + PKIX_ComCertSelParams *params, + PKIX_List **pPolicy, /* List of PKIX_PL_OID */ + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetPolicy"); + PKIX_NULLCHECK_TWO(params, pPolicy); + + PKIX_INCREF(params->policies); + *pPolicy = params->policies; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetPolicy (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetPolicy( + PKIX_ComCertSelParams *params, + PKIX_List *policy, /* List of PKIX_PL_OID */ + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetPolicy"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->policies); + PKIX_INCREF(policy); + params->policies = policy; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetCertificate + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetCertificate( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert **pCert, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetCertificate"); + PKIX_NULLCHECK_TWO(params, pCert); + + PKIX_INCREF(params->cert); + *pCert = params->cert; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetCertificate + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetCertificate( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetCertificate"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->cert); + PKIX_INCREF(cert); + params->cert = cert; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetCertificateValid + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetCertificateValid( + PKIX_ComCertSelParams *params, + PKIX_PL_Date **pDate, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_GetCertificateValid"); + + PKIX_NULLCHECK_TWO(params, pDate); + + PKIX_INCREF(params->date); + *pDate = params->date; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetCertificateValid + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetCertificateValid( + PKIX_ComCertSelParams *params, + PKIX_PL_Date *date, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetCertificateValid"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->date); + PKIX_INCREF(date); + params->date = date; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetNameConstraints + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetNameConstraints( + PKIX_ComCertSelParams *params, + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_GetNameConstraints"); + PKIX_NULLCHECK_TWO(params, pNameConstraints); + + PKIX_INCREF(params->nameConstraints); + + *pNameConstraints = params->nameConstraints; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetNameConstraints + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetNameConstraints( + PKIX_ComCertSelParams *params, + PKIX_PL_CertNameConstraints *nameConstraints, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetNameConstraints"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->nameConstraints); + PKIX_INCREF(nameConstraints); + params->nameConstraints = nameConstraints; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetPathToNames + * (see comments in pkix_certsel.h) + */PKIX_Error * +PKIX_ComCertSelParams_GetPathToNames( + PKIX_ComCertSelParams *params, + PKIX_List **pNames, /* list of PKIX_PL_GeneralName */ + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetPathToNames"); + PKIX_NULLCHECK_TWO(params, pNames); + + PKIX_INCREF(params->pathToNames); + + *pNames = params->pathToNames; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetPathToNames + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetPathToNames( + PKIX_ComCertSelParams *params, + PKIX_List *names, /* list of PKIX_PL_GeneralName */ + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetPathToNames"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->pathToNames); + PKIX_INCREF(names); + + params->pathToNames = names; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_AddPathToName + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_AddPathToName( + PKIX_ComCertSelParams *params, + PKIX_PL_GeneralName *name, + void *plContext) +{ + PKIX_List *pathToNamesList = NULL; + + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_AddPathToName"); + PKIX_NULLCHECK_ONE(params); + + if (name == NULL) { + goto cleanup; + } + + if (params->pathToNames == NULL) { + /* Create a list for name item */ + PKIX_CHECK(PKIX_List_Create(&pathToNamesList, plContext), + PKIX_LISTCREATEFAILED); + + params->pathToNames = pathToNamesList; + } + + PKIX_CHECK(PKIX_List_AppendItem + (params->pathToNames, (PKIX_PL_Object *)name, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjAltNames + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetSubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_List **pNames, /* list of PKIX_PL_GeneralName */ + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjAltNames"); + PKIX_NULLCHECK_TWO(params, pNames); + + PKIX_INCREF(params->subjAltNames); + + *pNames = params->subjAltNames; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjAltNames + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetSubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_List *names, /* list of PKIX_PL_GeneralName */ + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubjAltNames"); + PKIX_NULLCHECK_TWO(params, names); + + PKIX_DECREF(params->subjAltNames); + PKIX_INCREF(names); + + params->subjAltNames = names; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_AddSubjAltNames + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_AddSubjAltName( + PKIX_ComCertSelParams *params, + PKIX_PL_GeneralName *name, + void *plContext) +{ + PKIX_List *list = NULL; + + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_AddSubjAltName"); + PKIX_NULLCHECK_TWO(params, name); + + if (params->subjAltNames == NULL) { + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + params->subjAltNames = list; + } + + PKIX_CHECK(PKIX_List_AppendItem + (params->subjAltNames, (PKIX_PL_Object *)name, plContext), + PKIX_LISTAPPENDITEMFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS) +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetMatchAllSubjAltNames + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetMatchAllSubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_Boolean *pMatch, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_GetMatchAllSubjAltNames"); + PKIX_NULLCHECK_TWO(params, pMatch); + + *pMatch = params->matchAllSubjAltNames; + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetMatchAllSubjAltNames + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetMatchAllSubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_Boolean match, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetMatchAllSubjAltNames"); + PKIX_NULLCHECK_ONE(params); + + params->matchAllSubjAltNames = match; + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetExtendedKeyUsage + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetExtendedKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_List **pExtKeyUsage, /* list of PKIX_PL_OID */ + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_GetExtendedKeyUsage"); + PKIX_NULLCHECK_TWO(params, pExtKeyUsage); + + PKIX_INCREF(params->extKeyUsage); + *pExtKeyUsage = params->extKeyUsage; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetExtendedKeyUsage + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetExtendedKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_List *extKeyUsage, /* list of PKIX_PL_OID */ + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetExtendedKeyUsage"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->extKeyUsage); + PKIX_INCREF(extKeyUsage); + + params->extKeyUsage = extKeyUsage; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetKeyUsage + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_UInt32 *pKeyUsage, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_GetKeyUsage"); + PKIX_NULLCHECK_TWO(params, pKeyUsage); + + *pKeyUsage = params->keyUsage; + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetKeyUsage + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_UInt32 keyUsage, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetKeyUsage"); + PKIX_NULLCHECK_ONE(params); + + params->keyUsage = keyUsage; + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetIssuer + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetIssuer( + PKIX_ComCertSelParams *params, + PKIX_PL_X500Name **pIssuer, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetIssuer"); + PKIX_NULLCHECK_TWO(params, pIssuer); + + PKIX_INCREF(params->issuer); + *pIssuer = params->issuer; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetIssuer + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetIssuer( + PKIX_ComCertSelParams *params, + PKIX_PL_X500Name *issuer, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetIssuer"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->issuer); + PKIX_INCREF(issuer); + params->issuer = issuer; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSerialNumber + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetSerialNumber( + PKIX_ComCertSelParams *params, + PKIX_PL_BigInt **pSerialNumber, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSerialNumber"); + PKIX_NULLCHECK_TWO(params, pSerialNumber); + + PKIX_INCREF(params->serialNumber); + *pSerialNumber = params->serialNumber; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSerialNumber + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetSerialNumber( + PKIX_ComCertSelParams *params, + PKIX_PL_BigInt *serialNumber, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSerialNumber"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->serialNumber); + PKIX_INCREF(serialNumber); + params->serialNumber = serialNumber; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetVersion + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetVersion( + PKIX_ComCertSelParams *params, + PKIX_UInt32 *pVersion, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetVersion"); + PKIX_NULLCHECK_TWO(params, pVersion); + + *pVersion = params->version; + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetVersion + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetVersion( + PKIX_ComCertSelParams *params, + PKIX_Int32 version, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetVersion"); + PKIX_NULLCHECK_ONE(params); + + params->version = version; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjKeyIdentifier + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetSubjKeyIdentifier( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray **pSubjKeyId, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_GetSubjKeyIdentifier"); + PKIX_NULLCHECK_TWO(params, pSubjKeyId); + + PKIX_INCREF(params->subjKeyId); + + *pSubjKeyId = params->subjKeyId; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjKeyIdentifier + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetSubjKeyIdentifier( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray *subjKeyId, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetSubjKeyIdentifier"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->subjKeyId); + PKIX_INCREF(subjKeyId); + + params->subjKeyId = subjKeyId; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetAuthorityKeyIdentifier + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetAuthorityKeyIdentifier( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray **pAuthKeyId, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_GetAuthorityKeyIdentifier"); + PKIX_NULLCHECK_TWO(params, pAuthKeyId); + + PKIX_INCREF(params->authKeyId); + + *pAuthKeyId = params->authKeyId; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetAuthorityKeyIdentifier + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetAuthorityKeyIdentifier( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray *authKeyId, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetAuthKeyIdentifier"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->authKeyId); + PKIX_INCREF(authKeyId); + + params->authKeyId = authKeyId; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjPubKey + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetSubjPubKey( + PKIX_ComCertSelParams *params, + PKIX_PL_PublicKey **pSubjPubKey, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjPubKey"); + PKIX_NULLCHECK_TWO(params, pSubjPubKey); + + PKIX_INCREF(params->subjPubKey); + + *pSubjPubKey = params->subjPubKey; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjPubKey + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetSubjPubKey( + PKIX_ComCertSelParams *params, + PKIX_PL_PublicKey *subjPubKey, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, + "PKIX_ComCertSelParams_SetSubjPubKey"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->subjPubKey); + PKIX_INCREF(subjPubKey); + + params->subjPubKey = subjPubKey; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjPKAlgId + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_GetSubjPKAlgId( + PKIX_ComCertSelParams *params, + PKIX_PL_OID **pAlgId, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjPKAlgId"); + PKIX_NULLCHECK_TWO(params, pAlgId); + + PKIX_INCREF(params->subjPKAlgId); + + *pAlgId = params->subjPKAlgId; + +cleanup: + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjPKAlgId + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetSubjPKAlgId( + PKIX_ComCertSelParams *params, + PKIX_PL_OID *algId, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubjPKAlgId"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->subjPKAlgId); + PKIX_INCREF(algId); + + params->subjPKAlgId = algId; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_GetLeafCertFlag + * (see comments in pkix_certsel.h) + */ +PKIX_Error* +PKIX_ComCertSelParams_GetLeafCertFlag( + PKIX_ComCertSelParams *params, + PKIX_Boolean *pLeafFlag, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetLeafCertFlag"); + PKIX_NULLCHECK_TWO(params, pLeafFlag); + + *pLeafFlag = params->leafCertFlag; + + PKIX_RETURN(COMCERTSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCertSelParams_SetLeafCertFlag + * (see comments in pkix_certsel.h) + */ +PKIX_Error * +PKIX_ComCertSelParams_SetLeafCertFlag( + PKIX_ComCertSelParams *params, + PKIX_Boolean leafFlag, + void *plContext) +{ + PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetLeafCertFlag"); + PKIX_NULLCHECK_ONE(params); + + params->leafCertFlag = leafFlag; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCERTSELPARAMS); +} diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h new file mode 100644 index 0000000000..935c639f0a --- /dev/null +++ b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h @@ -0,0 +1,57 @@ +/* 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_comcertselparams.h + * + * ComCertSelParams Object Type Definition + * + */ + +#ifndef _PKIX_COMCERTSELPARAMS_H +#define _PKIX_COMCERTSELPARAMS_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * pathToNamesConstraint is Name Constraints generated based on the + * pathToNames. We save a cached copy to save regeneration for each + * check. SubjAltNames also has its cache, since SubjAltNames are + * verified by checker, its cache copy is stored in checkerstate. + */ +struct PKIX_ComCertSelParamsStruct { + PKIX_Int32 version; + PKIX_Int32 minPathLength; + PKIX_Boolean matchAllSubjAltNames; + PKIX_PL_X500Name *subject; + PKIX_List *policies; /* List of PKIX_PL_OID */ + PKIX_PL_Cert *cert; + PKIX_PL_CertNameConstraints *nameConstraints; + PKIX_List *pathToNames; /* List of PKIX_PL_GeneralNames */ + PKIX_List *subjAltNames; /* List of PKIX_PL_GeneralNames */ + PKIX_List *extKeyUsage; /* List of PKIX_PL_OID */ + PKIX_UInt32 keyUsage; + PKIX_PL_Date *date; + PKIX_PL_Date *certValid; + PKIX_PL_X500Name *issuer; + PKIX_PL_BigInt *serialNumber; + PKIX_PL_ByteArray *authKeyId; + PKIX_PL_ByteArray *subjKeyId; + PKIX_PL_PublicKey *subjPubKey; + PKIX_PL_OID *subjPKAlgId; + PKIX_Boolean leafCertFlag; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_ComCertSelParams_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_COMCERTSELPARAMS_H */ diff --git a/security/nss/lib/libpkix/pkix/checker/Makefile b/security/nss/lib/libpkix/pkix/checker/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/Makefile @@ -0,0 +1,46 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/checker/checker.gyp b/security/nss/lib/libpkix/pkix/checker/checker.gyp new file mode 100644 index 0000000000..ac260fc24d --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/checker.gyp @@ -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' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix/checker/exports.gyp b/security/nss/lib/libpkix/pkix/checker/exports.gyp new file mode 100644 index 0000000000..4bd68b39c1 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/exports.gyp @@ -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' + } +} diff --git a/security/nss/lib/libpkix/pkix/checker/manifest.mn b/security/nss/lib/libpkix/pkix/checker/manifest.mn new file mode 100644 index 0000000000..84a372cea9 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/manifest.mn @@ -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/. +CORE_DEPTH = ../../../.. + +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 +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c new file mode 100644 index 0000000000..0e7a87997d --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c @@ -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); +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h new file mode 100644 index 0000000000..7a8b09c379 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c new file mode 100644 index 0000000000..a6ea50d02d --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c @@ -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); + +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h new file mode 100644 index 0000000000..ff6454761e --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c new file mode 100644 index 0000000000..d6f5b6bcc8 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c @@ -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); +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h new file mode 100644 index 0000000000..35f1a47455 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c new file mode 100644 index 0000000000..a2b8437397 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c @@ -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); +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h new file mode 100644 index 0000000000..e542dda20b --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c new file mode 100644 index 0000000000..4f101ee29b --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c @@ -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); + +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h new file mode 100644 index 0000000000..17b5c1bc10 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c new file mode 100644 index 0000000000..873d19cd05 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c @@ -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); + +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h new file mode 100644 index 0000000000..bc413f4561 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c new file mode 100644 index 0000000000..28f21a6c2d --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c @@ -0,0 +1,340 @@ +/* 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_Boolean treatCommonNameAsDNSName = PKIX_FALSE; + PKIX_List *extKeyUsageList = NULL; + PKIX_PL_OID *serverAuthOID = NULL; + + 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); + + if (lastCert) { + /* For the last cert, treat the CN as a DNS name for name + * constraint check. But only if EKU has id-kp-serverAuth + * or EKU is absent. It does not make sense to treat CN + * as a DNS name for an OCSP signing certificate, for example. + */ + PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage + (cert, &extKeyUsageList, plContext), + PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); + if (extKeyUsageList == NULL) { + treatCommonNameAsDNSName = PKIX_TRUE; + } else { + PKIX_CHECK(PKIX_PL_OID_Create + (PKIX_KEY_USAGE_SERVER_AUTH_OID, + &serverAuthOID, + plContext), + PKIX_OIDCREATEFAILED); + + PKIX_CHECK(pkix_List_Contains + (extKeyUsageList, + (PKIX_PL_Object *) serverAuthOID, + &treatCommonNameAsDNSName, + plContext), + PKIX_LISTCONTAINSFAILED); + } + } + + /* 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, treatCommonNameAsDNSName, + 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_DECREF(extKeyUsageList); + PKIX_DECREF(serverAuthOID); + + 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); +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h new file mode 100644 index 0000000000..ac3de346db --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c new file mode 100644 index 0000000000..b6fca9a354 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c @@ -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); +} + + diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h new file mode 100644 index 0000000000..fbec315f96 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c new file mode 100644 index 0000000000..8e40596541 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c @@ -0,0 +1,2783 @@ +/* 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.c + * + * Functions for Policy Checker + * + */ +#include "pkix_policychecker.h" + +/* --Forward declarations----------------------------------------------- */ + +static PKIX_Error * +pkix_PolicyChecker_MakeSingleton( + PKIX_PL_Object *listItem, + PKIX_Boolean immutability, + PKIX_List **pList, + void *plContext); + +/* --Private-PolicyCheckerState-Functions---------------------------------- */ + +/* + * FUNCTION:pkix_PolicyCheckerState_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyCheckerState_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PolicyCheckerState *checkerState = NULL; + + PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYCHECKERSTATE); + + checkerState = (PKIX_PolicyCheckerState *)object; + + PKIX_DECREF(checkerState->certPoliciesExtension); + PKIX_DECREF(checkerState->policyMappingsExtension); + PKIX_DECREF(checkerState->policyConstraintsExtension); + PKIX_DECREF(checkerState->inhibitAnyPolicyExtension); + PKIX_DECREF(checkerState->anyPolicyOID); + PKIX_DECREF(checkerState->validPolicyTree); + PKIX_DECREF(checkerState->userInitialPolicySet); + PKIX_DECREF(checkerState->mappedUserInitialPolicySet); + + checkerState->policyQualifiersRejected = PKIX_FALSE; + checkerState->explicitPolicy = 0; + checkerState->inhibitAnyPolicy = 0; + checkerState->policyMapping = 0; + checkerState->numCerts = 0; + checkerState->certsProcessed = 0; + checkerState->certPoliciesCritical = PKIX_FALSE; + + PKIX_DECREF(checkerState->anyPolicyNodeAtBottom); + PKIX_DECREF(checkerState->newAnyPolicyNode); + PKIX_DECREF(checkerState->mappedPolicyOIDs); + +cleanup: + + PKIX_RETURN(CERTPOLICYCHECKERSTATE); +} + +/* + * FUNCTION: pkix_PolicyCheckerState_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyCheckerState_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pCheckerStateString, + void *plContext) +{ + PKIX_PolicyCheckerState *state = NULL; + PKIX_PL_String *resultString = NULL; + PKIX_PL_String *policiesExtOIDString = NULL; + PKIX_PL_String *policyMapOIDString = NULL; + PKIX_PL_String *policyConstrOIDString = NULL; + PKIX_PL_String *inhAnyPolOIDString = NULL; + PKIX_PL_String *anyPolicyOIDString = NULL; + PKIX_PL_String *validPolicyTreeString = NULL; + PKIX_PL_String *userInitialPolicySetString = NULL; + PKIX_PL_String *mappedUserPolicySetString = NULL; + PKIX_PL_String *mappedPolicyOIDsString = NULL; + PKIX_PL_String *anyAtBottomString = NULL; + PKIX_PL_String *newAnyPolicyString = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *trueString = NULL; + PKIX_PL_String *falseString = NULL; + PKIX_PL_String *nullString = NULL; + PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; + PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; + PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; + PKIX_Boolean initialIsAnyPolicy = PKIX_FALSE; + PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; + PKIX_Boolean certPoliciesCritical = PKIX_FALSE; + char *asciiFormat = + "{\n" + "\tcertPoliciesExtension: \t%s\n" + "\tpolicyMappingsExtension: \t%s\n" + "\tpolicyConstraintsExtension:\t%s\n" + "\tinhibitAnyPolicyExtension:\t%s\n" + "\tanyPolicyOID: \t%s\n" + "\tinitialIsAnyPolicy: \t%s\n" + "\tvalidPolicyTree: \t%s\n" + "\tuserInitialPolicySet: \t%s\n" + "\tmappedUserPolicySet: \t%s\n" + "\tpolicyQualifiersRejected: \t%s\n" + "\tinitialPolMappingInhibit: \t%s\n" + "\tinitialExplicitPolicy: \t%s\n" + "\tinitialAnyPolicyInhibit: \t%s\n" + "\texplicitPolicy: \t%d\n" + "\tinhibitAnyPolicy: \t%d\n" + "\tpolicyMapping: \t%d\n" + "\tnumCerts: \t%d\n" + "\tcertsProcessed: \t%d\n" + "\tanyPolicyNodeAtBottom: \t%s\n" + "\tnewAnyPolicyNode: \t%s\n" + "\tcertPoliciesCritical: \t%s\n" + "\tmappedPolicyOIDs: \t%s\n" + "}"; + + PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_ToString"); + + PKIX_NULLCHECK_TWO(object, pCheckerStateString); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYCHECKERSTATE); + + state = (PKIX_PolicyCheckerState *)object; + PKIX_NULLCHECK_THREE + (state->certPoliciesExtension, + state->policyMappingsExtension, + state->policyConstraintsExtension); + PKIX_NULLCHECK_THREE + (state->inhibitAnyPolicyExtension, + state->anyPolicyOID, + state->userInitialPolicySet); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + /* + * Create TRUE, FALSE, and "NULL" PKIX_PL_Strings. But creating a + * PKIX_PL_String is complicated enough, it's worth checking, for + * each, to make sure the string is needed. + */ + initialPolicyMappingInhibit = state->initialPolicyMappingInhibit; + initialExplicitPolicy = state->initialExplicitPolicy; + initialAnyPolicyInhibit = state->initialAnyPolicyInhibit; + initialIsAnyPolicy = state->initialIsAnyPolicy; + policyQualifiersRejected = state->policyQualifiersRejected; + certPoliciesCritical = state->certPoliciesCritical; + + if (initialPolicyMappingInhibit || initialExplicitPolicy || + initialAnyPolicyInhibit || initialIsAnyPolicy || + policyQualifiersRejected || certPoliciesCritical) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "TRUE", 0, &trueString, plContext), + PKIX_STRINGCREATEFAILED); + } + if (!initialPolicyMappingInhibit || !initialExplicitPolicy || + !initialAnyPolicyInhibit || !initialIsAnyPolicy || + !policyQualifiersRejected || !certPoliciesCritical) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "FALSE", 0, &falseString, plContext), + PKIX_STRINGCREATEFAILED); + } + if (!(state->anyPolicyNodeAtBottom) || !(state->newAnyPolicyNode)) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "(null)", 0, &nullString, plContext), + PKIX_STRINGCREATEFAILED); + } + + PKIX_TOSTRING + (state->certPoliciesExtension, &policiesExtOIDString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->policyMappingsExtension, + &policyMapOIDString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->policyConstraintsExtension, + &policyConstrOIDString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->inhibitAnyPolicyExtension, + &inhAnyPolOIDString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING(state->anyPolicyOID, &anyPolicyOIDString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING(state->validPolicyTree, &validPolicyTreeString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->userInitialPolicySet, + &userInitialPolicySetString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->mappedUserInitialPolicySet, + &mappedUserPolicySetString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + if (state->anyPolicyNodeAtBottom) { + PKIX_CHECK(pkix_SinglePolicyNode_ToString + (state->anyPolicyNodeAtBottom, + &anyAtBottomString, + plContext), + PKIX_SINGLEPOLICYNODETOSTRINGFAILED); + } else { + PKIX_INCREF(nullString); + anyAtBottomString = nullString; + } + + if (state->newAnyPolicyNode) { + PKIX_CHECK(pkix_SinglePolicyNode_ToString + (state->newAnyPolicyNode, + &newAnyPolicyString, + plContext), + PKIX_SINGLEPOLICYNODETOSTRINGFAILED); + } else { + PKIX_INCREF(nullString); + newAnyPolicyString = nullString; + } + + PKIX_TOSTRING + (state->mappedPolicyOIDs, + &mappedPolicyOIDsString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + formatString, + policiesExtOIDString, + policyMapOIDString, + policyConstrOIDString, + inhAnyPolOIDString, + anyPolicyOIDString, + initialIsAnyPolicy?trueString:falseString, + validPolicyTreeString, + userInitialPolicySetString, + mappedUserPolicySetString, + policyQualifiersRejected?trueString:falseString, + initialPolicyMappingInhibit?trueString:falseString, + initialExplicitPolicy?trueString:falseString, + initialAnyPolicyInhibit?trueString:falseString, + state->explicitPolicy, + state->inhibitAnyPolicy, + state->policyMapping, + state->numCerts, + state->certsProcessed, + anyAtBottomString, + newAnyPolicyString, + certPoliciesCritical?trueString:falseString, + mappedPolicyOIDsString), + PKIX_SPRINTFFAILED); + + *pCheckerStateString = resultString; + +cleanup: + PKIX_DECREF(policiesExtOIDString); + PKIX_DECREF(policyMapOIDString); + PKIX_DECREF(policyConstrOIDString); + PKIX_DECREF(inhAnyPolOIDString); + PKIX_DECREF(anyPolicyOIDString); + PKIX_DECREF(validPolicyTreeString); + PKIX_DECREF(userInitialPolicySetString); + PKIX_DECREF(mappedUserPolicySetString); + PKIX_DECREF(anyAtBottomString); + PKIX_DECREF(newAnyPolicyString); + PKIX_DECREF(mappedPolicyOIDsString); + PKIX_DECREF(formatString); + PKIX_DECREF(trueString); + PKIX_DECREF(falseString); + PKIX_DECREF(nullString); + + PKIX_RETURN(CERTPOLICYCHECKERSTATE); +} + +/* + * FUNCTION: pkix_PolicyCheckerState_RegisterSelf + * DESCRIPTION: + * + * Registers PKIX_POLICYCHECKERSTATE_TYPE and its related functions + * with systemClasses[] + * + * PARAMETERS: + * "plContext" + * Platform-specific context pointer. + * 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_PolicyCheckerState_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER + (CERTPOLICYCHECKERSTATE, + "pkix_PolicyCheckerState_RegisterSelf"); + + entry.description = "PolicyCheckerState"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PolicyCheckerState); + entry.destructor = pkix_PolicyCheckerState_Destroy; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = pkix_PolicyCheckerState_ToString; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_CERTPOLICYCHECKERSTATE_TYPE] = entry; + + PKIX_RETURN(CERTPOLICYCHECKERSTATE); +} + +/* + * FUNCTION:pkix_PolicyCheckerState_Create + * DESCRIPTION: + * + * Creates a PolicyCheckerState Object, using the List pointed to + * by "initialPolicies" for the user-initial-policy-set, the Boolean value + * of "policyQualifiersRejected" for the policyQualifiersRejected parameter, + * the Boolean value of "initialPolicyMappingInhibit" for the + * inhibitPolicyMappings parameter, the Boolean value of + * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the + * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy + * parameter, and the UInt32 value of "numCerts" as the number of + * certificates in the chain; and stores the Object at "pCheckerState". + * + * PARAMETERS: + * "initialPolicies" + * Address of List of OIDs comprising the user-initial-policy-set; the List + * may be empty, but must be non-NULL + * "policyQualifiersRejected" + * Boolean value of the policyQualifiersRejected parameter + * "initialPolicyMappingInhibit" + * Boolean value of the inhibitPolicyMappings parameter + * "initialExplicitPolicy" + * Boolean value of the initialExplicitPolicy parameter + * "initialAnyPolicyInhibit" + * Boolean value of the inhibitAnyPolicy parameter + * "numCerts" + * Number of certificates in the chain to be validated + * "pCheckerState" + * Address where PolicyCheckerState 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 CertPolicyCheckerState Error if the functions fails in a + * non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyCheckerState_Create( + PKIX_List *initialPolicies, + PKIX_Boolean policyQualifiersRejected, + PKIX_Boolean initialPolicyMappingInhibit, + PKIX_Boolean initialExplicitPolicy, + PKIX_Boolean initialAnyPolicyInhibit, + PKIX_UInt32 numCerts, + PKIX_PolicyCheckerState **pCheckerState, + void *plContext) +{ + PKIX_PolicyCheckerState *checkerState = NULL; + PKIX_PolicyNode *policyNode = NULL; + PKIX_List *anyPolicyList = NULL; + PKIX_Boolean initialPoliciesIsEmpty = PKIX_FALSE; + + PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Create"); + PKIX_NULLCHECK_TWO(initialPolicies, pCheckerState); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTPOLICYCHECKERSTATE_TYPE, + sizeof (PKIX_PolicyCheckerState), + (PKIX_PL_Object **)&checkerState, + plContext), + PKIX_COULDNOTCREATEPOLICYCHECKERSTATEOBJECT); + + /* Create constant PKIX_PL_OIDs: */ + + PKIX_CHECK(PKIX_PL_OID_Create + (PKIX_CERTIFICATEPOLICIES_OID, + &(checkerState->certPoliciesExtension), + plContext), + PKIX_OIDCREATEFAILED); + + PKIX_CHECK(PKIX_PL_OID_Create + (PKIX_POLICYMAPPINGS_OID, + &(checkerState->policyMappingsExtension), + plContext), + PKIX_OIDCREATEFAILED); + + PKIX_CHECK(PKIX_PL_OID_Create + (PKIX_POLICYCONSTRAINTS_OID, + &(checkerState->policyConstraintsExtension), + plContext), + PKIX_OIDCREATEFAILED); + + PKIX_CHECK(PKIX_PL_OID_Create + (PKIX_INHIBITANYPOLICY_OID, + &(checkerState->inhibitAnyPolicyExtension), + plContext), + PKIX_OIDCREATEFAILED); + + PKIX_CHECK(PKIX_PL_OID_Create + (PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID, + &(checkerState->anyPolicyOID), + plContext), + PKIX_OIDCREATEFAILED); + + /* Create an initial policy set from argument supplied */ + PKIX_INCREF(initialPolicies); + checkerState->userInitialPolicySet = initialPolicies; + PKIX_INCREF(initialPolicies); + checkerState->mappedUserInitialPolicySet = initialPolicies; + + PKIX_CHECK(PKIX_List_IsEmpty + (initialPolicies, + &initialPoliciesIsEmpty, + plContext), + PKIX_LISTISEMPTYFAILED); + if (initialPoliciesIsEmpty) { + checkerState->initialIsAnyPolicy = PKIX_TRUE; + } else { + PKIX_CHECK(pkix_List_Contains + (initialPolicies, + (PKIX_PL_Object *)(checkerState->anyPolicyOID), + &(checkerState->initialIsAnyPolicy), + plContext), + PKIX_LISTCONTAINSFAILED); + } + + checkerState->policyQualifiersRejected = + policyQualifiersRejected; + checkerState->initialExplicitPolicy = initialExplicitPolicy; + checkerState->explicitPolicy = + (initialExplicitPolicy? 0: numCerts + 1); + checkerState->initialAnyPolicyInhibit = initialAnyPolicyInhibit; + checkerState->inhibitAnyPolicy = + (initialAnyPolicyInhibit? 0: numCerts + 1); + checkerState->initialPolicyMappingInhibit = initialPolicyMappingInhibit; + checkerState->policyMapping = + (initialPolicyMappingInhibit? 0: numCerts + 1); + ; + checkerState->numCerts = numCerts; + checkerState->certsProcessed = 0; + checkerState->certPoliciesCritical = PKIX_FALSE; + + /* Create a valid_policy_tree as in RFC3280 6.1.2(a) */ + PKIX_CHECK(pkix_PolicyChecker_MakeSingleton + ((PKIX_PL_Object *)(checkerState->anyPolicyOID), + PKIX_TRUE, + &anyPolicyList, + plContext), + PKIX_POLICYCHECKERMAKESINGLETONFAILED); + + PKIX_CHECK(pkix_PolicyNode_Create + (checkerState->anyPolicyOID, /* validPolicy */ + NULL, /* qualifier set */ + PKIX_FALSE, /* criticality */ + anyPolicyList, /* expectedPolicySet */ + &policyNode, + plContext), + PKIX_POLICYNODECREATEFAILED); + checkerState->validPolicyTree = policyNode; + + /* + * Since the initial validPolicyTree specifies + * ANY_POLICY, begin with a pointer to the root node. + */ + PKIX_INCREF(policyNode); + checkerState->anyPolicyNodeAtBottom = policyNode; + + checkerState->newAnyPolicyNode = NULL; + + checkerState->mappedPolicyOIDs = NULL; + + *pCheckerState = checkerState; + checkerState = NULL; + +cleanup: + + PKIX_DECREF(checkerState); + + PKIX_DECREF(anyPolicyList); + + PKIX_RETURN(CERTPOLICYCHECKERSTATE); +} + +/* --Private-PolicyChecker-Functions--------------------------------------- */ + +/* + * FUNCTION: pkix_PolicyChecker_MapContains + * DESCRIPTION: + * + * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to + * determine whether the OID pointed to by "policy" is among the + * issuerDomainPolicies or subjectDomainPolicies of "certPolicyMaps", and + * stores the result in "pFound". + * + * This function is intended to allow an efficient check that the proscription + * against anyPolicy being mapped, described in RFC3280 Section 6.1.4(a), is + * not violated. + * + * PARAMETERS: + * "certPolicyMaps" + * Address of List of CertPolicyMaps to be searched. May be empty, but + * must be non-NULL + * "policy" + * Address of OID to be checked for. Must be non-NULL + * "pFound" + * Address where the result of the search 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_PolicyChecker_MapContains( + PKIX_List *certPolicyMaps, + PKIX_PL_OID *policy, + PKIX_Boolean *pFound, + void *plContext) +{ + PKIX_PL_CertPolicyMap *map = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + PKIX_Boolean match = PKIX_FALSE; + PKIX_PL_OID *issuerDomainPolicy = NULL; + PKIX_PL_OID *subjectDomainPolicy = NULL; + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MapContains"); + PKIX_NULLCHECK_THREE(certPolicyMaps, policy, pFound); + + PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (index = 0; (!match) && (index < numEntries); index++) { + PKIX_CHECK(PKIX_List_GetItem + (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_NULLCHECK_ONE(map); + + PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy + (map, &issuerDomainPolicy, plContext), + PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); + + PKIX_EQUALS + (policy, issuerDomainPolicy, &match, plContext, + PKIX_OBJECTEQUALSFAILED); + + if (!match) { + PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy + (map, &subjectDomainPolicy, plContext), + PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED); + + PKIX_EQUALS + (policy, subjectDomainPolicy, &match, plContext, + PKIX_OBJECTEQUALSFAILED); + } + + PKIX_DECREF(map); + PKIX_DECREF(issuerDomainPolicy); + PKIX_DECREF(subjectDomainPolicy); + } + + *pFound = match; + +cleanup: + + PKIX_DECREF(map); + PKIX_DECREF(issuerDomainPolicy); + PKIX_DECREF(subjectDomainPolicy); + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_MapGetSubjectDomainPolicies + * DESCRIPTION: + * + * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to create + * a list of all SubjectDomainPolicies for which the IssuerDomainPolicy is the + * policy pointed to by "policy", and stores the result in + * "pSubjectDomainPolicies". + * + * If the List of CertPolicyMaps provided in "certPolicyMaps" is NULL, the + * resulting List will be NULL. If there are CertPolicyMaps, but none that + * include "policy" as an IssuerDomainPolicy, the returned List pointer will + * be NULL. Otherwise, the returned List will contain the SubjectDomainPolicies + * of all CertPolicyMaps for which "policy" is the IssuerDomainPolicy. If a + * List is returned it will be immutable. + * + * PARAMETERS: + * "certPolicyMaps" + * Address of List of CertPolicyMaps to be searched. May be empty or NULL. + * "policy" + * Address of OID to be checked for. Must be non-NULL + * "pSubjectDomainPolicies" + * Address where the result of the search 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_PolicyChecker_MapGetSubjectDomainPolicies( + PKIX_List *certPolicyMaps, + PKIX_PL_OID *policy, + PKIX_List **pSubjectDomainPolicies, + void *plContext) +{ + PKIX_PL_CertPolicyMap *map = NULL; + PKIX_List *subjectList = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + PKIX_Boolean match = PKIX_FALSE; + PKIX_PL_OID *issuerDomainPolicy = NULL; + PKIX_PL_OID *subjectDomainPolicy = NULL; + + PKIX_ENTER + (CERTCHAINCHECKER, + "pkix_PolicyChecker_MapGetSubjectDomainPolicies"); + PKIX_NULLCHECK_TWO(policy, pSubjectDomainPolicies); + + if (certPolicyMaps) { + PKIX_CHECK(PKIX_List_GetLength + (certPolicyMaps, + &numEntries, + plContext), + PKIX_LISTGETLENGTHFAILED); + } + + for (index = 0; index < numEntries; index++) { + PKIX_CHECK(PKIX_List_GetItem + (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_NULLCHECK_ONE(map); + + PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy + (map, &issuerDomainPolicy, plContext), + PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); + + PKIX_EQUALS + (policy, issuerDomainPolicy, &match, plContext, + PKIX_OBJECTEQUALSFAILED); + + if (match) { + if (!subjectList) { + PKIX_CHECK(PKIX_List_Create(&subjectList, plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy + (map, &subjectDomainPolicy, plContext), + PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (subjectList, + (PKIX_PL_Object *)subjectDomainPolicy, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + PKIX_DECREF(map); + PKIX_DECREF(issuerDomainPolicy); + PKIX_DECREF(subjectDomainPolicy); + } + + if (subjectList) { + PKIX_CHECK(PKIX_List_SetImmutable(subjectList, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + } + + *pSubjectDomainPolicies = subjectList; + +cleanup: + + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(subjectList); + } + + PKIX_DECREF(map); + PKIX_DECREF(issuerDomainPolicy); + PKIX_DECREF(subjectDomainPolicy); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_MapGetMappedPolicies + * DESCRIPTION: + * + * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps" to create a + * List of all IssuerDomainPolicies, and stores the result in + * "pMappedPolicies". + * + * The caller may not rely on the IssuerDomainPolicies to be in any particular + * order. IssuerDomainPolicies that appear in more than one CertPolicyMap will + * only appear once in "pMappedPolicies". If "certPolicyMaps" is empty the + * result will be an empty List. The created List is mutable. + * + * PARAMETERS: + * "certPolicyMaps" + * Address of List of CertPolicyMaps to be searched. May be empty, but + * must be non-NULL. + * "pMappedPolicies" + * Address where the result 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 functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_PolicyChecker_MapGetMappedPolicies( + PKIX_List *certPolicyMaps, + PKIX_List **pMappedPolicies, + void *plContext) +{ + PKIX_PL_CertPolicyMap *map = NULL; + PKIX_List *mappedList = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + PKIX_Boolean isContained = PKIX_FALSE; + PKIX_PL_OID *issuerDomainPolicy = NULL; + + PKIX_ENTER + (CERTCHAINCHECKER, "pkix_PolicyChecker_MapGetMappedPolicies"); + PKIX_NULLCHECK_TWO(certPolicyMaps, pMappedPolicies); + + PKIX_CHECK(PKIX_List_Create(&mappedList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (index = 0; index < numEntries; index++) { + PKIX_CHECK(PKIX_List_GetItem + (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_NULLCHECK_ONE(map); + + PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy + (map, &issuerDomainPolicy, plContext), + PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); + + PKIX_CHECK(pkix_List_Contains + (mappedList, + (PKIX_PL_Object *)issuerDomainPolicy, + &isContained, + plContext), + PKIX_LISTCONTAINSFAILED); + + if (isContained == PKIX_FALSE) { + PKIX_CHECK(PKIX_List_AppendItem + (mappedList, + (PKIX_PL_Object *)issuerDomainPolicy, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + PKIX_DECREF(map); + PKIX_DECREF(issuerDomainPolicy); + } + + *pMappedPolicies = mappedList; + +cleanup: + + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(mappedList); + } + + PKIX_DECREF(map); + PKIX_DECREF(issuerDomainPolicy); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_MakeMutableCopy + * DESCRIPTION: + * + * Creates a mutable copy of the List pointed to by "list", which may or may + * not be immutable, and stores the address at "pMutableCopy". + * + * PARAMETERS: + * "list" + * Address of List to be copied. Must be non-NULL. + * "pMutableCopy" + * Address where mutable copy 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 functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_MakeMutableCopy( + PKIX_List *list, + PKIX_List **pMutableCopy, + void *plContext) +{ + PKIX_List *newList = NULL; + PKIX_UInt32 listLen = 0; + PKIX_UInt32 listIx = 0; + PKIX_PL_Object *object = NULL; + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeMutableCopy"); + PKIX_NULLCHECK_TWO(list, pMutableCopy); + + PKIX_CHECK(PKIX_List_Create(&newList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(list, &listLen, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (listIx = 0; listIx < listLen; listIx++) { + + PKIX_CHECK(PKIX_List_GetItem(list, listIx, &object, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem(newList, object, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(object); + } + + *pMutableCopy = newList; + newList = NULL; + +cleanup: + PKIX_DECREF(newList); + PKIX_DECREF(object); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_MakeSingleton + * DESCRIPTION: + * + * Creates a new List containing the Object pointed to by "listItem", using + * the Boolean value of "immutability" to determine whether to set the List + * immutable, and stores the address at "pList". + * + * PARAMETERS: + * "listItem" + * Address of Object to be inserted into the new List. Must be non-NULL. + * "immutability" + * Boolean value indicating whether new List is to be immutable + * "pList" + * Address where List 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 functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_MakeSingleton( + PKIX_PL_Object *listItem, + PKIX_Boolean immutability, + PKIX_List **pList, + void *plContext) +{ + PKIX_List *newList = NULL; + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeSingleton"); + PKIX_NULLCHECK_TWO(listItem, pList); + + PKIX_CHECK(PKIX_List_Create(&newList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (newList, (PKIX_PL_Object *)listItem, plContext), + PKIX_LISTAPPENDITEMFAILED); + + if (immutability) { + PKIX_CHECK(PKIX_List_SetImmutable(newList, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + } + + *pList = newList; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(newList); + } + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_Spawn + * DESCRIPTION: + * + * Creates a new childNode for the parent pointed to by "parent", using + * the OID pointed to by "policyOID", the List of CertPolicyQualifiers + * pointed to by "qualifiers", the List of OIDs pointed to by + * "subjectDomainPolicies", and the PolicyCheckerState pointed to by + * "state". The new node will be added to "parent". + * + * The validPolicy of the new node is set from the OID pointed to by + * "policyOID". The policy qualifiers for the new node is set from the + * List of qualifiers pointed to by "qualifiers", and may be NULL or + * empty if the argument provided was NULL or empty. The criticality is + * set according to the criticality obtained from the PolicyCheckerState. + * If "subjectDomainPolicies" is NULL, the expectedPolicySet of the + * child is set to contain the same policy as the validPolicy. If + * "subjectDomainPolicies" is not NULL, it is used as the value for + * the expectedPolicySet. + * + * The PolicyCheckerState also contains a constant, anyPolicy, which is + * compared to "policyOID". If they match, the address of the childNode + * is saved in the state's newAnyPolicyNode. + * + * PARAMETERS: + * "parent" + * Address of PolicyNode to which the child will be linked. Must be + * non-NULL. + * "policyOID" + * Address of OID of the new child's validPolicy and also, if + * subjectDomainPolicies is NULL, of the new child's expectedPolicySet. + * Must be non-NULL. + * "qualifiers" + * Address of List of CertPolicyQualifiers. May be NULL or empty. + * "subjectDomainPolicies" + * Address of List of OIDs indicating the policies to which "policy" is + * mapped. May be empty or NULL. + * "state" + * Address of the current PKIX_PolicyCheckerState. 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 CertChainChecker Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_Spawn( + PKIX_PolicyNode *parent, + PKIX_PL_OID *policyOID, + PKIX_List *qualifiers, /* CertPolicyQualifiers */ + PKIX_List *subjectDomainPolicies, + PKIX_PolicyCheckerState *state, + void *plContext) +{ + PKIX_List *expectedSet = NULL; /* OIDs */ + PKIX_PolicyNode *childNode = NULL; + PKIX_Boolean match = PKIX_FALSE; + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Spawn"); + PKIX_NULLCHECK_THREE(policyOID, parent, state); + + if (subjectDomainPolicies) { + + PKIX_INCREF(subjectDomainPolicies); + expectedSet = subjectDomainPolicies; + + } else { + /* Create the child's ExpectedPolicy Set */ + PKIX_CHECK(pkix_PolicyChecker_MakeSingleton + ((PKIX_PL_Object *)policyOID, + PKIX_TRUE, /* make expectedPolicySet immutable */ + &expectedSet, + plContext), + PKIX_POLICYCHECKERMAKESINGLETONFAILED); + } + + PKIX_CHECK(pkix_PolicyNode_Create + (policyOID, + qualifiers, + state->certPoliciesCritical, + expectedSet, + &childNode, + plContext), + PKIX_POLICYNODECREATEFAILED); + + /* + * If we had a non-empty mapping, we know the new node could not + * have been created with a validPolicy of anyPolicy. Otherwise, + * check whether we just created a new node with anyPolicy, because + * in that case we want to save the child pointer in newAnyPolicyNode. + */ + if (!subjectDomainPolicies) { + PKIX_EQUALS(policyOID, state->anyPolicyOID, &match, plContext, + PKIX_OBJECTEQUALSFAILED); + + if (match) { + PKIX_DECREF(state->newAnyPolicyNode); + PKIX_INCREF(childNode); + state->newAnyPolicyNode = childNode; + } + } + + PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, childNode, plContext), + PKIX_POLICYNODEADDTOPARENTFAILED); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + PKIX_DECREF(childNode); + PKIX_DECREF(expectedSet); + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_CheckPolicyRecursive + * DESCRIPTION: + * + * Performs policy processing for the policy whose OID is pointed to by + * "policyOID" and whose List of CertPolicyQualifiers is pointed to by + * "policyQualifiers", using the List of policy OIDs pointed to by + * "subjectDomainPolicies" and the PolicyNode pointed to by "currentNode", + * in accordance with the current PolicyCheckerState pointed to by "state", + * and setting "pChildNodeCreated" to TRUE if a new childNode is created. + * Note: "pChildNodeCreated" is not set to FALSE if no childNode is created. + * The intent of the design is that the caller can set a variable to FALSE + * initially, prior to a recursive set of calls. At the end, the variable + * can be tested to see whether *any* of the calls created a child node. + * + * If the currentNode is not at the bottom of the tree, this function + * calls itself recursively for each child of currentNode. At the bottom of + * the tree, it creates new child nodes as appropriate. This function will + * never be called with policy = anyPolicy. + * + * This function implements the processing described in RFC3280 + * Section 6.1.3(d)(1)(i). + * + * PARAMETERS: + * "policyOID" + * Address of OID of the policy to be checked for. Must be non-NULL. + * "policyQualifiers" + * Address of List of CertPolicyQualifiers of the policy to be checked for. + * May be empty or NULL. + * "subjectDomainPolicies" + * Address of List of OIDs indicating the policies to which "policy" is + * mapped. May be empty or NULL. + * "currentNode" + * Address of PolicyNode whose descendants will be checked, if not at the + * bottom of the tree; or whose expectedPolicySet will be compared to + * "policy", if at the bottom. Must be non-NULL. + * "state" + * Address of PolicyCheckerState of the current PolicyChecker. Must be + * non-NULL. + * "pChildNodeCreated" + * Address of the Boolean that will be set TRUE if this function + * creates a child node. 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 CertChainChecker Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_CheckPolicyRecursive( + PKIX_PL_OID *policyOID, + PKIX_List *policyQualifiers, + PKIX_List *subjectDomainPolicies, + PKIX_PolicyNode *currentNode, + PKIX_PolicyCheckerState *state, + PKIX_Boolean *pChildNodeCreated, + void *plContext) +{ + PKIX_UInt32 depth = 0; + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 childIx = 0; + PKIX_Boolean isIncluded = PKIX_FALSE; + PKIX_List *children = NULL; /* PolicyNodes */ + PKIX_PolicyNode *childNode = NULL; + PKIX_List *expectedPolicies = NULL; /* OIDs */ + + PKIX_ENTER + (CERTCHAINCHECKER, + "pkix_PolicyChecker_CheckPolicyRecursive"); + PKIX_NULLCHECK_FOUR(policyOID, currentNode, state, pChildNodeCreated); + + /* if not at the bottom of the tree */ + PKIX_CHECK(PKIX_PolicyNode_GetDepth + (currentNode, &depth, plContext), + PKIX_POLICYNODEGETDEPTHFAILED); + + if (depth < (state->certsProcessed)) { + PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable + (currentNode, &children, plContext), + PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); + + if (children) { + PKIX_CHECK(PKIX_List_GetLength + (children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + for (childIx = 0; childIx < numChildren; childIx++) { + + PKIX_CHECK(PKIX_List_GetItem + (children, + childIx, + (PKIX_PL_Object **)&childNode, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive + (policyOID, + policyQualifiers, + subjectDomainPolicies, + childNode, + state, + pChildNodeCreated, + plContext), + PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED); + + PKIX_DECREF(childNode); + } + } else { /* if at the bottom of the tree */ + + /* Check whether policy is in this node's expectedPolicySet */ + PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies + (currentNode, &expectedPolicies, plContext), + PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED); + + PKIX_NULLCHECK_ONE(expectedPolicies); + + PKIX_CHECK(pkix_List_Contains + (expectedPolicies, + (PKIX_PL_Object *)policyOID, + &isIncluded, + plContext), + PKIX_LISTCONTAINSFAILED); + + if (isIncluded) { + PKIX_CHECK(pkix_PolicyChecker_Spawn + (currentNode, + policyOID, + policyQualifiers, + subjectDomainPolicies, + state, + plContext), + PKIX_POLICYCHECKERSPAWNFAILED); + + *pChildNodeCreated = PKIX_TRUE; + } + } + +cleanup: + + PKIX_DECREF(children); + PKIX_DECREF(childNode); + PKIX_DECREF(expectedPolicies); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_CheckPolicy + * DESCRIPTION: + * + * Performs the non-recursive portion of the policy processing for the policy + * whose OID is pointed to by "policyOID" and whose List of + * CertPolicyQualifiers is pointed to by "policyQualifiers", for the + * Certificate pointed to by "cert" with the List of CertPolicyMaps pointed + * to by "maps", in accordance with the current PolicyCheckerState pointed + * to by "state". + * + * This function implements the processing described in RFC3280 + * Section 6.1.3(d)(1)(i). + * + * PARAMETERS: + * "policyOID" + * Address of OID of the policy to be checked for. Must be non-NULL. + * "policyQualifiers" + * Address of List of CertPolicyQualifiers of the policy to be checked for. + * May be empty or NULL. + * "cert" + * Address of the current certificate. Must be non-NULL. + * "maps" + * Address of List of CertPolicyMaps for the current certificate + * "state" + * Address of PolicyCheckerState of the current PolicyChecker. 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 CertChainChecker Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_CheckPolicy( + PKIX_PL_OID *policyOID, + PKIX_List *policyQualifiers, + PKIX_PL_Cert *cert, + PKIX_List *maps, + PKIX_PolicyCheckerState *state, + void *plContext) +{ + PKIX_Boolean childNodeCreated = PKIX_FALSE; + PKIX_Boolean okToSpawn = PKIX_FALSE; + PKIX_Boolean found = PKIX_FALSE; + PKIX_List *subjectDomainPolicies = NULL; + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckPolicy"); + PKIX_NULLCHECK_THREE(policyOID, cert, state); + + /* + * If this is not the last certificate, get the set of + * subjectDomainPolicies that "policy" maps to, according to the + * current cert's policy mapping extension. That set will be NULL + * if the current cert does not have a policy mapping extension, + * or if the current policy is not mapped. + */ + if (state->certsProcessed != (state->numCerts - 1)) { + PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies + (maps, policyOID, &subjectDomainPolicies, plContext), + PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); + } + + /* + * Section 6.1.4(b)(2) tells us that if policyMapping is zero, we + * will have to delete any nodes created with validPolicies equal to + * policies that appear as issuerDomainPolicies in a policy mapping + * extension. Let's avoid creating any such nodes. + */ + if ((state->policyMapping) == 0) { + if (subjectDomainPolicies) { + goto cleanup; + } + } + + PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive + (policyOID, + policyQualifiers, + subjectDomainPolicies, + state->validPolicyTree, + state, + &childNodeCreated, + plContext), + PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED); + + if (!childNodeCreated) { + /* + * Section 6.1.3(d)(1)(ii) + * There was no match. If there was a node at + * depth i-1 with valid policy anyPolicy, + * generate a node subordinate to that. + * + * But that means this created node would be in + * the valid-policy-node-set, and will be + * pruned in 6.1.5(g)(iii)(2) unless it is in + * the user-initial-policy-set or the user- + * initial-policy-set is {anyPolicy}. So check, + * and don't create it if it will be pruned. + */ + if (state->anyPolicyNodeAtBottom) { + if (state->initialIsAnyPolicy) { + okToSpawn = PKIX_TRUE; + } else { + PKIX_CHECK(pkix_List_Contains + (state->mappedUserInitialPolicySet, + (PKIX_PL_Object *)policyOID, + &okToSpawn, + plContext), + PKIX_LISTCONTAINSFAILED); + } + if (okToSpawn) { + PKIX_CHECK(pkix_PolicyChecker_Spawn + (state->anyPolicyNodeAtBottom, + policyOID, + policyQualifiers, + subjectDomainPolicies, + state, + plContext), + PKIX_POLICYCHECKERSPAWNFAILED); + childNodeCreated = PKIX_TRUE; + } + } + } + + if (childNodeCreated) { + /* + * If this policy had qualifiers, and the certificate policies + * extension was marked critical, and the user cannot deal with + * policy qualifiers, throw an error. + */ + if (policyQualifiers && + state->certPoliciesCritical && + state->policyQualifiersRejected) { + PKIX_ERROR + (PKIX_QUALIFIERSINCRITICALCERTIFICATEPOLICYEXTENSION); + } + /* + * If the policy we just propagated was in the list of mapped + * policies, remove it from the list. That list is used, at the + * end, to determine policies that have not been propagated. + */ + if (state->mappedPolicyOIDs) { + PKIX_CHECK(pkix_List_Contains + (state->mappedPolicyOIDs, + (PKIX_PL_Object *)policyOID, + &found, + plContext), + PKIX_LISTCONTAINSFAILED); + if (found) { + PKIX_CHECK(pkix_List_Remove + (state->mappedPolicyOIDs, + (PKIX_PL_Object *)policyOID, + plContext), + PKIX_LISTREMOVEFAILED); + } + } + } + +cleanup: + + PKIX_DECREF(subjectDomainPolicies); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_CheckAny + * DESCRIPTION: + * Performs the creation of PolicyNodes, for the PolicyNode pointed to by + * "currentNode" and PolicyNodes subordinate to it, using the List of + * qualifiers pointed to by "qualsOfAny", in accordance with the current + * certificate's PolicyMaps pointed to by "policyMaps" and the current + * PolicyCheckerState pointed to by "state". + * + * If the currentNode is not just above the bottom of the validPolicyTree, this + * function calls itself recursively for each child of currentNode. At the + * level just above the bottom, for each policy in the currentNode's + * expectedPolicySet not already present in a child node, it creates a new + * child node. The validPolicy of the child created, and its expectedPolicySet, + * will be the policy from the currentNode's expectedPolicySet. The policy + * qualifiers will be the qualifiers from the current certificate's anyPolicy, + * the "qualsOfAny" parameter. If the currentNode's expectedSet includes + * anyPolicy, a childNode will be created with a policy of anyPolicy. This is + * the only way such a node can be created. + * + * This function is called only when anyPolicy is one of the current + * certificate's policies. This function implements the processing described + * in RFC3280 Section 6.1.3(d)(2). + * + * PARAMETERS: + * "currentNode" + * Address of PolicyNode whose descendants will be checked, if not at the + * bottom of the tree; or whose expectedPolicySet will be compared to those + * in "alreadyPresent", if at the bottom. Must be non-NULL. + * "qualsOfAny" + * Address of List of qualifiers of the anyPolicy in the current + * certificate. May be empty or NULL. + * "policyMaps" + * Address of the List of PolicyMaps of the current certificate. May be + * empty or NULL. + * "state" + * Address of the current state of the PKIX_PolicyChecker. + * 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 CertChainChecker Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_CheckAny( + PKIX_PolicyNode *currentNode, + PKIX_List *qualsOfAny, /* CertPolicyQualifiers */ + PKIX_List *policyMaps, /* CertPolicyMaps */ + PKIX_PolicyCheckerState *state, + void *plContext) +{ + PKIX_UInt32 depth = 0; + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 childIx = 0; + PKIX_UInt32 numPolicies = 0; + PKIX_UInt32 polx = 0; + PKIX_Boolean isIncluded = PKIX_FALSE; + PKIX_List *children = NULL; /* PolicyNodes */ + PKIX_PolicyNode *childNode = NULL; + PKIX_List *expectedPolicies = NULL; /* OIDs */ + PKIX_PL_OID *policyOID = NULL; + PKIX_PL_OID *childPolicy = NULL; + PKIX_List *subjectDomainPolicies = NULL; /* OIDs */ + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckAny"); + PKIX_NULLCHECK_TWO(currentNode, state); + + PKIX_CHECK(PKIX_PolicyNode_GetDepth + (currentNode, &depth, plContext), + PKIX_POLICYNODEGETDEPTHFAILED); + + PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable + (currentNode, &children, plContext), + PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); + + if (children) { + PKIX_CHECK(PKIX_List_GetLength + (children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + if (depth < (state->certsProcessed)) { + for (childIx = 0; childIx < numChildren; childIx++) { + + PKIX_CHECK(PKIX_List_GetItem + (children, + childIx, + (PKIX_PL_Object **)&childNode, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_NULLCHECK_ONE(childNode); + PKIX_CHECK(pkix_PolicyChecker_CheckAny + (childNode, + qualsOfAny, + policyMaps, + state, + plContext), + PKIX_POLICYCHECKERCHECKANYFAILED); + + PKIX_DECREF(childNode); + } + } else { /* if at the bottom of the tree */ + + PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies + (currentNode, &expectedPolicies, plContext), + PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED); + + /* Expected Policy Set is not allowed to be NULL */ + PKIX_NULLCHECK_ONE(expectedPolicies); + + PKIX_CHECK(PKIX_List_GetLength + (expectedPolicies, &numPolicies, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (polx = 0; polx < numPolicies; polx++) { + PKIX_CHECK(PKIX_List_GetItem + (expectedPolicies, + polx, + (PKIX_PL_Object **)&policyOID, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_NULLCHECK_ONE(policyOID); + + isIncluded = PKIX_FALSE; + + for (childIx = 0; + (!isIncluded && (childIx < numChildren)); + childIx++) { + + PKIX_CHECK(PKIX_List_GetItem + (children, + childIx, + (PKIX_PL_Object **)&childNode, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_NULLCHECK_ONE(childNode); + + PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy + (childNode, &childPolicy, plContext), + PKIX_POLICYNODEGETVALIDPOLICYFAILED); + + PKIX_NULLCHECK_ONE(childPolicy); + + PKIX_EQUALS(policyOID, childPolicy, &isIncluded, plContext, + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(childNode); + PKIX_DECREF(childPolicy); + } + + if (!isIncluded) { + if (policyMaps) { + PKIX_CHECK + (pkix_PolicyChecker_MapGetSubjectDomainPolicies + (policyMaps, + policyOID, + &subjectDomainPolicies, + plContext), + PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); + } + PKIX_CHECK(pkix_PolicyChecker_Spawn + (currentNode, + policyOID, + qualsOfAny, + subjectDomainPolicies, + state, + plContext), + PKIX_POLICYCHECKERSPAWNFAILED); + PKIX_DECREF(subjectDomainPolicies); + } + + PKIX_DECREF(policyOID); + } + } + +cleanup: + + PKIX_DECREF(children); + PKIX_DECREF(childNode); + PKIX_DECREF(expectedPolicies); + PKIX_DECREF(policyOID); + PKIX_DECREF(childPolicy); + PKIX_DECREF(subjectDomainPolicies); + + PKIX_RETURN(CERTCHAINCHECKER); + +} + +/* + * FUNCTION: pkix_PolicyChecker_CalculateIntersection + * DESCRIPTION: + * + * Processes the PolicyNode pointed to by "currentNode", and its descendants, + * using the PolicyCheckerState pointed to by "state", using the List at + * the address pointed to by "nominees" the OIDs of policies that are in the + * user-initial-policy-set but are not represented among the nodes at the + * bottom of the tree, and storing at "pShouldBePruned" the value TRUE if + * currentNode is childless at the end of this processing, FALSE if it has + * children or is at the bottom of the tree. + * + * When this function is called at the top level, "nominees" should be the List + * of all policies in the user-initial-policy-set. Policies that are + * represented in the valid-policy-node-set are removed from this List. As a + * result when nodes are created according to 6.1.5.(g)(iii)(3)(b), a node will + * be created for each policy remaining in this List. + * + * This function implements the calculation of the intersection of the + * validPolicyTree with the user-initial-policy-set, as described in + * RFC 3280 6.1.5(g)(iii). + * + * PARAMETERS: + * "currentNode" + * Address of PolicyNode whose descendants will be processed as described. + * Must be non-NULL. + * "state" + * Address of the current state of the PKIX_PolicyChecker. Must be non-NULL + * "nominees" + * Address of List of the OIDs for which nodes should be created to replace + * anyPolicy nodes. Must be non-NULL but may be empty. + * "pShouldBePruned" + * Address where Boolean return value, set to TRUE if this PolicyNode + * should be deleted, is 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 CertChainChecker Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_CalculateIntersection( + PKIX_PolicyNode *currentNode, + PKIX_PolicyCheckerState *state, + PKIX_List *nominees, /* OIDs */ + PKIX_Boolean *pShouldBePruned, + void *plContext) +{ + PKIX_Boolean currentPolicyIsAny = PKIX_FALSE; + PKIX_Boolean parentPolicyIsAny = PKIX_FALSE; + PKIX_Boolean currentPolicyIsValid = PKIX_FALSE; + PKIX_Boolean shouldBePruned = PKIX_FALSE; + PKIX_Boolean priorCriticality = PKIX_FALSE; + PKIX_UInt32 depth = 0; + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 childIndex = 0; + PKIX_UInt32 numNominees = 0; + PKIX_UInt32 polIx = 0; + PKIX_PL_OID *currentPolicy = NULL; + PKIX_PL_OID *parentPolicy = NULL; + PKIX_PL_OID *substPolicy = NULL; + PKIX_PolicyNode *parent = NULL; + PKIX_PolicyNode *child = NULL; + PKIX_List *children = NULL; /* PolicyNodes */ + PKIX_List *policyQualifiers = NULL; + + PKIX_ENTER + (CERTCHAINCHECKER, + "pkix_PolicyChecker_CalculateIntersection"); + + /* + * We call this function if the valid_policy_tree is not NULL and + * the user-initial-policy-set is not any-policy. + */ + if (!state->validPolicyTree || state->initialIsAnyPolicy) { + PKIX_ERROR(PKIX_PRECONDITIONFAILED); + } + + PKIX_NULLCHECK_FOUR(currentNode, state, nominees, pShouldBePruned); + + PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy + (currentNode, ¤tPolicy, plContext), + PKIX_POLICYNODEGETVALIDPOLICYFAILED); + + PKIX_NULLCHECK_TWO(state->anyPolicyOID, currentPolicy); + + PKIX_EQUALS + (state->anyPolicyOID, + currentPolicy, + ¤tPolicyIsAny, + plContext, + PKIX_OBJECTEQUALSFAILED); + + PKIX_CHECK(PKIX_PolicyNode_GetParent(currentNode, &parent, plContext), + PKIX_POLICYNODEGETPARENTFAILED); + + if (currentPolicyIsAny == PKIX_FALSE) { + + /* + * If we are at the top of the tree, or if our + * parent's validPolicy is anyPolicy, we are in + * the valid policy node set. + */ + if (parent) { + PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy + (parent, &parentPolicy, plContext), + PKIX_POLICYNODEGETVALIDPOLICYFAILED); + + PKIX_NULLCHECK_ONE(parentPolicy); + + PKIX_EQUALS + (state->anyPolicyOID, + parentPolicy, + &parentPolicyIsAny, + plContext, + PKIX_OBJECTEQUALSFAILED); + } + + /* + * Section 6.1.5(g)(iii)(2) + * If this node's policy is not in the user-initial-policy-set, + * it is not in the intersection. Prune it. + */ + if (!parent || parentPolicyIsAny) { + PKIX_CHECK(pkix_List_Contains + (state->userInitialPolicySet, + (PKIX_PL_Object *)currentPolicy, + ¤tPolicyIsValid, + plContext), + PKIX_LISTCONTAINSFAILED); + if (!currentPolicyIsValid) { + *pShouldBePruned = PKIX_TRUE; + goto cleanup; + } + + /* + * If this node's policy is in the user-initial-policy- + * set, it will propagate that policy into the next + * level of the tree. Remove the policy from the list + * of policies that an anyPolicy will spawn. + */ + PKIX_CHECK(pkix_List_Remove + (nominees, + (PKIX_PL_Object *)currentPolicy, + plContext), + PKIX_LISTREMOVEFAILED); + } + } + + + /* Are we at the bottom of the tree? */ + + PKIX_CHECK(PKIX_PolicyNode_GetDepth + (currentNode, &depth, plContext), + PKIX_POLICYNODEGETDEPTHFAILED); + + if (depth == (state->numCerts)) { + /* + * Section 6.1.5(g)(iii)(3) + * Replace anyPolicy nodes... + */ + if (currentPolicyIsAny == PKIX_TRUE) { + + /* replace this node */ + + PKIX_CHECK(PKIX_List_GetLength + (nominees, &numNominees, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numNominees) { + + PKIX_CHECK(PKIX_PolicyNode_GetPolicyQualifiers + (currentNode, + &policyQualifiers, + plContext), + PKIX_POLICYNODEGETPOLICYQUALIFIERSFAILED); + + PKIX_CHECK(PKIX_PolicyNode_IsCritical + (currentNode, &priorCriticality, plContext), + PKIX_POLICYNODEISCRITICALFAILED); + } + + PKIX_NULLCHECK_ONE(parent); + + for (polIx = 0; polIx < numNominees; polIx++) { + + PKIX_CHECK(PKIX_List_GetItem + (nominees, + polIx, + (PKIX_PL_Object **)&substPolicy, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyChecker_Spawn + (parent, + substPolicy, + policyQualifiers, + NULL, + state, + plContext), + PKIX_POLICYCHECKERSPAWNFAILED); + + PKIX_DECREF(substPolicy); + + } + /* remove currentNode from parent */ + *pShouldBePruned = PKIX_TRUE; + /* + * We can get away with augmenting the parent's List + * of children because we started at the end and went + * toward the beginning. New nodes are added at the end. + */ + } + } else { + /* + * Section 6.1.5(g)(iii)(4) + * Prune any childless nodes above the bottom level + */ + PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable + (currentNode, &children, plContext), + PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); + + /* CurrentNode should have been pruned if childless. */ + PKIX_NULLCHECK_ONE(children); + + PKIX_CHECK(PKIX_List_GetLength + (children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (childIndex = numChildren; childIndex > 0; childIndex--) { + + PKIX_CHECK(PKIX_List_GetItem + (children, + childIndex - 1, + (PKIX_PL_Object **)&child, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection + (child, state, nominees, &shouldBePruned, plContext), + PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED); + + if (PKIX_TRUE == shouldBePruned) { + + PKIX_CHECK(PKIX_List_DeleteItem + (children, childIndex - 1, plContext), + PKIX_LISTDELETEITEMFAILED); + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + } + + PKIX_DECREF(child); + } + + PKIX_CHECK(PKIX_List_GetLength + (children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numChildren == 0) { + *pShouldBePruned = PKIX_TRUE; + } + } +cleanup: + PKIX_DECREF(currentPolicy); + PKIX_DECREF(parentPolicy); + PKIX_DECREF(substPolicy); + PKIX_DECREF(parent); + PKIX_DECREF(child); + PKIX_DECREF(children); + PKIX_DECREF(policyQualifiers); + + PKIX_RETURN(CERTCHAINCHECKER); + +} + +/* + * FUNCTION: pkix_PolicyChecker_PolicyMapProcessing + * DESCRIPTION: + * + * Performs the processing of Policies in the List of CertPolicyMaps pointed + * to by "policyMaps", using and updating the PolicyCheckerState pointed to by + * "state". + * + * This function implements the policyMap processing described in RFC3280 + * Section 6.1.4(b)(1), after certificate i has been processed, in preparation + * for certificate i+1. Section references are to that document. + * + * PARAMETERS: + * "policyMaps" + * Address of the List of CertPolicyMaps presented by certificate i. + * Must be non-NULL. + * "certPoliciesIncludeAny" + * Boolean value which is PKIX_TRUE if the current certificate asserts + * anyPolicy, PKIX_FALSE otherwise. + * "qualsOfAny" + * Address of List of qualifiers of the anyPolicy in the current + * certificate. May be empty or NULL. + * "state" + * Address of the current state of the PKIX_PolicyChecker. + * 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 CertChainChecker Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_PolicyMapProcessing( + PKIX_List *policyMaps, /* CertPolicyMaps */ + PKIX_Boolean certPoliciesIncludeAny, + PKIX_List *qualsOfAny, + PKIX_PolicyCheckerState *state, + void *plContext) +{ + PKIX_UInt32 numPolicies = 0; + PKIX_UInt32 polX = 0; + PKIX_PL_OID *policyOID = NULL; + PKIX_List *newMappedPolicies = NULL; /* OIDs */ + PKIX_List *subjectDomainPolicies = NULL; /* OIDs */ + + PKIX_ENTER + (CERTCHAINCHECKER, + "pkix_PolicyChecker_PolicyMapProcessing"); + PKIX_NULLCHECK_THREE + (policyMaps, + state, + state->mappedUserInitialPolicySet); + + /* + * For each policy in mappedUserInitialPolicySet, if it is not mapped, + * append it to new policySet; if it is mapped, append its + * subjectDomainPolicies to new policySet. When done, this new + * policySet will replace mappedUserInitialPolicySet. + */ + PKIX_CHECK(PKIX_List_Create + (&newMappedPolicies, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength + (state->mappedUserInitialPolicySet, + &numPolicies, + plContext), + PKIX_LISTGETLENGTHFAILED); + + for (polX = 0; polX < numPolicies; polX++) { + + PKIX_CHECK(PKIX_List_GetItem + (state->mappedUserInitialPolicySet, + polX, + (PKIX_PL_Object **)&policyOID, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies + (policyMaps, + policyOID, + &subjectDomainPolicies, + plContext), + PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); + + if (subjectDomainPolicies) { + + PKIX_CHECK(pkix_List_AppendUnique + (newMappedPolicies, + subjectDomainPolicies, + plContext), + PKIX_LISTAPPENDUNIQUEFAILED); + + PKIX_DECREF(subjectDomainPolicies); + + } else { + PKIX_CHECK(PKIX_List_AppendItem + (newMappedPolicies, + (PKIX_PL_Object *)policyOID, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + PKIX_DECREF(policyOID); + } + + /* + * For each policy ID-P remaining in mappedPolicyOIDs, it has not been + * propagated to the bottom of the tree (depth i). If policyMapping + * is greater than zero and this cert contains anyPolicy and the tree + * contains an anyPolicy node at depth i-1, then we must create a node + * with validPolicy ID-P, the policy qualifiers of anyPolicy in + * this certificate, and expectedPolicySet the subjectDomainPolicies + * that ID-P maps to. We also then add those subjectDomainPolicies to + * the list of policies that will be accepted in the next certificate, + * the mappedUserInitialPolicySet. + */ + + if ((state->policyMapping > 0) && (certPoliciesIncludeAny) && + (state->anyPolicyNodeAtBottom) && (state->mappedPolicyOIDs)) { + + PKIX_CHECK(PKIX_List_GetLength + (state->mappedPolicyOIDs, + &numPolicies, + plContext), + PKIX_LISTGETLENGTHFAILED); + + for (polX = 0; polX < numPolicies; polX++) { + + PKIX_CHECK(PKIX_List_GetItem + (state->mappedPolicyOIDs, + polX, + (PKIX_PL_Object **)&policyOID, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies + (policyMaps, + policyOID, + &subjectDomainPolicies, + plContext), + PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); + + PKIX_CHECK(pkix_PolicyChecker_Spawn + (state->anyPolicyNodeAtBottom, + policyOID, + qualsOfAny, + subjectDomainPolicies, + state, + plContext), + PKIX_POLICYCHECKERSPAWNFAILED); + + PKIX_CHECK(pkix_List_AppendUnique + (newMappedPolicies, + subjectDomainPolicies, + plContext), + PKIX_LISTAPPENDUNIQUEFAILED); + + PKIX_DECREF(subjectDomainPolicies); + PKIX_DECREF(policyOID); + } + } + + PKIX_CHECK(PKIX_List_SetImmutable(newMappedPolicies, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + PKIX_DECREF(state->mappedUserInitialPolicySet); + PKIX_INCREF(newMappedPolicies); + + state->mappedUserInitialPolicySet = newMappedPolicies; + +cleanup: + + PKIX_DECREF(policyOID); + PKIX_DECREF(newMappedPolicies); + PKIX_DECREF(subjectDomainPolicies); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_WrapUpProcessing + * DESCRIPTION: + * + * Performs the wrap-up processing for the Cert pointed to by "cert", + * using and updating the PolicyCheckerState pointed to by "state". + * + * This function implements the wrap-up processing described in RFC3280 + * Section 6.1.5, after the final certificate has been processed. Section + * references in the comments are to that document. + * + * PARAMETERS: + * "cert" + * Address of the current (presumably the end entity) certificate. + * Must be non-NULL. + * "state" + * Address of the current state of the PKIX_PolicyChecker. + * 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 CertChainChecker Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +static PKIX_Error * +pkix_PolicyChecker_WrapUpProcessing( + PKIX_PL_Cert *cert, + PKIX_PolicyCheckerState *state, + void *plContext) +{ + PKIX_Int32 explicitPolicySkipCerts = 0; + PKIX_Boolean isSelfIssued = PKIX_FALSE; + PKIX_Boolean shouldBePruned = PKIX_FALSE; + PKIX_List *nominees = NULL; /* OIDs */ +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG + PKIX_PL_String *stateString = NULL; + char *stateAscii = NULL; + PKIX_UInt32 length; +#endif + + PKIX_ENTER + (CERTCHAINCHECKER, + "pkix_PolicyChecker_WrapUpProcessing"); + PKIX_NULLCHECK_THREE(cert, state, state->userInitialPolicySet); + +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)state, &stateString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stateString, + PKIX_ESCASCII, + (void **)&stateAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_DEBUG_ARG("%s\n", stateAscii); + + PKIX_FREE(stateAscii); + PKIX_DECREF(stateString); +#endif + + /* Section 6.1.5(a) ... */ + PKIX_CHECK(pkix_IsCertSelfIssued + (cert, &isSelfIssued, plContext), + PKIX_ISCERTSELFISSUEDFAILED); + + if (!isSelfIssued) { + if (state->explicitPolicy > 0) { + + state->explicitPolicy--; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + } + } + + /* Section 6.1.5(b) ... */ + PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy + (cert, &explicitPolicySkipCerts, plContext), + PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); + + if (explicitPolicySkipCerts == 0) { + state->explicitPolicy = 0; + } + + /* Section 6.1.5(g)(i) ... */ + + if (!(state->validPolicyTree)) { + goto cleanup; + } + + /* Section 6.1.5(g)(ii) ... */ + + if (state->initialIsAnyPolicy) { + goto cleanup; + } + + /* + * Section 6.1.5(g)(iii) ... + * Create a list of policies which could be substituted for anyPolicy. + * Start with a (mutable) copy of user-initial-policy-set. + */ + PKIX_CHECK(pkix_PolicyChecker_MakeMutableCopy + (state->userInitialPolicySet, &nominees, plContext), + PKIX_POLICYCHECKERMAKEMUTABLECOPYFAILED); + + PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection + (state->validPolicyTree, /* node at top of tree */ + state, + nominees, + &shouldBePruned, + plContext), + PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED); + + if (PKIX_TRUE == shouldBePruned) { + PKIX_DECREF(state->validPolicyTree); + } + + if (state->validPolicyTree) { + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state->validPolicyTree, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG + if (state->validPolicyTree) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)state, &stateString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stateString, + PKIX_ESCASCII, + (void **)&stateAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_DEBUG_ARG + ("After CalculateIntersection:\n%s\n", stateAscii); + + PKIX_FREE(stateAscii); + PKIX_DECREF(stateString); + } else { + PKIX_DEBUG("validPolicyTree is NULL\n"); + } +#endif + + /* Section 6.1.5(g)(iii)(4) ... */ + + if (state->validPolicyTree) { + + PKIX_CHECK(pkix_PolicyNode_Prune + (state->validPolicyTree, + state->numCerts, + &shouldBePruned, + plContext), + PKIX_POLICYNODEPRUNEFAILED); + + if (shouldBePruned) { + PKIX_DECREF(state->validPolicyTree); + } + } + + if (state->validPolicyTree) { + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state->validPolicyTree, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)state, &stateString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stateString, + PKIX_ESCASCII, + (void **)&stateAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + PKIX_DEBUG_ARG("%s\n", stateAscii); + + PKIX_FREE(stateAscii); + PKIX_DECREF(stateString); +#endif + +cleanup: + + PKIX_DECREF(nominees); + + PKIX_RETURN(CERTCHAINCHECKER); +} + + +/* + * FUNCTION: pkix_PolicyChecker_Check + * (see comments in pkix_checker.h for PKIX_CertChainChecker_CheckCallback) + * + * Labels referring to sections, such as "Section 6.1.3(d)", refer to + * sections of RFC3280, Section 6.1.3 Basic Certificate Processing. + * + * If a non-fatal error occurs, it is unlikely that policy processing can + * continue. But it is still possible that chain validation could succeed if + * policy processing is non-critical. So if this function receives a non-fatal + * error from a lower level routine, it aborts policy processing by setting + * the validPolicyTree to NULL and tries to continue. + * + */ +static PKIX_Error * +pkix_PolicyChecker_Check( + PKIX_CertChainChecker *checker, + PKIX_PL_Cert *cert, + PKIX_List *unresolvedCriticals, /* OIDs */ + void **pNBIOContext, + void *plContext) +{ + PKIX_UInt32 numPolicies = 0; + PKIX_UInt32 polX = 0; + PKIX_Boolean result = PKIX_FALSE; + PKIX_Int32 inhibitMappingSkipCerts = 0; + PKIX_Int32 explicitPolicySkipCerts = 0; + PKIX_Int32 inhibitAnyPolicySkipCerts = 0; + PKIX_Boolean shouldBePruned = PKIX_FALSE; + PKIX_Boolean isSelfIssued = PKIX_FALSE; + PKIX_Boolean certPoliciesIncludeAny = PKIX_FALSE; + PKIX_Boolean doAnyPolicyProcessing = PKIX_FALSE; + + PKIX_PolicyCheckerState *state = NULL; + PKIX_List *certPolicyInfos = NULL; /* CertPolicyInfos */ + PKIX_PL_CertPolicyInfo *policy = NULL; + PKIX_PL_OID *policyOID = NULL; + PKIX_List *qualsOfAny = NULL; /* CertPolicyQualifiers */ + PKIX_List *policyQualifiers = NULL; /* CertPolicyQualifiers */ + PKIX_List *policyMaps = NULL; /* CertPolicyMaps */ + PKIX_List *mappedPolicies = NULL; /* OIDs */ + PKIX_Error *subroutineErr = NULL; +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG + PKIX_PL_String *stateString = NULL; + char *stateAscii = NULL; + PKIX_PL_String *certString = NULL; + char *certAscii = NULL; + PKIX_UInt32 length; +#endif + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Check"); + PKIX_NULLCHECK_FOUR(checker, cert, unresolvedCriticals, pNBIOContext); + + *pNBIOContext = NULL; /* we never block on pending I/O */ + + PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState + (checker, (PKIX_PL_Object **)&state, plContext), + PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); + + PKIX_NULLCHECK_TWO(state, state->certPoliciesExtension); + +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)state, &stateString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stateString, + PKIX_ESCASCII, + (void **)&stateAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + PKIX_DEBUG_ARG("On entry %s\n", stateAscii); + PKIX_FREE(stateAscii); + PKIX_DECREF(stateString); +#endif + + /* + * Section 6.1.4(a) + * If this is not the last certificate, and if + * policyMapping extension is present, check that no + * issuerDomainPolicy or subjectDomainPolicy is equal to the + * special policy anyPolicy. + */ + if (state->certsProcessed != (state->numCerts - 1)) { + PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings + (cert, &policyMaps, plContext), + PKIX_CERTGETPOLICYMAPPINGSFAILED); + } + + if (policyMaps) { + + PKIX_CHECK(pkix_PolicyChecker_MapContains + (policyMaps, state->anyPolicyOID, &result, plContext), + PKIX_POLICYCHECKERMAPCONTAINSFAILED); + + if (result) { + PKIX_ERROR(PKIX_INVALIDPOLICYMAPPINGINCLUDESANYPOLICY); + } + + PKIX_CHECK(pkix_PolicyChecker_MapGetMappedPolicies + (policyMaps, &mappedPolicies, plContext), + PKIX_POLICYCHECKERMAPGETMAPPEDPOLICIESFAILED); + + PKIX_DECREF(state->mappedPolicyOIDs); + PKIX_INCREF(mappedPolicies); + state->mappedPolicyOIDs = mappedPolicies; + } + + /* Section 6.1.3(d) */ + if (state->validPolicyTree) { + + PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation + (cert, &certPolicyInfos, plContext), + PKIX_CERTGETPOLICYINFORMATIONFAILED); + + if (certPolicyInfos) { + PKIX_CHECK(PKIX_List_GetLength + (certPolicyInfos, &numPolicies, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + if (numPolicies > 0) { + + PKIX_CHECK(PKIX_PL_Cert_AreCertPoliciesCritical + (cert, &(state->certPoliciesCritical), plContext), + PKIX_CERTARECERTPOLICIESCRITICALFAILED); + + /* Section 6.1.3(d)(1) For each policy not equal to anyPolicy */ + for (polX = 0; polX < numPolicies; polX++) { + + PKIX_CHECK(PKIX_List_GetItem + (certPolicyInfos, + polX, + (PKIX_PL_Object **)&policy, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId + (policy, &policyOID, plContext), + PKIX_CERTPOLICYINFOGETPOLICYIDFAILED); + + PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolQualifiers + (policy, &policyQualifiers, plContext), + PKIX_CERTPOLICYINFOGETPOLQUALIFIERSFAILED); + + PKIX_EQUALS + (state->anyPolicyOID, + policyOID, + &result, + plContext, + PKIX_OIDEQUALFAILED); + + if (result == PKIX_FALSE) { + + /* Section 6.1.3(d)(1)(i) */ + subroutineErr = pkix_PolicyChecker_CheckPolicy + (policyOID, + policyQualifiers, + cert, + policyMaps, + state, + plContext); + if (subroutineErr) { + goto subrErrorCleanup; + } + + } else { + /* + * No descent (yet) for anyPolicy, but we will need + * the policyQualifiers for anyPolicy in 6.1.3(d)(2) + */ + PKIX_DECREF(qualsOfAny); + PKIX_INCREF(policyQualifiers); + qualsOfAny = policyQualifiers; + certPoliciesIncludeAny = PKIX_TRUE; + } + PKIX_DECREF(policy); + PKIX_DECREF(policyOID); + PKIX_DECREF(policyQualifiers); + } + + /* Section 6.1.3(d)(2) */ + if (certPoliciesIncludeAny == PKIX_TRUE) { + if (state->inhibitAnyPolicy > 0) { + doAnyPolicyProcessing = PKIX_TRUE; + } else { + /* We haven't yet counted the current cert */ + if (((state->certsProcessed) + 1) < + (state->numCerts)) { + + PKIX_CHECK(pkix_IsCertSelfIssued + (cert, + &doAnyPolicyProcessing, + plContext), + PKIX_ISCERTSELFISSUEDFAILED); + } + } + if (doAnyPolicyProcessing) { + subroutineErr = pkix_PolicyChecker_CheckAny + (state->validPolicyTree, + qualsOfAny, + policyMaps, + state, + plContext); + if (subroutineErr) { + goto subrErrorCleanup; + } + } + } + + /* Section 6.1.3(d)(3) */ + if (state->validPolicyTree) { + subroutineErr = pkix_PolicyNode_Prune + (state->validPolicyTree, + state->certsProcessed + 1, + &shouldBePruned, + plContext); + if (subroutineErr) { + goto subrErrorCleanup; + } + if (shouldBePruned) { + PKIX_DECREF(state->validPolicyTree); + PKIX_DECREF(state->anyPolicyNodeAtBottom); + } + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + } else { + /* Section 6.1.3(e) */ + PKIX_DECREF(state->validPolicyTree); + PKIX_DECREF(state->anyPolicyNodeAtBottom); + PKIX_DECREF(state->newAnyPolicyNode); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + } + } + + /* Section 6.1.3(f) */ + if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) { + PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); + } + + /* + * Remove Policy OIDs from list of unresolved critical + * extensions, if present. + */ + PKIX_CHECK(pkix_List_Remove + (unresolvedCriticals, + (PKIX_PL_Object *)state->certPoliciesExtension, + plContext), + PKIX_LISTREMOVEFAILED); + + PKIX_CHECK(pkix_List_Remove + (unresolvedCriticals, + (PKIX_PL_Object *)state->policyMappingsExtension, + plContext), + PKIX_LISTREMOVEFAILED); + + PKIX_CHECK(pkix_List_Remove + (unresolvedCriticals, + (PKIX_PL_Object *)state->policyConstraintsExtension, + plContext), + PKIX_LISTREMOVEFAILED); + + PKIX_CHECK(pkix_List_Remove + (unresolvedCriticals, + (PKIX_PL_Object *)state->inhibitAnyPolicyExtension, + plContext), + PKIX_LISTREMOVEFAILED); + + state->certsProcessed++; + + /* If this was not the last certificate, do next-cert preparation */ + if (state->certsProcessed != state->numCerts) { + + if (policyMaps) { + subroutineErr = pkix_PolicyChecker_PolicyMapProcessing + (policyMaps, + certPoliciesIncludeAny, + qualsOfAny, + state, + plContext); + if (subroutineErr) { + goto subrErrorCleanup; + } + } + + /* update anyPolicyNodeAtBottom pointer */ + PKIX_DECREF(state->anyPolicyNodeAtBottom); + state->anyPolicyNodeAtBottom = state->newAnyPolicyNode; + state->newAnyPolicyNode = NULL; + + /* Section 6.1.4(h) */ + PKIX_CHECK(pkix_IsCertSelfIssued + (cert, &isSelfIssued, plContext), + PKIX_ISCERTSELFISSUEDFAILED); + + if (!isSelfIssued) { + if (state->explicitPolicy > 0) { + state->explicitPolicy--; + } + if (state->policyMapping > 0) { + state->policyMapping--; + } + if (state->inhibitAnyPolicy > 0) { + state->inhibitAnyPolicy--; + } + } + + /* Section 6.1.4(i) */ + PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy + (cert, &explicitPolicySkipCerts, plContext), + PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); + + if (explicitPolicySkipCerts != -1) { + if (((PKIX_UInt32)explicitPolicySkipCerts) < + (state->explicitPolicy)) { + state->explicitPolicy = + ((PKIX_UInt32) explicitPolicySkipCerts); + } + } + + PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited + (cert, &inhibitMappingSkipCerts, plContext), + PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED); + + if (inhibitMappingSkipCerts != -1) { + if (((PKIX_UInt32)inhibitMappingSkipCerts) < + (state->policyMapping)) { + state->policyMapping = + ((PKIX_UInt32)inhibitMappingSkipCerts); + } + } + + PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy + (cert, &inhibitAnyPolicySkipCerts, plContext), + PKIX_CERTGETINHIBITANYPOLICYFAILED); + + if (inhibitAnyPolicySkipCerts != -1) { + if (((PKIX_UInt32)inhibitAnyPolicySkipCerts) < + (state->inhibitAnyPolicy)) { + state->inhibitAnyPolicy = + ((PKIX_UInt32)inhibitAnyPolicySkipCerts); + } + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + } else { /* If this was the last certificate, do wrap-up processing */ + + /* Section 6.1.5 */ + subroutineErr = pkix_PolicyChecker_WrapUpProcessing + (cert, state, plContext); + if (subroutineErr) { + goto subrErrorCleanup; + } + + if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) { + PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); + } + + PKIX_DECREF(state->anyPolicyNodeAtBottom); + PKIX_DECREF(state->newAnyPolicyNode); + } + + + if (subroutineErr) { + +subrErrorCleanup: + /* We had an error. Was it a fatal error? */ + pkixErrorClass = subroutineErr->errClass; + if (pkixErrorClass == PKIX_FATAL_ERROR) { + pkixErrorResult = subroutineErr; + subroutineErr = NULL; + goto cleanup; + } + /* + * Abort policy processing, and then determine whether + * we can continue without policy processing. + */ + PKIX_DECREF(state->validPolicyTree); + PKIX_DECREF(state->anyPolicyNodeAtBottom); + PKIX_DECREF(state->newAnyPolicyNode); + if (state->explicitPolicy == 0) { + PKIX_ERROR + (PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); + } + } + + /* Checking is complete. Save state for the next certificate. */ + PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState + (checker, (PKIX_PL_Object *)state, plContext), + PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); + +cleanup: + +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG + if (cert) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)cert, &certString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + PKIX_CHECK(PKIX_PL_String_GetEncoded + (certString, + PKIX_ESCASCII, + (void **)&certAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + PKIX_DEBUG_ARG("Cert was %s\n", certAscii); + PKIX_FREE(certAscii); + PKIX_DECREF(certString); + } + if (state) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)state, &stateString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stateString, + PKIX_ESCASCII, + (void **)&stateAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + PKIX_DEBUG_ARG("On exit %s\n", stateAscii); + PKIX_FREE(stateAscii); + PKIX_DECREF(stateString); + } +#endif + + PKIX_DECREF(state); + PKIX_DECREF(certPolicyInfos); + PKIX_DECREF(policy); + PKIX_DECREF(qualsOfAny); + PKIX_DECREF(policyQualifiers); + PKIX_DECREF(policyOID); + PKIX_DECREF(subroutineErr); + PKIX_DECREF(policyMaps); + PKIX_DECREF(mappedPolicies); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_PolicyChecker_Initialize + * DESCRIPTION: + * + * Creates and initializes a PolicyChecker, using the List pointed to + * by "initialPolicies" for the user-initial-policy-set, the Boolean value + * of "policyQualifiersRejected" for the policyQualifiersRejected parameter, + * the Boolean value of "initialPolicyMappingInhibit" for the + * inhibitPolicyMappings parameter, the Boolean value of + * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the + * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy + * parameter, and the UInt32 value of "numCerts" as the number of + * certificates in the chain; and stores the Checker at "pChecker". + * + * PARAMETERS: + * "initialPolicies" + * Address of List of OIDs comprising the user-initial-policy-set; the List + * may be empty or NULL + * "policyQualifiersRejected" + * Boolean value of the policyQualifiersRejected parameter + * "initialPolicyMappingInhibit" + * Boolean value of the inhibitPolicyMappings parameter + * "initialExplicitPolicy" + * Boolean value of the initialExplicitPolicy parameter + * "initialAnyPolicyInhibit" + * Boolean value of the inhibitAnyPolicy parameter + * "numCerts" + * Number of certificates in the chain to be validated + * "pChecker" + * Address to store the created PolicyChecker. 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 functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +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) +{ + PKIX_PolicyCheckerState *polCheckerState = NULL; + PKIX_List *policyExtensions = NULL; /* OIDs */ + PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Initialize"); + PKIX_NULLCHECK_ONE(pChecker); + + PKIX_CHECK(pkix_PolicyCheckerState_Create + (initialPolicies, + policyQualifiersRejected, + initialPolicyMappingInhibit, + initialExplicitPolicy, + initialAnyPolicyInhibit, + numCerts, + &polCheckerState, + plContext), + PKIX_POLICYCHECKERSTATECREATEFAILED); + + /* Create the list of extensions that we handle */ + PKIX_CHECK(pkix_PolicyChecker_MakeSingleton + ((PKIX_PL_Object *)(polCheckerState->certPoliciesExtension), + PKIX_TRUE, + &policyExtensions, + plContext), + PKIX_POLICYCHECKERMAKESINGLETONFAILED); + + PKIX_CHECK(PKIX_CertChainChecker_Create + (pkix_PolicyChecker_Check, + PKIX_FALSE, /* forwardCheckingSupported */ + PKIX_FALSE, + policyExtensions, + (PKIX_PL_Object *)polCheckerState, + pChecker, + plContext), + PKIX_CERTCHAINCHECKERCREATEFAILED); + +cleanup: + PKIX_DECREF(polCheckerState); + PKIX_DECREF(policyExtensions); + PKIX_RETURN(CERTCHAINCHECKER); + +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h new file mode 100644 index 0000000000..8b87ac1224 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c new file mode 100644 index 0000000000..7bed9b8860 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c @@ -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); +} + diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h new file mode 100644 index 0000000000..20dfe37787 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c new file mode 100644 index 0000000000..ee18ddef95 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c @@ -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); +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h new file mode 100644 index 0000000000..a97c7620ae --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c new file mode 100644 index 0000000000..0ed9ffaecc --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c @@ -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); + +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h new file mode 100644 index 0000000000..ccfb578579 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c new file mode 100644 index 0000000000..46fe07112b --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c @@ -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); +} diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h new file mode 100644 index 0000000000..4592d10a94 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h @@ -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 */ diff --git a/security/nss/lib/libpkix/pkix/crlsel/Makefile b/security/nss/lib/libpkix/pkix/crlsel/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/crlsel/Makefile @@ -0,0 +1,46 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/crlsel/crlsel.gyp b/security/nss/lib/libpkix/pkix/crlsel/crlsel.gyp new file mode 100644 index 0000000000..894569ef6c --- /dev/null +++ b/security/nss/lib/libpkix/pkix/crlsel/crlsel.gyp @@ -0,0 +1,24 @@ +# 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': 'pkixcrlsel', + 'type': 'static_library', + 'sources': [ + 'pkix_comcrlselparams.c', + 'pkix_crlselector.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix/crlsel/exports.gyp b/security/nss/lib/libpkix/pkix/crlsel/exports.gyp new file mode 100644 index 0000000000..a7001ffed7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/crlsel/exports.gyp @@ -0,0 +1,26 @@ +# 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_crlsel_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_comcrlselparams.h', + 'pkix_crlselector.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/crlsel/manifest.mn b/security/nss/lib/libpkix/pkix/crlsel/manifest.mn new file mode 100644 index 0000000000..fe84a2d62f --- /dev/null +++ b/security/nss/lib/libpkix/pkix/crlsel/manifest.mn @@ -0,0 +1,20 @@ +# +# 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 = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_comcrlselparams.h \ + pkix_crlselector.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_crlselector.c \ + pkix_comcrlselparams.c \ + $(NULL) + +LIBRARY_NAME = pkixcrlsel +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c new file mode 100644 index 0000000000..90380c5b2b --- /dev/null +++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c @@ -0,0 +1,826 @@ +/* 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_comcrlselparams.c + * + * ComCRLSelParams Function Definitions + * + */ + +#include "pkix_comcrlselparams.h" + +/* --ComCRLSelParams-Private-Functions------------------------------------ */ + +/* + * FUNCTION: pkix_ComCrlSelParams_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ComCRLSelParams_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ComCRLSelParams *params = NULL; + + PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_COMCRLSELPARAMS_TYPE, plContext), + PKIX_OBJECTNOTCOMCRLSELPARAMS); + + params = (PKIX_ComCRLSelParams *)object; + + PKIX_DECREF(params->issuerNames); + PKIX_DECREF(params->cert); + PKIX_DECREF(params->date); + PKIX_DECREF(params->maxCRLNumber); + PKIX_DECREF(params->minCRLNumber); + PKIX_DECREF(params->crldpList); + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: pkix_ComCRLSelParams_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of ComCRLSelParams + * pointed to by "crlParams" and stores the result at "pString". + * + * PARAMETERS + * "crlParams" + * Address of ComCRLSelParams whose string representation is desired. + * Must be non-NULL. + * "pString" + * Address of object pointer's destination. Must be non-NULL. + * "plContext" - Platform-specific context pointer. + * + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CRLEntry 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_ComCRLSelParams_ToString_Helper( + PKIX_ComCRLSelParams *crlParams, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *crlIssuerNamesString = NULL; + PKIX_PL_String *crlDateString = NULL; + PKIX_PL_String *crlMaxCRLNumberString = NULL; + PKIX_PL_String *crlMinCRLNumberString = NULL; + PKIX_PL_String *crlCertString = NULL; + PKIX_PL_String *crlParamsString = NULL; + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + + PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_ToString_Helper"); + PKIX_NULLCHECK_TWO(crlParams, pString); + + asciiFormat = + "\n\t[\n" + "\tIssuerNames: %s\n" + "\tDate: %s\n" + "\tmaxCRLNumber: %s\n" + "\tminCRLNumber: %s\n" + "\tCertificate: %s\n" + "\t]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_TOSTRING + (crlParams->issuerNames, &crlIssuerNamesString, plContext, + PKIX_LISTTOSTRINGFAILED); + + PKIX_TOSTRING(crlParams->date, &crlDateString, plContext, + PKIX_DATETOSTRINGFAILED); + + PKIX_TOSTRING + (crlParams->maxCRLNumber, &crlMaxCRLNumberString, plContext, + PKIX_BIGINTTOSTRINGFAILED); + + PKIX_TOSTRING + (crlParams->minCRLNumber, &crlMinCRLNumberString, plContext, + PKIX_BIGINTTOSTRINGFAILED); + + PKIX_TOSTRING(crlParams->cert, &crlCertString, plContext, + PKIX_CERTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&crlParamsString, + plContext, + formatString, + crlIssuerNamesString, + crlDateString, + crlMaxCRLNumberString, + crlMinCRLNumberString, + crlCertString), + PKIX_SPRINTFFAILED); + + *pString = crlParamsString; + +cleanup: + + PKIX_DECREF(crlIssuerNamesString); + PKIX_DECREF(crlDateString); + PKIX_DECREF(crlMaxCRLNumberString); + PKIX_DECREF(crlMinCRLNumberString); + PKIX_DECREF(crlCertString); + PKIX_DECREF(formatString); + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: pkix_ComCRLSelParams_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ComCRLSelParams_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *crlParamsString = NULL; + PKIX_ComCRLSelParams *crlParams = NULL; + + PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext), + PKIX_OBJECTNOTCOMCRLSELPARAMS); + + crlParams = (PKIX_ComCRLSelParams *) object; + + PKIX_CHECK(pkix_ComCRLSelParams_ToString_Helper + (crlParams, &crlParamsString, plContext), + PKIX_COMCRLSELPARAMSTOSTRINGHELPERFAILED); + + *pString = crlParamsString; + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: pkix_ComCRLSelParams_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ComCRLSelParams_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_ComCRLSelParams *crlParams = NULL; + PKIX_UInt32 namesHash = 0; + PKIX_UInt32 certHash = 0; + PKIX_UInt32 dateHash = 0; + PKIX_UInt32 maxCRLNumberHash = 0; + PKIX_UInt32 minCRLNumberHash = 0; + PKIX_UInt32 hash = 0; + + PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext), + PKIX_OBJECTNOTCOMCRLSELPARAMS); + + crlParams = (PKIX_ComCRLSelParams *)object; + + PKIX_HASHCODE(crlParams->issuerNames, &namesHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(crlParams->cert, &certHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(crlParams->date, &dateHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(crlParams->maxCRLNumber, &maxCRLNumberHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(crlParams->minCRLNumber, &minCRLNumberHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + + hash = (((namesHash << 3) + certHash) << 3) + dateHash; + hash = (hash << 3) + maxCRLNumberHash + minCRLNumberHash; + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: pkix_ComCRLSelParams_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ComCRLSelParams_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_ComCRLSelParams *firstCrlParams = NULL; + PKIX_ComCRLSelParams *secondCrlParams = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult = PKIX_FALSE; + + PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a ComCRLSelParams */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_COMCRLSELPARAMS_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCOMCRLSELPARAMS); + + firstCrlParams = (PKIX_ComCRLSelParams *)firstObject; + secondCrlParams = (PKIX_ComCRLSelParams *)secondObject; + + /* + * Since we know firstObject is a ComCRLSelParams, if both references + * are identical, they must be equal + */ + if (firstCrlParams == secondCrlParams){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondComCRLSelParams isn't a ComCRLSelParams, we don't + * throw an error. We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + ((PKIX_PL_Object *)secondCrlParams, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + if (secondType != PKIX_COMCRLSELPARAMS_TYPE) { + goto cleanup; + } + + /* Compare Issuer Names */ + PKIX_EQUALS + (firstCrlParams->issuerNames, + secondCrlParams->issuerNames, + &cmpResult, + plContext, + PKIX_LISTEQUALSFAILED); + + if (cmpResult != PKIX_TRUE) { + goto cleanup; + } + + /* Compare Date */ + PKIX_EQUALS + (firstCrlParams->date, + secondCrlParams->date, + &cmpResult, + plContext, + PKIX_DATEEQUALSFAILED); + + if (cmpResult != PKIX_TRUE) { + goto cleanup; + } + + /* Compare Max CRL Number */ + PKIX_EQUALS + (firstCrlParams->maxCRLNumber, + secondCrlParams->maxCRLNumber, + &cmpResult, + plContext, + PKIX_BIGINTEQUALSFAILED); + + if (cmpResult != PKIX_TRUE) { + goto cleanup; + } + + /* Compare Min CRL Number */ + PKIX_EQUALS + (firstCrlParams->minCRLNumber, + secondCrlParams->minCRLNumber, + &cmpResult, + plContext, + PKIX_BIGINTEQUALSFAILED); + + if (cmpResult != PKIX_TRUE) { + goto cleanup; + } + + /* Compare Cert */ + PKIX_EQUALS + (firstCrlParams->cert, + secondCrlParams->cert, + &cmpResult, + plContext, + PKIX_CERTEQUALSFAILED); + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: pkix_ComCRLSelParams_Duplicate + * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ComCRLSelParams_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_ComCRLSelParams *old; + PKIX_ComCRLSelParams *new = NULL; + + PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext), + PKIX_OBJECTNOTCOMCRLSELPARAMS); + + old = (PKIX_ComCRLSelParams *)object; + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_COMCRLSELPARAMS_TYPE, + (PKIX_UInt32)(sizeof (PKIX_ComCRLSelParams)), + (PKIX_PL_Object **)&new, + plContext), + PKIX_OBJECTALLOCFAILED); + + PKIX_DUPLICATE(old->cert, &new->cert, plContext, + PKIX_OBJECTDUPLICATECERTFAILED); + + PKIX_DUPLICATE(old->crldpList, &new->crldpList, plContext, + PKIX_OBJECTDUPLICATECERTFAILED); + + PKIX_DUPLICATE(old->issuerNames, &new->issuerNames, plContext, + PKIX_OBJECTDUPLICATEISSUERNAMESFAILED); + + PKIX_DUPLICATE(old->date, &new->date, plContext, + PKIX_OBJECTDUPLICATEDATEFAILED); + + PKIX_DUPLICATE(old->maxCRLNumber, &new->maxCRLNumber, plContext, + PKIX_OBJECTDUPLICATEMAXCRLNUMBERFAILED); + + PKIX_DUPLICATE(old->minCRLNumber, &new->minCRLNumber, plContext, + PKIX_OBJECTDUPLICATEMINCRLNUMBERFAILED); + + *pNewObject = (PKIX_PL_Object *)new; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(new); + } + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: pkix_ComCrlSelParams_RegisterSelf + * DESCRIPTION: + * Registers PKIX_COMCRLSELPARAMS_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_ComCRLSelParams_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_RegisterSelf"); + + entry.description = "ComCRLSelParams"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_ComCRLSelParams); + entry.destructor = pkix_ComCRLSelParams_Destroy; + entry.equalsFunction = pkix_ComCRLSelParams_Equals; + entry.hashcodeFunction = pkix_ComCRLSelParams_Hashcode; + entry.toStringFunction = pkix_ComCRLSelParams_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_ComCRLSelParams_Duplicate; + + systemClasses[PKIX_COMCRLSELPARAMS_TYPE] = entry; + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* --ComCRLSelParams-Public-Functions------------------------------------- */ + +/* + * FUNCTION: PKIX_ComCRLSelParams_Create (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_Create( + PKIX_ComCRLSelParams **pParams, + void *plContext) +{ + PKIX_ComCRLSelParams *params = NULL; + + PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_Create"); + PKIX_NULLCHECK_ONE(pParams); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_COMCRLSELPARAMS_TYPE, + sizeof (PKIX_ComCRLSelParams), + (PKIX_PL_Object **)¶ms, + plContext), + PKIX_COULDNOTCREATECOMMONCRLSELECTORPARAMSOBJECT); + + /* initialize fields */ + params->issuerNames = NULL; + params->cert = NULL; + params->crldpList = NULL; + params->date = NULL; + params->nistPolicyEnabled = PKIX_TRUE; + params->maxCRLNumber = NULL; + params->minCRLNumber = NULL; + + *pParams = params; + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetIssuerNames (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_GetIssuerNames( + PKIX_ComCRLSelParams *params, + PKIX_List **pIssuerNames, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_GetIssuerNames"); + PKIX_NULLCHECK_TWO(params, pIssuerNames); + + PKIX_INCREF(params->issuerNames); + + *pIssuerNames = params->issuerNames; + +cleanup: + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetIssuerNames (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_SetIssuerNames( + PKIX_ComCRLSelParams *params, + PKIX_List *names, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_SetIssuerNames"); + PKIX_NULLCHECK_ONE(params); /* allows null for names from spec */ + + PKIX_DECREF(params->issuerNames); + + PKIX_INCREF(names); /* if NULL, allows to reset for no action */ + + params->issuerNames = names; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_AddIssuerName (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_AddIssuerName( + PKIX_ComCRLSelParams *params, + PKIX_PL_X500Name *name, + void *plContext) +{ + PKIX_List *list = NULL; + + PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_AddIssuerName"); + PKIX_NULLCHECK_ONE(params); + + if (name != NULL) { + + if (params->issuerNames == NULL) { + + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + params->issuerNames = list; + } + + PKIX_CHECK(PKIX_List_AppendItem + (params->issuerNames, (PKIX_PL_Object *)name, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + } + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetCertificateChecking + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_GetCertificateChecking( + PKIX_ComCRLSelParams *params, + PKIX_PL_Cert **pCert, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_GetCertificateChecking"); + PKIX_NULLCHECK_TWO(params, pCert); + + PKIX_INCREF(params->cert); + + *pCert = params->cert; + +cleanup: + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetCertificateChecking + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_SetCertificateChecking( + PKIX_ComCRLSelParams *params, + PKIX_PL_Cert *cert, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_SetCertificateChecking"); + PKIX_NULLCHECK_ONE(params); /* allows cert to be NULL from spec */ + + PKIX_DECREF(params->cert); + + PKIX_INCREF(cert); + + params->cert = cert; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetDateAndTime (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_GetDateAndTime( + PKIX_ComCRLSelParams *params, + PKIX_PL_Date **pDate, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_GetDateAndTime"); + PKIX_NULLCHECK_TWO(params, pDate); + + PKIX_INCREF(params->date); + + *pDate = params->date; + +cleanup: + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetDateAndTime (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_SetDateAndTime( + PKIX_ComCRLSelParams *params, + PKIX_PL_Date *date, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_SetDateAndTime"); + PKIX_NULLCHECK_ONE(params); /* allows date to be NULL from spec */ + + PKIX_DECREF (params->date); + + PKIX_INCREF(date); + + params->date = date; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetDateAndTime (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_GetNISTPolicyEnabled( + PKIX_ComCRLSelParams *params, + PKIX_Boolean *pEnabled, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_GetNISTPolicyEnabled"); + PKIX_NULLCHECK_TWO(params, pEnabled); + + *pEnabled = params->nistPolicyEnabled; + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetDateAndTime (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_SetNISTPolicyEnabled( + PKIX_ComCRLSelParams *params, + PKIX_Boolean enabled, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_SetNISTPolicyEnabled"); + PKIX_NULLCHECK_ONE(params); /* allows date to be NULL from spec */ + + params->nistPolicyEnabled = enabled; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetMaxCRLNumber + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_GetMaxCRLNumber( + PKIX_ComCRLSelParams *params, + PKIX_PL_BigInt **pMaxCRLNumber, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_GetMaxCRLNumber"); + PKIX_NULLCHECK_TWO(params, pMaxCRLNumber); + + PKIX_INCREF(params->maxCRLNumber); + + *pMaxCRLNumber = params->maxCRLNumber; + +cleanup: + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetMaxCRLNumber + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_SetMaxCRLNumber( + PKIX_ComCRLSelParams *params, + PKIX_PL_BigInt *maxCRLNumber, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_SetMaxCRLNumber"); + PKIX_NULLCHECK_ONE(params); /* maxCRLNumber can be NULL - from spec */ + + PKIX_DECREF(params->maxCRLNumber); + + PKIX_INCREF(maxCRLNumber); + + params->maxCRLNumber = maxCRLNumber; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetMinCRLNumber + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_GetMinCRLNumber( + PKIX_ComCRLSelParams *params, + PKIX_PL_BigInt **pMinCRLNumber, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_GetMinCRLNumber"); + PKIX_NULLCHECK_TWO(params, pMinCRLNumber); + + PKIX_INCREF(params->minCRLNumber); + + *pMinCRLNumber = params->minCRLNumber; + +cleanup: + PKIX_RETURN(COMCRLSELPARAMS); +} + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetMinCRLNumber + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_ComCRLSelParams_SetMinCRLNumber( + PKIX_ComCRLSelParams *params, + PKIX_PL_BigInt *minCRLNumber, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, + "PKIX_ComCRLSelParams_SetMinCRLNumber"); + PKIX_NULLCHECK_ONE(params); /* minCRLNumber can be NULL - from spec */ + + PKIX_DECREF(params->minCRLNumber); + + PKIX_INCREF(minCRLNumber); + + params->minCRLNumber = minCRLNumber; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} + + +PKIX_Error* +PKIX_ComCRLSelParams_SetCrlDp( + PKIX_ComCRLSelParams *params, + PKIX_List *crldpList, + void *plContext) +{ + PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_SetCrlDp"); + PKIX_NULLCHECK_ONE(params); /* minCRLNumber can be NULL - from spec */ + + PKIX_INCREF(crldpList); + params->crldpList = crldpList; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); +cleanup: + + PKIX_RETURN(COMCRLSELPARAMS); +} diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h new file mode 100644 index 0000000000..08351375d9 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h @@ -0,0 +1,38 @@ +/* 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_comcrlselparams.h + * + * ComCrlSelParams Object Type Definition + * + */ + +#ifndef _PKIX_COMCRLSELPARAMS_H +#define _PKIX_COMCRLSELPARAMS_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_ComCRLSelParamsStruct { + PKIX_List *issuerNames; /* list of PKIX_PL_X500Name */ + PKIX_PL_Cert *cert; /* certificate being checked */ + PKIX_List *crldpList; + PKIX_PL_Date *date; + PKIX_Boolean nistPolicyEnabled; + PKIX_PL_BigInt *maxCRLNumber; + PKIX_PL_BigInt *minCRLNumber; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_ComCRLSelParams_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_COMCRLSELPARAMS_H */ diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c new file mode 100644 index 0000000000..e9a9c03dfd --- /dev/null +++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c @@ -0,0 +1,870 @@ +/* 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_crlselector.c + * + * CRLSelector Function Definitions + * + */ + +#include "pkix_crlselector.h" + +/* --CRLSelector Private-Functions-------------------------------------- */ + +/* + * FUNCTION: pkix_CRLSelector_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CRLSelector_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_CRLSelector *selector = NULL; + + PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext), + PKIX_OBJECTNOTCRLSELECTOR); + + selector = (PKIX_CRLSelector *)object; + + selector->matchCallback = NULL; + + PKIX_DECREF(selector->params); + PKIX_DECREF(selector->context); + +cleanup: + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: pkix_CRLSelector_ToString_Helper + * + * DESCRIPTION: + * Helper function that creates a string representation of CRLSelector + * pointed to by "crlParams" and stores its address in the object pointed to + * by "pString". + * + * PARAMETERS + * "list" + * Address of CRLSelector whose string representation is desired. + * Must be non-NULL. + * "pString" + * Address of object pointer's destination. Must be non-NULL. + * "plContext" - Platform-specific context pointer. + * + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CRLSelector 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_CRLSelector_ToString_Helper( + PKIX_CRLSelector *crlSelector, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *crlSelectorString = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *crlParamsString = NULL; + PKIX_PL_String *crlContextString = NULL; + char *asciiFormat = NULL; + + PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_ToString_Helper"); + PKIX_NULLCHECK_TWO(crlSelector, pString); + PKIX_NULLCHECK_ONE(crlSelector->params); + + asciiFormat = + "\n\t[\n" + "\tMatchCallback: 0x%x\n" + "\tParams: %s\n" + "\tContext: %s\n" + "\t]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + /* Params */ + PKIX_TOSTRING + ((PKIX_PL_Object *)crlSelector->params, + &crlParamsString, + plContext, + PKIX_COMCRLSELPARAMSTOSTRINGFAILED); + + /* Context */ + PKIX_TOSTRING(crlSelector->context, &crlContextString, plContext, + PKIX_LISTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&crlSelectorString, + plContext, + formatString, + crlSelector->matchCallback, + crlParamsString, + crlContextString), + PKIX_SPRINTFFAILED); + + *pString = crlSelectorString; + +cleanup: + + PKIX_DECREF(crlParamsString); + PKIX_DECREF(crlContextString); + PKIX_DECREF(formatString); + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: pkix_CRLSelector_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CRLSelector_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *crlSelectorString = NULL; + PKIX_CRLSelector *crlSelector = NULL; + + PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext), + PKIX_OBJECTNOTCRLSELECTOR); + + crlSelector = (PKIX_CRLSelector *) object; + + PKIX_CHECK(pkix_CRLSelector_ToString_Helper + (crlSelector, &crlSelectorString, plContext), + PKIX_CRLSELECTORTOSTRINGHELPERFAILED); + + *pString = crlSelectorString; + +cleanup: + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: pkix_CRLSelector_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CRLSelector_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 paramsHash = 0; + PKIX_UInt32 contextHash = 0; + PKIX_UInt32 hash = 0; + + PKIX_CRLSelector *crlSelector = NULL; + + PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext), + PKIX_OBJECTNOTCRLSELECTOR); + + crlSelector = (PKIX_CRLSelector *)object; + + PKIX_HASHCODE(crlSelector->params, ¶msHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(crlSelector->context, &contextHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + hash = 31 * ((PKIX_UInt32)((char *)crlSelector->matchCallback - (char *)NULL) + + (contextHash << 3)) + paramsHash; + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: pkix_CRLSelector_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CRLSelector_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_CRLSelector *firstCrlSelector = NULL; + PKIX_CRLSelector *secondCrlSelector = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult = PKIX_FALSE; + + PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a CRLSelector */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_CRLSELECTOR_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCRLSELECTOR); + + firstCrlSelector = (PKIX_CRLSelector *)firstObject; + secondCrlSelector = (PKIX_CRLSelector *)secondObject; + + /* + * Since we know firstObject is a CRLSelector, if both references are + * identical, they must be equal + */ + if (firstCrlSelector == secondCrlSelector){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondCRLSelector isn't a CRLSelector, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + ((PKIX_PL_Object *)secondCrlSelector, + &secondType, + plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + if (secondType != PKIX_CRLSELECTOR_TYPE) { + goto cleanup; + } + + /* Compare MatchCallback address */ + cmpResult = (firstCrlSelector->matchCallback == + secondCrlSelector->matchCallback); + + if (cmpResult == PKIX_FALSE) { + goto cleanup; + } + + /* Compare Common CRL Selector Params */ + PKIX_EQUALS + (firstCrlSelector->params, + secondCrlSelector->params, + &cmpResult, + plContext, + PKIX_COMCRLSELPARAMSEQUALSFAILED); + + + if (cmpResult == PKIX_FALSE) { + goto cleanup; + } + + /* Compare Context */ + PKIX_EQUALS + (firstCrlSelector->context, + secondCrlSelector->context, + &cmpResult, + plContext, + PKIX_COMCRLSELPARAMSEQUALSFAILED); + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: pkix_CRLSelector_Duplicate + * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CRLSelector_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_CRLSelector *old; + PKIX_CRLSelector *new = NULL; + + PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CRLSELECTOR_TYPE, plContext), + PKIX_OBJECTNOTCRLSELECTOR); + + old = (PKIX_CRLSelector *)object; + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CRLSELECTOR_TYPE, + (PKIX_UInt32)(sizeof (PKIX_CRLSelector)), + (PKIX_PL_Object **)&new, + plContext), + PKIX_CREATECRLSELECTORDUPLICATEOBJECTFAILED); + + new->matchCallback = old->matchCallback; + + PKIX_DUPLICATE(old->params, &new->params, plContext, + PKIX_OBJECTDUPLICATEPARAMSFAILED); + + PKIX_DUPLICATE(old->context, &new->context, plContext, + PKIX_OBJECTDUPLICATECONTEXTFAILED); + + *pNewObject = (PKIX_PL_Object *)new; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(new); + } + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: pkix_CRLSelector_DefaultMatch + * + * DESCRIPTION: + * This function compares the parameter values (Issuer, date, and CRL number) + * set in the ComCRLSelParams of the CRLSelector pointed to by "selector" with + * the corresponding values in the CRL pointed to by "crl". When all the + * criteria set in the parameter values match the values in "crl", PKIX_TRUE is + * stored at "pMatch". If the CRL does not match the CRLSelector's criteria, + * PKIX_FALSE is stored at "pMatch". + * + * PARAMETERS + * "selector" + * Address of CRLSelector which is verified for a match + * Must be non-NULL. + * "crl" + * Address of the CRL object to be verified. Must be non-NULL. + * "pMatch" + * Address at which Boolean result is stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CRLSelector 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_CRLSelector_DefaultMatch( + PKIX_CRLSelector *selector, + PKIX_PL_CRL *crl, + PKIX_Boolean *pMatch, + void *plContext) +{ + PKIX_ComCRLSelParams *params = NULL; + PKIX_PL_X500Name *crlIssuerName = NULL; + PKIX_PL_X500Name *issuerName = NULL; + PKIX_List *selIssuerNames = NULL; + PKIX_PL_Date *selDate = NULL; + PKIX_Boolean result = PKIX_TRUE; + PKIX_UInt32 numIssuers = 0; + PKIX_UInt32 i; + PKIX_PL_BigInt *minCRLNumber = NULL; + PKIX_PL_BigInt *maxCRLNumber = NULL; + PKIX_PL_BigInt *crlNumber = NULL; + PKIX_Boolean nistPolicyEnabled = PKIX_FALSE; + + PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_DefaultMatch"); + PKIX_NULLCHECK_TWO(selector, crl); + + *pMatch = PKIX_TRUE; + params = selector->params; + + /* No matching parameter provided, just a match */ + if (params == NULL) { + goto cleanup; + } + + PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames + (params, &selIssuerNames, plContext), + PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED); + + /* Check for Issuers */ + if (selIssuerNames != NULL){ + + result = PKIX_FALSE; + + PKIX_CHECK(PKIX_PL_CRL_GetIssuer + (crl, &crlIssuerName, plContext), + PKIX_CRLGETISSUERFAILED); + + PKIX_CHECK(PKIX_List_GetLength + (selIssuerNames, &numIssuers, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numIssuers; i++){ + + PKIX_CHECK(PKIX_List_GetItem + (selIssuerNames, + i, + (PKIX_PL_Object **)&issuerName, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_PL_X500Name_Match + (crlIssuerName, + issuerName, + &result, + plContext), + PKIX_X500NAMEMATCHFAILED); + + PKIX_DECREF(issuerName); + + if (result == PKIX_TRUE) { + break; + } + } + + if (result == PKIX_FALSE) { + PKIX_CRLSELECTOR_DEBUG("Issuer Match Failed\N"); + *pMatch = PKIX_FALSE; + goto cleanup; + } + + } + + PKIX_CHECK(PKIX_ComCRLSelParams_GetDateAndTime + (params, &selDate, plContext), + PKIX_COMCRLSELPARAMSGETDATEANDTIMEFAILED); + + /* Check for Date */ + if (selDate != NULL){ + + PKIX_CHECK(PKIX_ComCRLSelParams_GetNISTPolicyEnabled + (params, &nistPolicyEnabled, plContext), + PKIX_COMCRLSELPARAMSGETNISTPOLICYENABLEDFAILED); + + /* check crl dates only for if NIST policies enforced */ + if (nistPolicyEnabled) { + result = PKIX_FALSE; + + PKIX_CHECK(PKIX_PL_CRL_VerifyUpdateTime + (crl, selDate, &result, plContext), + PKIX_CRLVERIFYUPDATETIMEFAILED); + + if (result == PKIX_FALSE) { + *pMatch = PKIX_FALSE; + goto cleanup; + } + } + + } + + /* Check for CRL number in range */ + PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber(crl, &crlNumber, plContext), + PKIX_CRLGETCRLNUMBERFAILED); + + if (crlNumber != NULL) { + result = PKIX_FALSE; + + PKIX_CHECK(PKIX_ComCRLSelParams_GetMinCRLNumber + (params, &minCRLNumber, plContext), + PKIX_COMCRLSELPARAMSGETMINCRLNUMBERFAILED); + + if (minCRLNumber != NULL) { + + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)minCRLNumber, + (PKIX_PL_Object *)crlNumber, + &result, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + + if (result == 1) { + PKIX_CRLSELECTOR_DEBUG + ("CRL MinNumber Range Match Failed\n"); + *pMatch = PKIX_FALSE; + goto cleanup; + } + } + + PKIX_CHECK(PKIX_ComCRLSelParams_GetMaxCRLNumber + (params, &maxCRLNumber, plContext), + PKIX_COMCRLSELPARAMSGETMAXCRLNUMBERFAILED); + + if (maxCRLNumber != NULL) { + + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)crlNumber, + (PKIX_PL_Object *)maxCRLNumber, + &result, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + + if (result == 1) { + PKIX_CRLSELECTOR_DEBUG + (PKIX_CRLMAXNUMBERRANGEMATCHFAILED); + *pMatch = PKIX_FALSE; + goto cleanup; + } + } + } + +cleanup: + + PKIX_DECREF(selIssuerNames); + PKIX_DECREF(selDate); + PKIX_DECREF(crlIssuerName); + PKIX_DECREF(issuerName); + PKIX_DECREF(crlNumber); + PKIX_DECREF(minCRLNumber); + PKIX_DECREF(maxCRLNumber); + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: pkix_CRLSelector_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CRLSELECTOR_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_CRLSelector_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_RegisterSelf"); + + entry.description = "CRLSelector"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_CRLSelector); + entry.destructor = pkix_CRLSelector_Destroy; + entry.equalsFunction = pkix_CRLSelector_Equals; + entry.hashcodeFunction = pkix_CRLSelector_Hashcode; + entry.toStringFunction = pkix_CRLSelector_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_CRLSelector_Duplicate; + + systemClasses[PKIX_CRLSELECTOR_TYPE] = entry; + + PKIX_RETURN(CRLSELECTOR); +} + +/* --CRLSelector-Public-Functions---------------------------------------- */ +PKIX_Error * +pkix_CRLSelector_Create( + PKIX_CRLSelector_MatchCallback callback, + PKIX_PL_Object *crlSelectorContext, + PKIX_CRLSelector **pSelector, + void *plContext) +{ + PKIX_CRLSelector *selector = NULL; + + PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_Create"); + PKIX_NULLCHECK_ONE(pSelector); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CRLSELECTOR_TYPE, + sizeof (PKIX_CRLSelector), + (PKIX_PL_Object **)&selector, + plContext), + PKIX_COULDNOTCREATECRLSELECTOROBJECT); + + /* + * if user specified a particular match callback, we use that one. + * otherwise, we use the default match provided. + */ + + if (callback != NULL){ + selector->matchCallback = callback; + } else { + selector->matchCallback = pkix_CRLSelector_DefaultMatch; + } + + /* initialize other fields */ + selector->params = NULL; + + PKIX_INCREF(crlSelectorContext); + selector->context = crlSelectorContext; + + *pSelector = selector; + selector = NULL; + +cleanup: + + PKIX_DECREF(selector); + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: PKIX_CRLSelector_Create (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_CRLSelector_Create( + PKIX_PL_Cert *issuer, + PKIX_List *crldpList, + PKIX_PL_Date *date, + PKIX_CRLSelector **pCrlSelector, + void *plContext) +{ + PKIX_PL_X500Name *issuerName = NULL; + PKIX_PL_Date *nowDate = NULL; + PKIX_ComCRLSelParams *comCrlSelParams = NULL; + PKIX_CRLSelector *crlSelector = NULL; + + PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CrlSelector_Create"); + PKIX_NULLCHECK_ONE(issuer); + + PKIX_CHECK( + PKIX_PL_Cert_GetSubject(issuer, &issuerName, plContext), + PKIX_CERTGETISSUERFAILED); + + if (date != NULL) { + PKIX_INCREF(date); + nowDate = date; + } else { + PKIX_CHECK( + PKIX_PL_Date_Create_UTCTime(NULL, &nowDate, plContext), + PKIX_DATECREATEUTCTIMEFAILED); + } + + PKIX_CHECK( + PKIX_ComCRLSelParams_Create(&comCrlSelParams, plContext), + PKIX_COMCRLSELPARAMSCREATEFAILED); + + PKIX_CHECK( + PKIX_ComCRLSelParams_AddIssuerName(comCrlSelParams, issuerName, + plContext), + PKIX_COMCRLSELPARAMSADDISSUERNAMEFAILED); + + PKIX_CHECK( + PKIX_ComCRLSelParams_SetCrlDp(comCrlSelParams, crldpList, + plContext), + PKIX_COMCRLSELPARAMSSETCERTFAILED); + + PKIX_CHECK( + PKIX_ComCRLSelParams_SetDateAndTime(comCrlSelParams, nowDate, + plContext), + PKIX_COMCRLSELPARAMSSETDATEANDTIMEFAILED); + + PKIX_CHECK( + pkix_CRLSelector_Create(NULL, NULL, &crlSelector, plContext), + PKIX_CRLSELECTORCREATEFAILED); + + PKIX_CHECK( + PKIX_CRLSelector_SetCommonCRLSelectorParams(crlSelector, + comCrlSelParams, + plContext), + PKIX_CRLSELECTORSETCOMMONCRLSELECTORPARAMSFAILED); + + *pCrlSelector = crlSelector; + crlSelector = NULL; + +cleanup: + + PKIX_DECREF(issuerName); + PKIX_DECREF(nowDate); + PKIX_DECREF(comCrlSelParams); + PKIX_DECREF(crlSelector); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: PKIX_CRLSelector_GetMatchCallback (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_CRLSelector_GetMatchCallback( + PKIX_CRLSelector *selector, + PKIX_CRLSelector_MatchCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetMatchCallback"); + PKIX_NULLCHECK_TWO(selector, pCallback); + + *pCallback = selector->matchCallback; + + PKIX_RETURN(CRLSELECTOR); +} + + +/* + * FUNCTION: PKIX_CRLSelector_GetCRLSelectorContext + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_CRLSelector_GetCRLSelectorContext( + PKIX_CRLSelector *selector, + void **pCrlSelectorContext, + void *plContext) +{ + PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetCRLSelectorContext"); + PKIX_NULLCHECK_TWO(selector, pCrlSelectorContext); + + PKIX_INCREF(selector->context); + + *pCrlSelectorContext = selector->context; + +cleanup: + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: PKIX_CRLSelector_GetCommonCRLSelectorParams + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_CRLSelector_GetCommonCRLSelectorParams( + PKIX_CRLSelector *selector, + PKIX_ComCRLSelParams **pParams, + void *plContext) +{ + PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetCommonCRLSelectorParams"); + PKIX_NULLCHECK_TWO(selector, pParams); + + PKIX_INCREF(selector->params); + + *pParams = selector->params; + +cleanup: + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: PKIX_CRLSelector_SetCommonCRLSelectorParams + * (see comments in pkix_crlsel.h) + */ +PKIX_Error * +PKIX_CRLSelector_SetCommonCRLSelectorParams( + PKIX_CRLSelector *selector, + PKIX_ComCRLSelParams *params, + void *plContext) +{ + PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_SetCommonCRLSelectorParams"); + PKIX_NULLCHECK_TWO(selector, params); + + PKIX_DECREF(selector->params); + + PKIX_INCREF(params); + selector->params = params; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)selector, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(CRLSELECTOR); +} + +/* + * FUNCTION: pkix_CRLSelector_Select + * DESCRIPTION: + * + * This function applies the selector pointed to by "selector" to each CRL, + * in turn, in the List pointed to by "before", and creates a List containing + * all the CRLs that matched, or passed the selection process, storing that + * List at "pAfter". If no CRLs match, an empty List is stored at "pAfter". + * + * The List returned in "pAfter" is immutable. + * + * PARAMETERS: + * "selector" + * Address of CRLSelelector to be applied to the List. Must be non-NULL. + * "before" + * Address of List that is to be filtered. Must be non-NULL. + * "pAfter" + * Address at which resulting List, possibly empty, is 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 CRLSelector 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_CRLSelector_Select( + PKIX_CRLSelector *selector, + PKIX_List *before, + PKIX_List **pAfter, + void *plContext) +{ + PKIX_Boolean match = PKIX_FALSE; + PKIX_UInt32 numBefore = 0; + PKIX_UInt32 i = 0; + PKIX_List *filtered = NULL; + PKIX_PL_CRL *candidate = NULL; + + PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_Select"); + PKIX_NULLCHECK_THREE(selector, before, pAfter); + + PKIX_CHECK(PKIX_List_Create(&filtered, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(before, &numBefore, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numBefore; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (before, i, (PKIX_PL_Object **)&candidate, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK_ONLY_FATAL(selector->matchCallback + (selector, candidate, &match, plContext), + PKIX_CRLSELECTORMATCHCALLBACKFAILED); + + if (!(PKIX_ERROR_RECEIVED) && match == PKIX_TRUE) { + + PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem + (filtered, + (PKIX_PL_Object *)candidate, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + pkixTempErrorReceived = PKIX_FALSE; + PKIX_DECREF(candidate); + } + + PKIX_CHECK(PKIX_List_SetImmutable(filtered, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + /* Don't throw away the list if one CRL was bad! */ + pkixTempErrorReceived = PKIX_FALSE; + + *pAfter = filtered; + filtered = NULL; + +cleanup: + + PKIX_DECREF(filtered); + PKIX_DECREF(candidate); + + PKIX_RETURN(CRLSELECTOR); + +} diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h new file mode 100644 index 0000000000..4f44cc7683 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h @@ -0,0 +1,40 @@ +/* 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_crlselector.h + * + * CrlSelector Object Type Definition + * + */ + +#ifndef _PKIX_CRLSELECTOR_H +#define _PKIX_CRLSELECTOR_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_CRLSelectorStruct { + PKIX_CRLSelector_MatchCallback matchCallback; + PKIX_ComCRLSelParams *params; + PKIX_PL_Object *context; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_CRLSelector_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_CRLSelector_Select( + PKIX_CRLSelector *selector, + PKIX_List *before, + PKIX_List **pAfter, + void *plContext); +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_CRLSELECTOR_H */ diff --git a/security/nss/lib/libpkix/pkix/manifest.mn b/security/nss/lib/libpkix/pkix/manifest.mn new file mode 100644 index 0000000000..dcb6f0ce61 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/manifest.mn @@ -0,0 +1,11 @@ +# +# 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 = ../../.. +DEPTH = ../../.. + +# +DIRS = certsel crlsel checker params results store top util \ + $(NULL) + diff --git a/security/nss/lib/libpkix/pkix/params/Makefile b/security/nss/lib/libpkix/pkix/params/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/Makefile @@ -0,0 +1,46 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/params/exports.gyp b/security/nss/lib/libpkix/pkix/params/exports.gyp new file mode 100644 index 0000000000..921f2ceae3 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/exports.gyp @@ -0,0 +1,28 @@ +# 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_params_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_procparams.h', + 'pkix_resourcelimits.h', + 'pkix_trustanchor.h', + 'pkix_valparams.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/params/manifest.mn b/security/nss/lib/libpkix/pkix/params/manifest.mn new file mode 100644 index 0000000000..2a77bf0eea --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/manifest.mn @@ -0,0 +1,24 @@ +# +# 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 = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_procparams.h \ + pkix_trustanchor.h \ + pkix_valparams.h \ + pkix_resourcelimits.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_trustanchor.c \ + pkix_procparams.c \ + pkix_valparams.c \ + pkix_resourcelimits.c \ + $(NULL) + +LIBRARY_NAME = pkixparams +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/params/params.gyp b/security/nss/lib/libpkix/pkix/params/params.gyp new file mode 100644 index 0000000000..a1463c4c7c --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/params.gyp @@ -0,0 +1,26 @@ +# 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': 'pkixparams', + 'type': 'static_library', + 'sources': [ + 'pkix_procparams.c', + 'pkix_resourcelimits.c', + 'pkix_trustanchor.c', + 'pkix_valparams.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix/params/pkix_procparams.c b/security/nss/lib/libpkix/pkix/params/pkix_procparams.c new file mode 100644 index 0000000000..260b0074c7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/pkix_procparams.c @@ -0,0 +1,1417 @@ +/* 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_procparams.c + * + * ProcessingParams Object Functions + * + */ + +#include "pkix_procparams.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_ProcessingParams_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ProcessingParams_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ProcessingParams *params = NULL; + + PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a processing params object */ + PKIX_CHECK(pkix_CheckType + (object, PKIX_PROCESSINGPARAMS_TYPE, plContext), + PKIX_OBJECTNOTPROCESSINGPARAMS); + + params = (PKIX_ProcessingParams *)object; + + PKIX_DECREF(params->trustAnchors); + PKIX_DECREF(params->hintCerts); + PKIX_DECREF(params->constraints); + PKIX_DECREF(params->date); + PKIX_DECREF(params->initialPolicies); + PKIX_DECREF(params->certChainCheckers); + PKIX_DECREF(params->revChecker); + PKIX_DECREF(params->certStores); + PKIX_DECREF(params->resourceLimits); + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: pkix_ProcessingParams_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ProcessingParams_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_ProcessingParams *firstProcParams = NULL; + PKIX_ProcessingParams *secondProcParams = NULL; + + PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_PROCESSINGPARAMS_TYPE, plContext), + PKIX_FIRSTOBJECTNOTPROCESSINGPARAMS); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_PROCESSINGPARAMS_TYPE) goto cleanup; + + firstProcParams = (PKIX_ProcessingParams *)first; + secondProcParams = (PKIX_ProcessingParams *)second; + + /* Do the simplest tests first */ + if ((firstProcParams->qualifiersRejected) != + (secondProcParams->qualifiersRejected)) { + goto cleanup; + } + + if (firstProcParams->isCrlRevocationCheckingEnabled != + secondProcParams->isCrlRevocationCheckingEnabled) { + goto cleanup; + } + if (firstProcParams->isCrlRevocationCheckingEnabledWithNISTPolicy != + secondProcParams->isCrlRevocationCheckingEnabledWithNISTPolicy) { + goto cleanup; + } + + /* trustAnchors can never be NULL */ + + PKIX_EQUALS + (firstProcParams->trustAnchors, + secondProcParams->trustAnchors, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_EQUALS + (firstProcParams->hintCerts, + secondProcParams->hintCerts, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_EQUALS + (firstProcParams->date, + secondProcParams->date, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_EQUALS + (firstProcParams->constraints, + secondProcParams->constraints, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_EQUALS + (firstProcParams->initialPolicies, + secondProcParams->initialPolicies, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + /* There is no Equals function for CertChainCheckers */ + + PKIX_EQUALS + ((PKIX_PL_Object *)firstProcParams->certStores, + (PKIX_PL_Object *)secondProcParams->certStores, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_EQUALS + (firstProcParams->resourceLimits, + secondProcParams->resourceLimits, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (cmpResult == PKIX_FALSE) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: pkix_ProcessingParams_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ProcessingParams_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_ProcessingParams *procParams = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 anchorsHash = 0; + PKIX_UInt32 hintCertsHash = 0; + PKIX_UInt32 dateHash = 0; + PKIX_UInt32 constraintsHash = 0; + PKIX_UInt32 initialHash = 0; + PKIX_UInt32 rejectedHash = 0; + PKIX_UInt32 certChainCheckersHash = 0; + PKIX_UInt32 revCheckerHash = 0; + PKIX_UInt32 certStoresHash = 0; + PKIX_UInt32 resourceLimitsHash = 0; + + PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_PROCESSINGPARAMS_TYPE, plContext), + PKIX_OBJECTNOTPROCESSINGPARAMS); + + procParams = (PKIX_ProcessingParams*)object; + + PKIX_HASHCODE(procParams->trustAnchors, &anchorsHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(procParams->hintCerts, &hintCertsHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(procParams->date, &dateHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(procParams->constraints, &constraintsHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(procParams->initialPolicies, &initialHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + rejectedHash = procParams->qualifiersRejected; + + /* There is no Hash function for CertChainCheckers */ + + PKIX_HASHCODE(procParams->certStores, &certStoresHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(procParams->resourceLimits, + &resourceLimitsHash, + plContext, + PKIX_OBJECTHASHCODEFAILED); + + hash = (31 * ((31 * anchorsHash) + hintCertsHash + dateHash)) + + constraintsHash + initialHash + rejectedHash; + + hash += ((((certStoresHash + resourceLimitsHash) << 7) + + certChainCheckersHash + revCheckerHash + + procParams->isCrlRevocationCheckingEnabled + + procParams->isCrlRevocationCheckingEnabledWithNISTPolicy) << 7); + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: pkix_ProcessingParams_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ProcessingParams_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_ProcessingParams *procParams = NULL; + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *procParamsString = NULL; + PKIX_PL_String *anchorsString = NULL; + PKIX_PL_String *dateString = NULL; + PKIX_PL_String *constraintsString = NULL; + PKIX_PL_String *InitialPoliciesString = NULL; + PKIX_PL_String *qualsRejectedString = NULL; + PKIX_List *certStores = NULL; + PKIX_PL_String *certStoresString = NULL; + PKIX_PL_String *resourceLimitsString = NULL; + + PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_PROCESSINGPARAMS_TYPE, plContext), + PKIX_OBJECTNOTPROCESSINGPARAMS); + + asciiFormat = + "[\n" + "\tTrust Anchors: \n" + "\t********BEGIN LIST OF TRUST ANCHORS********\n" + "\t\t%s\n" + "\t********END LIST OF TRUST ANCHORS********\n" + "\tDate: \t\t%s\n" + "\tTarget Constraints: %s\n" + "\tInitial Policies: %s\n" + "\tQualifiers Rejected: %s\n" + "\tCert Stores: %s\n" + "\tResource Limits: %s\n" + "\tCRL Checking Enabled: %d\n" + "]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + procParams = (PKIX_ProcessingParams*)object; + + PKIX_TOSTRING(procParams->trustAnchors, &anchorsString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING(procParams->date, &dateString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING(procParams->constraints, &constraintsString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (procParams->initialPolicies, &InitialPoliciesString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (procParams->qualifiersRejected)?"TRUE":"FALSE", + 0, + &qualsRejectedString, + plContext), + PKIX_STRINGCREATEFAILED); + + /* There is no ToString function for CertChainCheckers */ + + PKIX_CHECK(PKIX_ProcessingParams_GetCertStores + (procParams, &certStores, plContext), + PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); + + PKIX_TOSTRING(certStores, &certStoresString, plContext, + PKIX_LISTTOSTRINGFAILED); + + PKIX_TOSTRING(procParams->resourceLimits, + &resourceLimitsString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&procParamsString, + plContext, + formatString, + anchorsString, + dateString, + constraintsString, + InitialPoliciesString, + qualsRejectedString, + certStoresString, + resourceLimitsString, + procParams->isCrlRevocationCheckingEnabled, + procParams->isCrlRevocationCheckingEnabledWithNISTPolicy), + PKIX_SPRINTFFAILED); + + *pString = procParamsString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(anchorsString); + PKIX_DECREF(dateString); + PKIX_DECREF(constraintsString); + PKIX_DECREF(InitialPoliciesString); + PKIX_DECREF(qualsRejectedString); + PKIX_DECREF(certStores); + PKIX_DECREF(certStoresString); + PKIX_DECREF(resourceLimitsString); + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: pkix_ProcessingParams_Duplicate + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ProcessingParams_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_ProcessingParams *params = NULL; + PKIX_ProcessingParams *paramsDuplicate = NULL; + + PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_PROCESSINGPARAMS_TYPE, plContext), + PKIX_OBJECTNOTPROCESSINGPARAMS); + + params = (PKIX_ProcessingParams *)object; + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_PROCESSINGPARAMS_TYPE, + sizeof (PKIX_ProcessingParams), + (PKIX_PL_Object **)¶msDuplicate, + plContext), + PKIX_PROCESSINGPARAMSCREATEFAILED); + + /* initialize fields */ + PKIX_DUPLICATE + (params->trustAnchors, + &(paramsDuplicate->trustAnchors), + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->hintCerts, &(paramsDuplicate->hintCerts), plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->constraints, + &(paramsDuplicate->constraints), + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->date, &(paramsDuplicate->date), plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->initialPolicies, + &(paramsDuplicate->initialPolicies), + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + paramsDuplicate->initialPolicyMappingInhibit = + params->initialPolicyMappingInhibit; + paramsDuplicate->initialAnyPolicyInhibit = + params->initialAnyPolicyInhibit; + paramsDuplicate->initialExplicitPolicy = params->initialExplicitPolicy; + paramsDuplicate->qualifiersRejected = params->qualifiersRejected; + + PKIX_DUPLICATE + (params->certChainCheckers, + &(paramsDuplicate->certChainCheckers), + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->revChecker, + &(paramsDuplicate->revChecker), + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->certStores, &(paramsDuplicate->certStores), plContext, + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_DUPLICATE + (params->resourceLimits, + &(paramsDuplicate->resourceLimits), + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + paramsDuplicate->isCrlRevocationCheckingEnabled = + params->isCrlRevocationCheckingEnabled; + + paramsDuplicate->isCrlRevocationCheckingEnabledWithNISTPolicy = + params->isCrlRevocationCheckingEnabledWithNISTPolicy; + + *pNewObject = (PKIX_PL_Object *)paramsDuplicate; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(paramsDuplicate); + } + + PKIX_RETURN(PROCESSINGPARAMS); + +} + +/* + * FUNCTION: pkix_ProcessingParams_RegisterSelf + * DESCRIPTION: + * Registers PKIX_PROCESSINGPARAMS_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_ProcessingParams_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_RegisterSelf"); + + entry.description = "ProcessingParams"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_ProcessingParams); + entry.destructor = pkix_ProcessingParams_Destroy; + entry.equalsFunction = pkix_ProcessingParams_Equals; + entry.hashcodeFunction = pkix_ProcessingParams_Hashcode; + entry.toStringFunction = pkix_ProcessingParams_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_ProcessingParams_Duplicate; + + systemClasses[PKIX_PROCESSINGPARAMS_TYPE] = entry; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_ProcessingParams_Create (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_Create( + PKIX_ProcessingParams **pParams, + void *plContext) +{ + PKIX_ProcessingParams *params = NULL; + + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_Create"); + PKIX_NULLCHECK_ONE(pParams); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_PROCESSINGPARAMS_TYPE, + sizeof (PKIX_ProcessingParams), + (PKIX_PL_Object **)¶ms, + plContext), + PKIX_COULDNOTCREATEPROCESSINGPARAMSOBJECT); + + /* initialize fields */ + PKIX_CHECK(PKIX_List_Create(¶ms->trustAnchors, plContext), + PKIX_LISTCREATEFAILED); + PKIX_CHECK(PKIX_List_SetImmutable(params->trustAnchors, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + PKIX_CHECK(PKIX_PL_Date_Create_UTCTime + (NULL, ¶ms->date, plContext), + PKIX_DATECREATEUTCTIMEFAILED); + + params->hintCerts = NULL; + params->constraints = NULL; + params->initialPolicies = NULL; + params->initialPolicyMappingInhibit = PKIX_FALSE; + params->initialAnyPolicyInhibit = PKIX_FALSE; + params->initialExplicitPolicy = PKIX_FALSE; + params->qualifiersRejected = PKIX_FALSE; + params->certChainCheckers = NULL; + params->revChecker = NULL; + params->certStores = NULL; + params->resourceLimits = NULL; + + params->isCrlRevocationCheckingEnabled = PKIX_TRUE; + + params->isCrlRevocationCheckingEnabledWithNISTPolicy = PKIX_TRUE; + + params->useAIAForCertFetching = PKIX_FALSE; + params->qualifyTargetCert = PKIX_TRUE; + params->useOnlyTrustAnchors = PKIX_TRUE; + + *pParams = params; + params = NULL; + +cleanup: + + PKIX_DECREF(params); + + PKIX_RETURN(PROCESSINGPARAMS); + +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetUseAIAForCertFetching + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetUseAIAForCertFetching( + PKIX_ProcessingParams *params, + PKIX_Boolean *pUseAIA, /* list of TrustAnchor */ + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetUseAIAForCertFetching"); + PKIX_NULLCHECK_TWO(params, pUseAIA); + + *pUseAIA = params->useAIAForCertFetching; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetUseAIAForCertFetching + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetUseAIAForCertFetching( + PKIX_ProcessingParams *params, + PKIX_Boolean useAIA, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetUseAIAForCertFetching"); + PKIX_NULLCHECK_ONE(params); + + params->useAIAForCertFetching = useAIA; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetQualifyTargetCert + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetValidateTargetCert( + PKIX_ProcessingParams *params, + PKIX_Boolean *pQualifyTargetCert, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_GetValidateTargetCert"); + PKIX_NULLCHECK_TWO(params, pQualifyTargetCert); + + *pQualifyTargetCert = params->qualifyTargetCert; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetQualifyTargetCert + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetQualifyTargetCert( + PKIX_ProcessingParams *params, + PKIX_Boolean qualifyTargetCert, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetQualifyTargetCert"); + PKIX_NULLCHECK_ONE(params); + + params->qualifyTargetCert = qualifyTargetCert; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetTrustAnchors + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetTrustAnchors( + PKIX_ProcessingParams *params, + PKIX_List *anchors, /* list of TrustAnchor */ + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetTrustAnchors"); + PKIX_NULLCHECK_TWO(params, anchors); + + PKIX_DECREF(params->trustAnchors); + + PKIX_INCREF(anchors); + params->trustAnchors = anchors; + PKIX_CHECK(PKIX_List_SetImmutable(params->trustAnchors, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + +cleanup: + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetTrustAnchors + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetTrustAnchors( + PKIX_ProcessingParams *params, + PKIX_List **pAnchors, /* list of TrustAnchor */ + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetTrustAnchors"); + PKIX_NULLCHECK_TWO(params, pAnchors); + + PKIX_INCREF(params->trustAnchors); + + *pAnchors = params->trustAnchors; + +cleanup: + PKIX_RETURN(PROCESSINGPARAMS); +} + +/** + * FUNCTION: PKIX_ProcessingParams_SetUseOnlyTrustAnchors + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetUseOnlyTrustAnchors( + PKIX_ProcessingParams *params, + PKIX_Boolean *pUseOnlyTrustAnchors, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetUseTrustAnchorsOnly"); + PKIX_NULLCHECK_TWO(params, pUseOnlyTrustAnchors); + + *pUseOnlyTrustAnchors = params->useOnlyTrustAnchors; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/** + * FUNCTION: PKIX_ProcessingParams_SetUseOnlyTrustAnchors + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetUseOnlyTrustAnchors( + PKIX_ProcessingParams *params, + PKIX_Boolean useOnlyTrustAnchors, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetUseTrustAnchorsOnly"); + PKIX_NULLCHECK_ONE(params); + + params->useOnlyTrustAnchors = useOnlyTrustAnchors; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetDate (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetDate( + PKIX_ProcessingParams *params, + PKIX_PL_Date **pDate, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetDate"); + PKIX_NULLCHECK_TWO(params, pDate); + + PKIX_INCREF(params->date); + *pDate = params->date; + +cleanup: + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetDate (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetDate( + PKIX_ProcessingParams *params, + PKIX_PL_Date *date, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetDate"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->date); + + PKIX_INCREF(date); + params->date = date; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + if (PKIX_ERROR_RECEIVED && params) { + PKIX_DECREF(params->date); + } + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetTargetCertConstraints + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetTargetCertConstraints( + PKIX_ProcessingParams *params, + PKIX_CertSelector **pConstraints, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_GetTargetCertConstraints"); + + PKIX_NULLCHECK_TWO(params, pConstraints); + + PKIX_INCREF(params->constraints); + *pConstraints = params->constraints; + +cleanup: + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetTargetCertConstraints + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetTargetCertConstraints( + PKIX_ProcessingParams *params, + PKIX_CertSelector *constraints, + void *plContext) +{ + + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetTargetCertConstraints"); + + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->constraints); + + PKIX_INCREF(constraints); + params->constraints = constraints; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + if (PKIX_ERROR_RECEIVED && params) { + PKIX_DECREF(params->constraints); + } + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetInitialPolicies + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetInitialPolicies( + PKIX_ProcessingParams *params, + PKIX_List **pInitPolicies, /* list of PKIX_PL_OID */ + void *plContext) +{ + + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_GetInitialPolicies"); + + PKIX_NULLCHECK_TWO(params, pInitPolicies); + + if (params->initialPolicies == NULL) { + PKIX_CHECK(PKIX_List_Create + (¶ms->initialPolicies, plContext), + PKIX_UNABLETOCREATELIST); + PKIX_CHECK(PKIX_List_SetImmutable + (params->initialPolicies, plContext), + PKIX_UNABLETOMAKELISTIMMUTABLE); + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + } + + PKIX_INCREF(params->initialPolicies); + *pInitPolicies = params->initialPolicies; + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetInitialPolicies + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetInitialPolicies( + PKIX_ProcessingParams *params, + PKIX_List *initPolicies, /* list of PKIX_PL_OID */ + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetInitialPolicies"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->initialPolicies); + + PKIX_INCREF(initPolicies); + params->initialPolicies = initPolicies; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + if (PKIX_ERROR_RECEIVED && params) { + PKIX_DECREF(params->initialPolicies); + } + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetPolicyQualifiersRejected + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetPolicyQualifiersRejected( + PKIX_ProcessingParams *params, + PKIX_Boolean *pRejected, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_GetPolicyQualifiersRejected"); + + PKIX_NULLCHECK_TWO(params, pRejected); + + *pRejected = params->qualifiersRejected; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetPolicyQualifiersRejected + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetPolicyQualifiersRejected( + PKIX_ProcessingParams *params, + PKIX_Boolean rejected, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetPolicyQualifiersRejected"); + + PKIX_NULLCHECK_ONE(params); + + params->qualifiersRejected = rejected; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetCertChainCheckers + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetCertChainCheckers( + PKIX_ProcessingParams *params, + PKIX_List **pCheckers, /* list of PKIX_CertChainChecker */ + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_GetCertChainCheckers"); + PKIX_NULLCHECK_TWO(params, pCheckers); + + PKIX_INCREF(params->certChainCheckers); + *pCheckers = params->certChainCheckers; + +cleanup: + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetCertChainCheckers + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetCertChainCheckers( + PKIX_ProcessingParams *params, + PKIX_List *checkers, /* list of PKIX_CertChainChecker */ + void *plContext) +{ + + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetCertChainCheckers"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->certChainCheckers); + + PKIX_INCREF(checkers); + params->certChainCheckers = checkers; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + if (PKIX_ERROR_RECEIVED && params) { + PKIX_DECREF(params->certChainCheckers); + } + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_AddCertChainCheckers + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_AddCertChainChecker( + PKIX_ProcessingParams *params, + PKIX_CertChainChecker *checker, + void *plContext) +{ + PKIX_List *list = NULL; + + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_AddCertChainChecker"); + PKIX_NULLCHECK_TWO(params, checker); + + if (params->certChainCheckers == NULL) { + + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + + params->certChainCheckers = list; + } + + PKIX_CHECK(PKIX_List_AppendItem + (params->certChainCheckers, (PKIX_PL_Object *)checker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + list = NULL; + +cleanup: + + if (list && params) { + PKIX_DECREF(params->certChainCheckers); + } + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetRevocationChecker + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetRevocationChecker( + PKIX_ProcessingParams *params, + PKIX_RevocationChecker **pChecker, + void *plContext) +{ + + PKIX_ENTER + (PROCESSINGPARAMS, "PKIX_ProcessingParams_GetRevocationCheckers"); + PKIX_NULLCHECK_TWO(params, pChecker); + + PKIX_INCREF(params->revChecker); + *pChecker = params->revChecker; + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetRevocationChecker + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetRevocationChecker( + PKIX_ProcessingParams *params, + PKIX_RevocationChecker *checker, + void *plContext) +{ + + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_InitRevocationChecker"); + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->revChecker); + PKIX_INCREF(checker); + params->revChecker = checker; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetCertStores + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetCertStores( + PKIX_ProcessingParams *params, + PKIX_List **pStores, /* list of PKIX_CertStore */ + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetCertStores"); + + PKIX_NULLCHECK_TWO(params, pStores); + + if (!params->certStores){ + PKIX_CHECK(PKIX_List_Create(¶ms->certStores, plContext), + PKIX_UNABLETOCREATELIST); + } + + PKIX_INCREF(params->certStores); + *pStores = params->certStores; + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetCertStores + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetCertStores( + PKIX_ProcessingParams *params, + PKIX_List *stores, /* list of PKIX_CertStore */ + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetCertStores"); + + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->certStores); + + PKIX_INCREF(stores); + params->certStores = stores; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + if (PKIX_ERROR_RECEIVED && params) { + PKIX_DECREF(params->certStores); + } + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_AddCertStore + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_AddCertStore( + PKIX_ProcessingParams *params, + PKIX_CertStore *store, + void *plContext) +{ + PKIX_List *certStores = NULL; + + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_AddCertStore"); + PKIX_NULLCHECK_TWO(params, store); + + PKIX_CHECK(PKIX_ProcessingParams_GetCertStores + (params, &certStores, plContext), + PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (certStores, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_DECREF(certStores); + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetResourceLimits + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetResourceLimits( + PKIX_ProcessingParams *params, + PKIX_ResourceLimits *resourceLimits, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetResourceLimits"); + + PKIX_NULLCHECK_TWO(params, resourceLimits); + + PKIX_DECREF(params->resourceLimits); + PKIX_INCREF(resourceLimits); + params->resourceLimits = resourceLimits; + +cleanup: + if (PKIX_ERROR_RECEIVED && params) { + PKIX_DECREF(params->resourceLimits); + } + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetResourceLimits + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetResourceLimits( + PKIX_ProcessingParams *params, + PKIX_ResourceLimits **pResourceLimits, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_GetResourceLimits"); + + PKIX_NULLCHECK_TWO(params, pResourceLimits); + + PKIX_INCREF(params->resourceLimits); + *pResourceLimits = params->resourceLimits; + +cleanup: + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_IsAnyPolicyInhibited + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_IsAnyPolicyInhibited( + PKIX_ProcessingParams *params, + PKIX_Boolean *pInhibited, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_IsAnyPolicyInhibited"); + + PKIX_NULLCHECK_TWO(params, pInhibited); + + *pInhibited = params->initialAnyPolicyInhibit; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetAnyPolicyInhibited + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetAnyPolicyInhibited( + PKIX_ProcessingParams *params, + PKIX_Boolean inhibited, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetAnyPolicyInhibited"); + + PKIX_NULLCHECK_ONE(params); + + params->initialAnyPolicyInhibit = inhibited; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_IsExplicitPolicyRequired + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_IsExplicitPolicyRequired( + PKIX_ProcessingParams *params, + PKIX_Boolean *pRequired, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_IsExplicitPolicyRequired"); + + PKIX_NULLCHECK_TWO(params, pRequired); + + *pRequired = params->initialExplicitPolicy; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetExplicitPolicyRequired + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetExplicitPolicyRequired( + PKIX_ProcessingParams *params, + PKIX_Boolean required, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetExplicitPolicyRequired"); + + PKIX_NULLCHECK_ONE(params); + + params->initialExplicitPolicy = required; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_IsPolicyMappingInhibited + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_IsPolicyMappingInhibited( + PKIX_ProcessingParams *params, + PKIX_Boolean *pInhibited, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_IsPolicyMappingInhibited"); + + PKIX_NULLCHECK_TWO(params, pInhibited); + + *pInhibited = params->initialPolicyMappingInhibit; + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetPolicyMappingInhibited + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetPolicyMappingInhibited( + PKIX_ProcessingParams *params, + PKIX_Boolean inhibited, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, + "PKIX_ProcessingParams_SetPolicyMappingInhibited"); + + PKIX_NULLCHECK_ONE(params); + + params->initialPolicyMappingInhibit = inhibited; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)params, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_SetHintCerts + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_SetHintCerts( + PKIX_ProcessingParams *params, + PKIX_List *hintCerts, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetHintCerts"); + + PKIX_NULLCHECK_ONE(params); + + PKIX_DECREF(params->hintCerts); + PKIX_INCREF(hintCerts); + params->hintCerts = hintCerts; + +cleanup: + if (PKIX_ERROR_RECEIVED && params) { + PKIX_DECREF(params->hintCerts); + } + + PKIX_RETURN(PROCESSINGPARAMS); +} + +/* + * FUNCTION: PKIX_ProcessingParams_GetHintCerts + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ProcessingParams_GetHintCerts( + PKIX_ProcessingParams *params, + PKIX_List **pHintCerts, + void *plContext) +{ + PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetHintCerts"); + + PKIX_NULLCHECK_TWO(params, pHintCerts); + + PKIX_INCREF(params->hintCerts); + *pHintCerts = params->hintCerts; + +cleanup: + PKIX_RETURN(PROCESSINGPARAMS); +} diff --git a/security/nss/lib/libpkix/pkix/params/pkix_procparams.h b/security/nss/lib/libpkix/pkix/params/pkix_procparams.h new file mode 100644 index 0000000000..599f5d4988 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/pkix_procparams.h @@ -0,0 +1,50 @@ +/* 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_procparams.h + * + * ProcessingParams Object Type Definition + * + */ + +#ifndef _PKIX_PROCESSINGPARAMS_H +#define _PKIX_PROCESSINGPARAMS_H + +#include "pkix_tools.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_ProcessingParamsStruct { + PKIX_List *trustAnchors; /* Never NULL */ + PKIX_List *hintCerts; /* user-supplied partial chain, may be NULL */ + PKIX_CertSelector *constraints; + PKIX_PL_Date *date; + PKIX_List *initialPolicies; /* list of PKIX_PL_OID */ + PKIX_Boolean initialPolicyMappingInhibit; + PKIX_Boolean initialAnyPolicyInhibit; + PKIX_Boolean initialExplicitPolicy; + PKIX_Boolean qualifiersRejected; + PKIX_List *certChainCheckers; + PKIX_List *certStores; + PKIX_Boolean isCrlRevocationCheckingEnabled; + PKIX_Boolean isCrlRevocationCheckingEnabledWithNISTPolicy; + PKIX_RevocationChecker *revChecker; + PKIX_ResourceLimits *resourceLimits; + PKIX_Boolean useAIAForCertFetching; + PKIX_Boolean qualifyTargetCert; + PKIX_Boolean useOnlyTrustAnchors; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_ProcessingParams_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PROCESSINGPARAMS_H */ diff --git a/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c new file mode 100644 index 0000000000..de93e9d771 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c @@ -0,0 +1,433 @@ +/* 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_resourcelimits.c + * + * Resourcelimits Params Object Functions + * + */ + +#include "pkix_resourcelimits.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_ResourceLimits_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ResourceLimits_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ResourceLimits *rLimits = NULL; + + PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a ResourceLimits object */ + PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext), + PKIX_OBJECTNOTRESOURCELIMITS); + + rLimits = (PKIX_ResourceLimits *)object; + + rLimits->maxTime = 0; + rLimits->maxFanout = 0; + rLimits->maxDepth = 0; + rLimits->maxCertsNumber = 0; + rLimits->maxCrlsNumber = 0; + +cleanup: + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: pkix_ResourceLimits_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ResourceLimits_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_ResourceLimits *firstRLimits = NULL; + PKIX_ResourceLimits *secondRLimits = NULL; + + PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_RESOURCELIMITS_TYPE, plContext), + PKIX_FIRSTOBJECTNOTRESOURCELIMITS); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_RESOURCELIMITS_TYPE) goto cleanup; + + firstRLimits = (PKIX_ResourceLimits *)first; + secondRLimits = (PKIX_ResourceLimits *)second; + + cmpResult = (firstRLimits->maxTime == secondRLimits->maxTime) && + (firstRLimits->maxFanout == secondRLimits->maxFanout) && + (firstRLimits->maxDepth == secondRLimits->maxDepth) && + (firstRLimits->maxCertsNumber == + secondRLimits->maxCertsNumber) && + (firstRLimits->maxCrlsNumber == + secondRLimits->maxCrlsNumber); + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: pkix_ResourceLimits_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ResourceLimits_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_ResourceLimits *rLimits = NULL; + PKIX_UInt32 hash = 0; + + PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext), + PKIX_OBJECTNOTRESOURCELIMITS); + + rLimits = (PKIX_ResourceLimits*)object; + + hash = 31 * rLimits->maxTime + (rLimits->maxFanout << 1) + + (rLimits->maxDepth << 2) + (rLimits->maxCertsNumber << 3) + + rLimits->maxCrlsNumber; + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: pkix_ResourceLimits_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ResourceLimits_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_ResourceLimits *rLimits = NULL; + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *rLimitsString = NULL; + + PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext), + PKIX_OBJECTNOTRESOURCELIMITS); + + /* maxCertsNumber and maxCrlsNumber are not supported */ + asciiFormat = + "[\n" + "\tMaxTime: \t\t%d\n" + "\tMaxFanout: \t\t%d\n" + "\tMaxDepth: \t\t%d\n" + "]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + rLimits = (PKIX_ResourceLimits*)object; + + PKIX_CHECK(PKIX_PL_Sprintf + (&rLimitsString, + plContext, + formatString, + rLimits->maxTime, + rLimits->maxFanout, + rLimits->maxDepth), + PKIX_SPRINTFFAILED); + + *pString = rLimitsString; + +cleanup: + + PKIX_DECREF(formatString); + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: pkix_ResourceLimits_RegisterSelf + * DESCRIPTION: + * Registers PKIX_RESOURCELIMITS_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_ResourceLimits_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_RegisterSelf"); + + entry.description = "ResourceLimits"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_ResourceLimits); + entry.destructor = pkix_ResourceLimits_Destroy; + entry.equalsFunction = pkix_ResourceLimits_Equals; + entry.hashcodeFunction = pkix_ResourceLimits_Hashcode; + entry.toStringFunction = pkix_ResourceLimits_ToString; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_RESOURCELIMITS_TYPE] = entry; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_ResourceLimits_Create (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_Create( + PKIX_ResourceLimits **pResourceLimits, + void *plContext) +{ + PKIX_ResourceLimits *rLimits = NULL; + + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_Create"); + PKIX_NULLCHECK_ONE(pResourceLimits); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_RESOURCELIMITS_TYPE, + sizeof (PKIX_ResourceLimits), + (PKIX_PL_Object **)&rLimits, + plContext), + PKIX_COULDNOTCREATERESOURCELIMITOBJECT); + + /* initialize fields */ + rLimits->maxTime = 0; + rLimits->maxFanout = 0; + rLimits->maxDepth = 0; + rLimits->maxCertsNumber = 0; + rLimits->maxCrlsNumber = 0; + + *pResourceLimits = rLimits; + +cleanup: + + PKIX_RETURN(RESOURCELIMITS); + +} + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxTime + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_GetMaxTime( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 *pMaxTime, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxTime"); + PKIX_NULLCHECK_TWO(rLimits, pMaxTime); + + *pMaxTime = rLimits->maxTime; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxTime + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_SetMaxTime( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 maxTime, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxTime"); + PKIX_NULLCHECK_ONE(rLimits); + + rLimits->maxTime = maxTime; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxFanout + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_GetMaxFanout( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 *pMaxFanout, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxFanout"); + PKIX_NULLCHECK_TWO(rLimits, pMaxFanout); + + *pMaxFanout = rLimits->maxFanout; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxFanout + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_SetMaxFanout( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 maxFanout, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxFanout"); + PKIX_NULLCHECK_ONE(rLimits); + + rLimits->maxFanout = maxFanout; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxDepth + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_GetMaxDepth( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 *pMaxDepth, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxDepth"); + PKIX_NULLCHECK_TWO(rLimits, pMaxDepth); + + *pMaxDepth = rLimits->maxDepth; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxDepth + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_SetMaxDepth( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 maxDepth, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxDepth"); + PKIX_NULLCHECK_ONE(rLimits); + + rLimits->maxDepth = maxDepth; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCerts + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_GetMaxNumberOfCerts( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 *pMaxNumber, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxNumberOfCerts"); + PKIX_NULLCHECK_TWO(rLimits, pMaxNumber); + + *pMaxNumber = rLimits->maxCertsNumber; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCerts + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_SetMaxNumberOfCerts( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 maxNumber, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxNumberOfCerts"); + PKIX_NULLCHECK_ONE(rLimits); + + rLimits->maxCertsNumber = maxNumber; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCRLs + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_GetMaxNumberOfCRLs( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 *pMaxNumber, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxNumberOfCRLs"); + PKIX_NULLCHECK_TWO(rLimits, pMaxNumber); + + *pMaxNumber = rLimits->maxCrlsNumber; + + PKIX_RETURN(RESOURCELIMITS); +} + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCRLs + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ResourceLimits_SetMaxNumberOfCRLs( + PKIX_ResourceLimits *rLimits, + PKIX_UInt32 maxNumber, + void *plContext) +{ + PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxNumberOfCRLs"); + PKIX_NULLCHECK_ONE(rLimits); + + rLimits->maxCrlsNumber = maxNumber; + + PKIX_RETURN(RESOURCELIMITS); +} diff --git a/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h new file mode 100644 index 0000000000..c4f582ce6f --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h @@ -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_resourcelimits.h + * + * ResourceLimits Object Type Definition + * + */ + +#ifndef _PKIX_RESOURCELIMITS_H +#define _PKIX_RESOURCELIMITS_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_ResourceLimitsStruct { + PKIX_UInt32 maxTime; + PKIX_UInt32 maxFanout; + PKIX_UInt32 maxDepth; + PKIX_UInt32 maxCertsNumber; + PKIX_UInt32 maxCrlsNumber; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_ResourceLimits_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_RESOURCELIMITS_H */ diff --git a/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c new file mode 100644 index 0000000000..ced16d2902 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c @@ -0,0 +1,525 @@ +/* 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_trustanchor.c + * + * TrustAnchor Object Functions + * + */ + +#include "pkix_trustanchor.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_TrustAnchor_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_TrustAnchor_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_TrustAnchor *anchor = NULL; + + PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a trust anchor */ + PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext), + PKIX_OBJECTNOTTRUSTANCHOR); + + anchor = (PKIX_TrustAnchor *)object; + + PKIX_DECREF(anchor->trustedCert); + PKIX_DECREF(anchor->caName); + PKIX_DECREF(anchor->caPubKey); + PKIX_DECREF(anchor->nameConstraints); + +cleanup: + + PKIX_RETURN(TRUSTANCHOR); +} + +/* + * FUNCTION: pkix_TrustAnchor_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_TrustAnchor_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_TrustAnchor *firstAnchor = NULL; + PKIX_TrustAnchor *secondAnchor = NULL; + PKIX_PL_Cert *firstCert = NULL; + PKIX_PL_Cert *secondCert = NULL; + + PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_TRUSTANCHOR_TYPE, plContext), + PKIX_FIRSTOBJECTNOTTRUSTANCHOR); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_TRUSTANCHOR_TYPE) goto cleanup; + + firstAnchor = (PKIX_TrustAnchor *)first; + secondAnchor = (PKIX_TrustAnchor *)second; + + firstCert = firstAnchor->trustedCert; + secondCert = secondAnchor->trustedCert; + + if ((firstCert && !secondCert) || (!firstCert && secondCert)){ + goto cleanup; + } + + if (firstCert && secondCert){ + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstCert, + (PKIX_PL_Object *)secondCert, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + } else { + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstAnchor->caName, + (PKIX_PL_Object *)secondAnchor->caName, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstAnchor->caPubKey, + (PKIX_PL_Object *)secondAnchor->caPubKey, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_EQUALS + (firstAnchor->nameConstraints, + secondAnchor->nameConstraints, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + } + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(TRUSTANCHOR); +} + +/* + * FUNCTION: pkix_TrustAnchor_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_TrustAnchor_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_TrustAnchor *anchor = NULL; + PKIX_PL_Cert *cert = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 certHash = 0; + PKIX_UInt32 nameHash = 0; + PKIX_UInt32 pubKeyHash = 0; + PKIX_UInt32 ncHash = 0; + + PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext), + PKIX_OBJECTNOTTRUSTANCHOR); + + anchor = (PKIX_TrustAnchor*)object; + cert = anchor->trustedCert; + + if (cert){ + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)cert, + &certHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + hash = certHash; + + } else { + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)anchor->caName, + &nameHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)anchor->caPubKey, + &pubKeyHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE(anchor->nameConstraints, &ncHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + hash = 31 * nameHash + pubKeyHash + ncHash; + + } + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(TRUSTANCHOR); +} + +/* + * FUNCTION: pkix_TrustAnchor_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_TrustAnchor_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_TrustAnchor *anchor = NULL; + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *anchorString = NULL; + PKIX_PL_String *certString = NULL; + PKIX_PL_String *nameString = NULL; + PKIX_PL_String *pubKeyString = NULL; + PKIX_PL_String *nameConstraintsString = NULL; + + PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext), + PKIX_OBJECTNOTTRUSTANCHOR); + + anchor = (PKIX_TrustAnchor*)object; + + if (anchor->trustedCert){ + asciiFormat = + "[\n" + "\tTrusted Cert: %s\n" + "]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)anchor->trustedCert, + &certString, + plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&anchorString, + plContext, + formatString, + certString), + PKIX_SPRINTFFAILED); + } else { + asciiFormat = + "[\n" + "\tTrusted CA Name: %s\n" + "\tTrusted CA PublicKey: %s\n" + "\tInitial Name Constraints:%s\n" + "]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)anchor->caName, + &nameString, + plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)anchor->caPubKey, + &pubKeyString, + plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (anchor->nameConstraints, + &nameConstraintsString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&anchorString, + plContext, + formatString, + nameString, + pubKeyString, + nameConstraintsString), + PKIX_SPRINTFFAILED); + } + + *pString = anchorString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(certString); + PKIX_DECREF(nameString); + PKIX_DECREF(pubKeyString); + PKIX_DECREF(nameConstraintsString); + + PKIX_RETURN(TRUSTANCHOR); +} + +/* + * FUNCTION: pkix_TrustAnchor_RegisterSelf + * DESCRIPTION: + * Registers PKIX_TRUSTANCHOR_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_TrustAnchor_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_RegisterSelf"); + + entry.description = "TrustAnchor"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_TrustAnchor); + entry.destructor = pkix_TrustAnchor_Destroy; + entry.equalsFunction = pkix_TrustAnchor_Equals; + entry.hashcodeFunction = pkix_TrustAnchor_Hashcode; + entry.toStringFunction = pkix_TrustAnchor_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_TRUSTANCHOR_TYPE] = entry; + + PKIX_RETURN(TRUSTANCHOR); +} + +/* --Public-Functions--------------------------------------------- */ + + +/* + * FUNCTION: PKIX_TrustAnchor_CreateWithCert (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_TrustAnchor_CreateWithCert( + PKIX_PL_Cert *cert, + PKIX_TrustAnchor **pAnchor, + void *plContext) +{ + PKIX_TrustAnchor *anchor = NULL; + + PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithCert"); + PKIX_NULLCHECK_TWO(cert, pAnchor); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_TRUSTANCHOR_TYPE, + sizeof (PKIX_TrustAnchor), + (PKIX_PL_Object **)&anchor, + plContext), + PKIX_COULDNOTCREATETRUSTANCHOROBJECT); + + /* initialize fields */ + PKIX_CHECK( + PKIX_PL_Cert_SetAsTrustAnchor(cert, plContext), + PKIX_CERTSETASTRUSTANCHORFAILED); + + PKIX_INCREF(cert); + anchor->trustedCert = cert; + + anchor->caName = NULL; + anchor->caPubKey = NULL; + + PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints + (anchor->trustedCert, &anchor->nameConstraints, plContext), + PKIX_CERTGETNAMECONSTRAINTSFAILED); + + + *pAnchor = anchor; + anchor = NULL; + +cleanup: + + PKIX_DECREF(anchor); + + PKIX_RETURN(TRUSTANCHOR); + +} + +/* + * FUNCTION: PKIX_TrustAnchor_CreateWithNameKeyPair + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_TrustAnchor_CreateWithNameKeyPair( + PKIX_PL_X500Name *name, + PKIX_PL_PublicKey *pubKey, + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_TrustAnchor **pAnchor, + void *plContext) +{ + PKIX_TrustAnchor *anchor = NULL; + + PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithNameKeyPair"); + +#ifndef BUILD_LIBPKIX_TESTS + /* Nss creates trust anchors by using PKIX_TrustAnchor_CreateWithCert + * function as the complete trusted cert structure, and not only cert + * public key, is required for chain building and validation processes. + * Restricting this function for been used only in libpkix unit + * tests. */ + PKIX_ERROR(PKIX_FUNCTIONMUSTNOTBEUSED); +#endif + + PKIX_NULLCHECK_THREE(name, pubKey, pAnchor); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_TRUSTANCHOR_TYPE, + sizeof (PKIX_TrustAnchor), + (PKIX_PL_Object **)&anchor, + plContext), + PKIX_COULDNOTCREATETRUSTANCHOROBJECT); + + /* initialize fields */ + anchor->trustedCert = NULL; + + PKIX_INCREF(name); + anchor->caName = name; + + PKIX_INCREF(pubKey); + anchor->caPubKey = pubKey; + + PKIX_INCREF(nameConstraints); + anchor->nameConstraints = nameConstraints; + + *pAnchor = anchor; + anchor = NULL; +cleanup: + + PKIX_DECREF(anchor); + + PKIX_RETURN(TRUSTANCHOR); +} + +/* + * FUNCTION: PKIX_TrustAnchor_GetTrustedCert (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_TrustAnchor_GetTrustedCert( + PKIX_TrustAnchor *anchor, + PKIX_PL_Cert **pCert, + void *plContext) +{ + PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetTrustedCert"); + PKIX_NULLCHECK_TWO(anchor, pCert); + + PKIX_INCREF(anchor->trustedCert); + + *pCert = anchor->trustedCert; + +cleanup: + PKIX_RETURN(TRUSTANCHOR); + +} + +/* + * FUNCTION: PKIX_TrustAnchor_GetCAName (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_TrustAnchor_GetCAName( + PKIX_TrustAnchor *anchor, + PKIX_PL_X500Name **pCAName, + void *plContext) +{ + PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAName"); + PKIX_NULLCHECK_TWO(anchor, pCAName); + + PKIX_INCREF(anchor->caName); + + *pCAName = anchor->caName; + +cleanup: + PKIX_RETURN(TRUSTANCHOR); + +} + +/* + * FUNCTION: PKIX_TrustAnchor_GetCAPublicKey (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_TrustAnchor_GetCAPublicKey( + PKIX_TrustAnchor *anchor, + PKIX_PL_PublicKey **pPubKey, + void *plContext) +{ + PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAPublicKey"); + PKIX_NULLCHECK_TWO(anchor, pPubKey); + + PKIX_INCREF(anchor->caPubKey); + + *pPubKey = anchor->caPubKey; + +cleanup: + PKIX_RETURN(TRUSTANCHOR); +} + +/* + * FUNCTION: PKIX_TrustAnchor_GetNameConstraints + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_TrustAnchor_GetNameConstraints( + PKIX_TrustAnchor *anchor, + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext) +{ + PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetNameConstraints"); + PKIX_NULLCHECK_TWO(anchor, pNameConstraints); + + PKIX_INCREF(anchor->nameConstraints); + + *pNameConstraints = anchor->nameConstraints; + +cleanup: + PKIX_RETURN(TRUSTANCHOR); +} diff --git a/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h new file mode 100644 index 0000000000..e3ceb7fd33 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h @@ -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/. */ +/* + * pkix_trustanchor.h + * + * TrustAnchor Object Type Definition + * + */ + +#ifndef _PKIX_TRUSTANCHOR_H +#define _PKIX_TRUSTANCHOR_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_TrustAnchorStruct { + PKIX_PL_Cert *trustedCert; + PKIX_PL_X500Name *caName; + PKIX_PL_PublicKey *caPubKey; + PKIX_PL_CertNameConstraints *nameConstraints; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_TrustAnchor_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_TRUSTANCHOR_H */ diff --git a/security/nss/lib/libpkix/pkix/params/pkix_valparams.c b/security/nss/lib/libpkix/pkix/params/pkix_valparams.c new file mode 100644 index 0000000000..83c3d2b08f --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/pkix_valparams.c @@ -0,0 +1,335 @@ +/* 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_valparams.c + * + * Validate Params Object Functions + * + */ + +#include "pkix_valparams.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_ValidateParams_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateParams_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ValidateParams *params = NULL; + + PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a validate params object */ + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext), + PKIX_OBJECTNOTVALIDATEPARAMS); + + params = (PKIX_ValidateParams *)object; + + PKIX_DECREF(params->procParams); + PKIX_DECREF(params->chain); + +cleanup: + + PKIX_RETURN(VALIDATEPARAMS); +} + +/* + * FUNCTION: pkix_ValidateParams_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateParams_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_ValidateParams *firstValParams = NULL; + PKIX_ValidateParams *secondValParams = NULL; + + PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_VALIDATEPARAMS_TYPE, plContext), + PKIX_FIRSTOBJECTNOTVALIDATEPARAMS); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_VALIDATEPARAMS_TYPE) goto cleanup; + + firstValParams = (PKIX_ValidateParams *)first; + secondValParams = (PKIX_ValidateParams *)second; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstValParams->procParams, + (PKIX_PL_Object *)secondValParams->procParams, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstValParams->chain, + (PKIX_PL_Object *)secondValParams->chain, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(VALIDATEPARAMS); +} + +/* + * FUNCTION: pkix_ValidateParams_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateParams_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_ValidateParams *valParams = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 procParamsHash = 0; + PKIX_UInt32 chainHash = 0; + + PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext), + PKIX_OBJECTNOTVALIDATEPARAMS); + + valParams = (PKIX_ValidateParams*)object; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)valParams->procParams, + &procParamsHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)valParams->chain, + &chainHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + hash = 31 * procParamsHash + chainHash; + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(VALIDATEPARAMS); +} + +/* + * FUNCTION: pkix_ValidateParams_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateParams_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_ValidateParams *valParams = NULL; + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *valParamsString = NULL; + + PKIX_PL_String *procParamsString = NULL; + PKIX_PL_String *chainString = NULL; + + PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext), + PKIX_OBJECTNOTVALIDATEPARAMS); + + asciiFormat = + "[\n" + "\tProcessing Params: \n" + "\t********BEGIN PROCESSING PARAMS********\n" + "\t\t%s\n" + "\t********END PROCESSING PARAMS********\n" + "\tChain: \t\t%s\n" + "]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + valParams = (PKIX_ValidateParams*)object; + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)valParams->procParams, + &procParamsString, + plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)valParams->chain, + &chainString, + plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&valParamsString, + plContext, + formatString, + procParamsString, + chainString), + PKIX_SPRINTFFAILED); + + *pString = valParamsString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(procParamsString); + PKIX_DECREF(chainString); + + PKIX_RETURN(VALIDATEPARAMS); +} + +/* + * FUNCTION: pkix_ValidateParams_RegisterSelf + * DESCRIPTION: + * Registers PKIX_VALIDATEPARAMS_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_ValidateParams_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_RegisterSelf"); + + entry.description = "ValidateParams"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_ValidateParams); + entry.destructor = pkix_ValidateParams_Destroy; + entry.equalsFunction = pkix_ValidateParams_Equals; + entry.hashcodeFunction = pkix_ValidateParams_Hashcode; + entry.toStringFunction = pkix_ValidateParams_ToString; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_VALIDATEPARAMS_TYPE] = entry; + + PKIX_RETURN(VALIDATEPARAMS); +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_ValidateParams_Create (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ValidateParams_Create( + PKIX_ProcessingParams *procParams, + PKIX_List *chain, + PKIX_ValidateParams **pParams, + void *plContext) +{ + PKIX_ValidateParams *params = NULL; + + PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_Create"); + PKIX_NULLCHECK_THREE(procParams, chain, pParams); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_VALIDATEPARAMS_TYPE, + sizeof (PKIX_ValidateParams), + (PKIX_PL_Object **)¶ms, + plContext), + PKIX_COULDNOTCREATEVALIDATEPARAMSOBJECT); + + /* initialize fields */ + PKIX_INCREF(procParams); + params->procParams = procParams; + + PKIX_INCREF(chain); + params->chain = chain; + + *pParams = params; + params = NULL; + +cleanup: + + PKIX_DECREF(params); + + PKIX_RETURN(VALIDATEPARAMS); + +} + +/* + * FUNCTION: PKIX_ValidateParams_GetProcessingParams + * (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ValidateParams_GetProcessingParams( + PKIX_ValidateParams *valParams, + PKIX_ProcessingParams **pProcParams, + void *plContext) +{ + PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_GetProcessingParams"); + PKIX_NULLCHECK_TWO(valParams, pProcParams); + + PKIX_INCREF(valParams->procParams); + + *pProcParams = valParams->procParams; + +cleanup: + PKIX_RETURN(VALIDATEPARAMS); +} + +/* + * FUNCTION: PKIX_ValidateParams_GetCertChain (see comments in pkix_params.h) + */ +PKIX_Error * +PKIX_ValidateParams_GetCertChain( + PKIX_ValidateParams *valParams, + PKIX_List **pChain, + void *plContext) +{ + PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_GetCertChain"); + PKIX_NULLCHECK_TWO(valParams, pChain); + + PKIX_INCREF(valParams->chain); + + *pChain = valParams->chain; + +cleanup: + PKIX_RETURN(VALIDATEPARAMS); +} diff --git a/security/nss/lib/libpkix/pkix/params/pkix_valparams.h b/security/nss/lib/libpkix/pkix/params/pkix_valparams.h new file mode 100644 index 0000000000..93b754f712 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/params/pkix_valparams.h @@ -0,0 +1,33 @@ +/* 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_valparams.h + * + * ValidateParams Object Type Definition + * + */ + +#ifndef _PKIX_VALIDATEPARAMS_H +#define _PKIX_VALIDATEPARAMS_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_ValidateParamsStruct { + PKIX_ProcessingParams *procParams; /* Never NULL */ + PKIX_List *chain; /* Never NULL */ +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_ValidateParams_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_VALIDATEPARAMS_H */ diff --git a/security/nss/lib/libpkix/pkix/results/Makefile b/security/nss/lib/libpkix/pkix/results/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/Makefile @@ -0,0 +1,46 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/results/exports.gyp b/security/nss/lib/libpkix/pkix/results/exports.gyp new file mode 100644 index 0000000000..dfff689033 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/exports.gyp @@ -0,0 +1,28 @@ +# 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_results_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_buildresult.h', + 'pkix_policynode.h', + 'pkix_valresult.h', + 'pkix_verifynode.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/results/manifest.mn b/security/nss/lib/libpkix/pkix/results/manifest.mn new file mode 100644 index 0000000000..bec0270fb6 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/manifest.mn @@ -0,0 +1,24 @@ +# +# 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 = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_buildresult.h \ + pkix_policynode.h \ + pkix_valresult.h \ + pkix_verifynode.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_buildresult.c \ + pkix_policynode.c \ + pkix_valresult.c \ + pkix_verifynode.c \ + $(NULL) + +LIBRARY_NAME = pkixresults +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c new file mode 100644 index 0000000000..7d35119bcb --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c @@ -0,0 +1,362 @@ +/* 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_buildresult.c + * + * BuildResult Object Functions + * + */ + +#include "pkix_buildresult.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_BuildResult_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_BuildResult_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_BuildResult *result = NULL; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a build result object */ + PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext), + PKIX_OBJECTNOTBUILDRESULT); + + result = (PKIX_BuildResult *)object; + + PKIX_DECREF(result->valResult); + PKIX_DECREF(result->certChain); + +cleanup: + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_BuildResult_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_BuildResult *firstBuildResult = NULL; + PKIX_BuildResult *secondBuildResult = NULL; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_BUILDRESULT_TYPE, plContext), + PKIX_FIRSTOBJECTNOTBUILDRESULT); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_BUILDRESULT_TYPE) goto cleanup; + + firstBuildResult = (PKIX_BuildResult *)first; + secondBuildResult = (PKIX_BuildResult *)second; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstBuildResult->valResult, + (PKIX_PL_Object *)secondBuildResult->valResult, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstBuildResult->certChain, + (PKIX_PL_Object *)secondBuildResult->certChain, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + /* + * The remaining case is that both are null, + * which we consider equality. + * cmpResult = PKIX_TRUE; + */ + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_BuildResult_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_BuildResult *buildResult = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 valResultHash = 0; + PKIX_UInt32 certChainHash = 0; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext), + PKIX_OBJECTNOTBUILDRESULT); + + buildResult = (PKIX_BuildResult*)object; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)buildResult->valResult, + &valResultHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)buildResult->certChain, + &certChainHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + hash = 31*(31 * valResultHash + certChainHash); + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_BuildResult_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_BuildResult *buildResult = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *buildResultString = NULL; + + PKIX_ValidateResult *valResult = NULL; + PKIX_List *certChain = NULL; + + PKIX_PL_String *valResultString = NULL; + PKIX_PL_String *certChainString = NULL; + + char *asciiFormat = + "[\n" + "\tValidateResult: \t\t%s" + "\tCertChain: \t\t%s\n" + "]\n"; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext), + PKIX_OBJECTNOTBUILDRESULT); + + buildResult = (PKIX_BuildResult*)object; + + valResult = buildResult->valResult; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)valResult, &valResultString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + certChain = buildResult->certChain; + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)certChain, &certChainString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&buildResultString, + plContext, + formatString, + valResultString, + certChainString), + PKIX_SPRINTFFAILED); + + *pString = buildResultString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(valResultString); + PKIX_DECREF(certChainString); + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_RegisterSelf + * DESCRIPTION: + * Registers PKIX_BUILDRESULT_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_BuildResult_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_RegisterSelf"); + + entry.description = "BuildResult"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_BuildResult); + entry.destructor = pkix_BuildResult_Destroy; + entry.equalsFunction = pkix_BuildResult_Equals; + entry.hashcodeFunction = pkix_BuildResult_Hashcode; + entry.toStringFunction = pkix_BuildResult_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_BUILDRESULT_TYPE] = entry; + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_Create + * DESCRIPTION: + * + * Creates a new BuildResult Object using the ValidateResult pointed to by + * "valResult" and the List pointed to by "certChain", and stores it at + * "pResult". + * + * PARAMETERS + * "valResult" + * Address of ValidateResult component. Must be non-NULL. + * "certChain + * Address of List component. Must be non-NULL. + * "pResult" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_BuildResult_Create( + PKIX_ValidateResult *valResult, + PKIX_List *certChain, + PKIX_BuildResult **pResult, + void *plContext) +{ + PKIX_BuildResult *result = NULL; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Create"); + PKIX_NULLCHECK_THREE(valResult, certChain, pResult); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_BUILDRESULT_TYPE, + sizeof (PKIX_BuildResult), + (PKIX_PL_Object **)&result, + plContext), + PKIX_COULDNOTCREATEBUILDRESULTOBJECT); + + /* initialize fields */ + + PKIX_INCREF(valResult); + result->valResult = valResult; + + PKIX_INCREF(certChain); + result->certChain = certChain; + + PKIX_CHECK(PKIX_List_SetImmutable(result->certChain, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pResult = result; + result = NULL; + +cleanup: + + PKIX_DECREF(result); + + PKIX_RETURN(BUILDRESULT); + +} + +/* --Public-Functions--------------------------------------------- */ + + +/* + * FUNCTION: PKIX_BuildResult_GetValidateResult + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_BuildResult_GetValidateResult( + PKIX_BuildResult *result, + PKIX_ValidateResult **pResult, + void *plContext) +{ + PKIX_ENTER(BUILDRESULT, "PKIX_BuildResult_GetValidateResult"); + PKIX_NULLCHECK_TWO(result, pResult); + + PKIX_INCREF(result->valResult); + *pResult = result->valResult; + +cleanup: + PKIX_RETURN(BUILDRESULT); +} + + + +/* + * FUNCTION: PKIX_BuildResult_GetCertChain + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_BuildResult_GetCertChain( + PKIX_BuildResult *result, + PKIX_List **pChain, + void *plContext) +{ + PKIX_ENTER(BUILDRESULT, "PKIX_BuildResult_GetCertChain"); + PKIX_NULLCHECK_TWO(result, pChain); + + PKIX_INCREF(result->certChain); + *pChain = result->certChain; + +cleanup: + PKIX_RETURN(BUILDRESULT); +} diff --git a/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h new file mode 100644 index 0000000000..b43f12ba14 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h @@ -0,0 +1,40 @@ +/* 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_buildresult.h + * + * BuildResult Object Type Definition + * + */ + +#ifndef _PKIX_BUILDRESULT_H +#define _PKIX_BUILDRESULT_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_BuildResultStruct { + PKIX_ValidateResult *valResult; + PKIX_List *certChain; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_BuildResult_Create( + PKIX_ValidateResult *valResult, + PKIX_List *certChain, + PKIX_BuildResult **pResult, + void *plContext); + +PKIX_Error *pkix_BuildResult_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_BUILDRESULT_H */ diff --git a/security/nss/lib/libpkix/pkix/results/pkix_policynode.c b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c new file mode 100644 index 0000000000..fd8cee982b --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c @@ -0,0 +1,1377 @@ +/* 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_policynode.c + * + * Policy Node Object Type Definition + * + */ + +#include "pkix_policynode.h" + +/* --Private-PolicyNode-Functions---------------------------------- */ + +/* + * FUNCTION: pkix_PolicyNode_GetChildrenMutable + * DESCRIPTION: + * + * Retrieves the List of PolicyNodes representing the child nodes of the + * Policy Node pointed to by "node" and stores it at "pChildren". If "node" + * has no List of child nodes, this function stores NULL at "pChildren". + * + * Note that the List returned by this function may be mutable. This function + * differs from the public function PKIX_PolicyNode_GetChildren in that + * respect. (It also differs in that the public function creates an empty + * List, if necessary, rather than storing NULL.) + * + * During certificate processing, children Lists are created and modified. + * Once the list is accessed using the public call, the List is set immutable. + * + * PARAMETERS: + * "node" + * Address of PolicyNode whose child nodes are to be stored. + * Must be non-NULL. + * "pChildren" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a PolicyNode 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_PolicyNode_GetChildrenMutable( + PKIX_PolicyNode *node, + PKIX_List **pChildren, /* list of PKIX_PolicyNode */ + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_GetChildrenMutable"); + + PKIX_NULLCHECK_TWO(node, pChildren); + + PKIX_INCREF(node->children); + + *pChildren = node->children; + +cleanup: + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Create + * DESCRIPTION: + * + * Creates a new PolicyNode using the OID pointed to by "validPolicy", the List + * of CertPolicyQualifiers pointed to by "qualifierSet", the criticality + * indicated by the Boolean value of "criticality", and the List of OIDs + * pointed to by "expectedPolicySet", and stores the result at "pObject". The + * criticality should be derived from whether the certificate policy extension + * was marked as critical in the certificate that led to creation of this + * PolicyNode. The "qualifierSet" and "expectedPolicySet" Lists are made + * immutable. The PolicyNode pointers to parent and to children are initialized + * to NULL, and the depth is set to zero; those values should be set by using + * the pkix_PolicyNode_AddToParent function. + * + * PARAMETERS + * "validPolicy" + * Address of OID of the valid policy for the path. Must be non-NULL + * "qualifierSet" + * Address of List of CertPolicyQualifiers associated with the validpolicy. + * May be NULL + * "criticality" + * Boolean indicator of whether the criticality should be set in this + * PolicyNode + * "expectedPolicySet" + * Address of List of OIDs that would satisfy this policy in the next + * certificate. Must be non-NULL + * "pObject" + * Address where the PolicyNode 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 PolicyNode 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_PolicyNode_Create( + PKIX_PL_OID *validPolicy, + PKIX_List *qualifierSet, + PKIX_Boolean criticality, + PKIX_List *expectedPolicySet, + PKIX_PolicyNode **pObject, + void *plContext) +{ + PKIX_PolicyNode *node = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Create"); + + PKIX_NULLCHECK_THREE(validPolicy, expectedPolicySet, pObject); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTPOLICYNODE_TYPE, + sizeof (PKIX_PolicyNode), + (PKIX_PL_Object **)&node, + plContext), + PKIX_COULDNOTCREATEPOLICYNODEOBJECT); + + PKIX_INCREF(validPolicy); + node->validPolicy = validPolicy; + + PKIX_INCREF(qualifierSet); + node->qualifierSet = qualifierSet; + if (qualifierSet) { + PKIX_CHECK(PKIX_List_SetImmutable(qualifierSet, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + } + + node->criticality = criticality; + + PKIX_INCREF(expectedPolicySet); + node->expectedPolicySet = expectedPolicySet; + PKIX_CHECK(PKIX_List_SetImmutable(expectedPolicySet, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + node->parent = NULL; + node->children = NULL; + node->depth = 0; + + *pObject = node; + node = NULL; + +cleanup: + + PKIX_DECREF(node); + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_AddToParent + * DESCRIPTION: + * + * Adds the PolicyNode pointed to by "child" to the List of children of + * the PolicyNode pointed to by "parentNode". If "parentNode" had a + * NULL pointer for the List of children, a new List is created containing + * "child". Otherwise "child" is appended to the existing List. The + * parent field in "child" is set to "parent", and the depth field is + * set to one more than the corresponding value in "parent". + * + * Depth, in this context, means distance from the root node, which + * is at depth zero. + * + * PARAMETERS: + * "parentNode" + * Address of PolicyNode whose List of child PolicyNodes is to be + * created or appended to. Must be non-NULL. + * "child" + * Address of PolicyNode to be added to parentNode's List. 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 PolicyNode 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_PolicyNode_AddToParent( + PKIX_PolicyNode *parentNode, + PKIX_PolicyNode *child, + void *plContext) +{ + PKIX_List *listOfChildren = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_AddToParent"); + + PKIX_NULLCHECK_TWO(parentNode, child); + + listOfChildren = parentNode->children; + if (listOfChildren == NULL) { + PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext), + PKIX_LISTCREATEFAILED); + parentNode->children = listOfChildren; + } + + /* + * Note: this link is not reference-counted. The link from parent + * to child is counted (actually, the parent "owns" a List which + * "owns" children), but the children do not "own" the parent. + * Otherwise, there would be loops. + */ + child->parent = parentNode; + + child->depth = 1 + (parentNode->depth); + + PKIX_CHECK(PKIX_List_AppendItem + (listOfChildren, (PKIX_PL_Object *)child, plContext), + PKIX_COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)parentNode, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)child, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Prune + * DESCRIPTION: + * + * Prunes a tree below the PolicyNode whose address is pointed to by "node", + * using the UInt32 value of "height" as the distance from the leaf level, + * and storing at "pDelete" the Boolean value of whether this PolicyNode is, + * after pruning, childless and should be pruned. + * + * Any PolicyNode at height 0 is allowed to survive. If the height is greater + * than zero, pkix_PolicyNode_Prune is called recursively for each child of + * the current PolicyNode. After this process, a node with no children + * stores PKIX_TRUE in "pDelete" to indicate that it should be deleted. + * + * PARAMETERS: + * "node" + * Address of the PolicyNode to be pruned. Must be non-NULL. + * "height" + * UInt32 value for the distance from the leaf level + * "pDelete" + * Address to store the Boolean return value of PKIX_TRUE if this node + * should be pruned, or PKIX_FALSE if there remains at least one + * branch of the required height. 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 PolicyNode 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_PolicyNode_Prune( + PKIX_PolicyNode *node, + PKIX_UInt32 height, + PKIX_Boolean *pDelete, + void *plContext) +{ + PKIX_Boolean childless = PKIX_FALSE; + PKIX_Boolean shouldBePruned = PKIX_FALSE; + PKIX_UInt32 listSize = 0; + PKIX_UInt32 listIndex = 0; + PKIX_PolicyNode *candidate = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Prune"); + + PKIX_NULLCHECK_TWO(node, pDelete); + + /* Don't prune at the leaf */ + if (height == 0) { + goto cleanup; + } + + /* Above the bottom level, childless nodes get pruned */ + if (!(node->children)) { + childless = PKIX_TRUE; + goto cleanup; + } + + /* + * This node has children. If they are leaf nodes, + * we know they will live. Otherwise, check them out. + */ + if (height > 1) { + PKIX_CHECK(PKIX_List_GetLength + (node->children, &listSize, plContext), + PKIX_LISTGETLENGTHFAILED); + /* + * By working backwards from the end of the list, + * we avoid having to worry about possible + * decreases in the size of the list, as we + * delete items. The only nuisance is that since the + * index is UInt32, we can't check for it to reach -1; + * we have to use the 1-based index, rather than the + * 0-based index that PKIX_List functions require. + */ + for (listIndex = listSize; listIndex > 0; listIndex--) { + PKIX_CHECK(PKIX_List_GetItem + (node->children, + (listIndex - 1), + (PKIX_PL_Object **)&candidate, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyNode_Prune + (candidate, + height - 1, + &shouldBePruned, + plContext), + PKIX_POLICYNODEPRUNEFAILED); + + if (shouldBePruned == PKIX_TRUE) { + PKIX_CHECK(PKIX_List_DeleteItem + (node->children, + (listIndex - 1), + plContext), + PKIX_LISTDELETEITEMFAILED); + } + + PKIX_DECREF(candidate); + } + } + + /* Prune if this node has *become* childless */ + PKIX_CHECK(PKIX_List_GetLength + (node->children, &listSize, plContext), + PKIX_LISTGETLENGTHFAILED); + if (listSize == 0) { + childless = PKIX_TRUE; + } + + /* + * Even if we did not change this node, or any of its children, + * maybe a [great-]*grandchild was pruned. + */ + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)node, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + *pDelete = childless; + + PKIX_DECREF(candidate); + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_SinglePolicyNode_ToString + * DESCRIPTION: + * + * Creates a String representation of the attributes of the PolicyNode + * pointed to by "node", other than its parents or children, and + * stores the result at "pString". + * + * PARAMETERS: + * "node" + * Address of PolicyNode to be described by the string. Must be non-NULL. + * "pString" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +PKIX_Error * +pkix_SinglePolicyNode_ToString( + PKIX_PolicyNode *node, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *fmtString = NULL; + PKIX_PL_String *validString = NULL; + PKIX_PL_String *qualifierString = NULL; + PKIX_PL_String *criticalityString = NULL; + PKIX_PL_String *expectedString = NULL; + PKIX_PL_String *outString = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_ToString"); + PKIX_NULLCHECK_TWO(node, pString); + PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "{%s,%s,%s,%s,%d}", + 0, + &fmtString, + plContext), + PKIX_CANTCREATESTRING); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)(node->validPolicy), + &validString, + plContext), + PKIX_OIDTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)(node->expectedPolicySet), + &expectedString, + plContext), + PKIX_LISTTOSTRINGFAILED); + + if (node->qualifierSet) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)(node->qualifierSet), + &qualifierString, + plContext), + PKIX_LISTTOSTRINGFAILED); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "{}", + 0, + &qualifierString, + plContext), + PKIX_CANTCREATESTRING); + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (node->criticality)?"Critical":"Not Critical", + 0, + &criticalityString, + plContext), + PKIX_CANTCREATESTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, + plContext, + fmtString, + validString, + qualifierString, + criticalityString, + expectedString, + node->depth), + PKIX_SPRINTFFAILED); + + *pString = outString; + +cleanup: + + PKIX_DECREF(fmtString); + PKIX_DECREF(validString); + PKIX_DECREF(qualifierString); + PKIX_DECREF(criticalityString); + PKIX_DECREF(expectedString); + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_ToString_Helper + * DESCRIPTION: + * + * Produces a String representation of a PolicyNode tree below the PolicyNode + * pointed to by "rootNode", with each line of output prefixed by the String + * pointed to by "indent", and stores the result at "pTreeString". It is + * called recursively, with ever-increasing indentation, for successively + * lower nodes on the tree. + * + * PARAMETERS: + * "rootNode" + * Address of PolicyNode subtree. Must be non-NULL. + * "indent" + * Address of String to be prefixed to each line of output. May be NULL + * if no indentation is desired + * "pTreeString" + * Address where the resulting String will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a PolicyNode 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_PolicyNode_ToString_Helper( + PKIX_PolicyNode *rootNode, + PKIX_PL_String *indent, + PKIX_PL_String **pTreeString, + void *plContext) +{ + PKIX_PL_String *nextIndentFormat = NULL; + PKIX_PL_String *thisNodeFormat = NULL; + PKIX_PL_String *childrenFormat = NULL; + PKIX_PL_String *nextIndentString = NULL; + PKIX_PL_String *resultString = NULL; + PKIX_PL_String *thisItemString = NULL; + PKIX_PL_String *childString = NULL; + PKIX_PolicyNode *childNode = NULL; + PKIX_UInt32 numberOfChildren = 0; + PKIX_UInt32 childIndex = 0; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString_Helper"); + + PKIX_NULLCHECK_TWO(rootNode, pTreeString); + + /* Create a string for this node */ + PKIX_CHECK(pkix_SinglePolicyNode_ToString + (rootNode, &thisItemString, plContext), + PKIX_ERRORINSINGLEPOLICYNODETOSTRING); + + if (indent) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s%s", + 0, + &thisNodeFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + thisNodeFormat, + indent, + thisItemString), + PKIX_ERRORINSPRINTF); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s", + 0, + &thisNodeFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + thisNodeFormat, + thisItemString), + PKIX_ERRORINSPRINTF); + } + + PKIX_DECREF(thisItemString); + thisItemString = resultString; + + /* if no children, we are done */ + if (rootNode->children) { + PKIX_CHECK(PKIX_List_GetLength + (rootNode->children, &numberOfChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + if (numberOfChildren != 0) { + /* + * We create a string for each child in turn, + * concatenating them to thisItemString. + */ + + /* Prepare an indent string for each child */ + if (indent) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s. ", + 0, + &nextIndentFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&nextIndentString, + plContext, + nextIndentFormat, + indent), + PKIX_ERRORINSPRINTF); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + ". ", + 0, + &nextIndentString, + plContext), + PKIX_ERRORCREATINGINDENTSTRING); + } + + /* Prepare the format for concatenation. */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s\n%s", + 0, + &childrenFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + for (childIndex = 0; + childIndex < numberOfChildren; + childIndex++) { + PKIX_CHECK(PKIX_List_GetItem + (rootNode->children, + childIndex, + (PKIX_PL_Object **)&childNode, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyNode_ToString_Helper + (childNode, + nextIndentString, + &childString, + plContext), + PKIX_ERRORCREATINGCHILDSTRING); + + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + childrenFormat, + thisItemString, + childString), + PKIX_ERRORINSPRINTF); + + PKIX_DECREF(childNode); + PKIX_DECREF(childString); + PKIX_DECREF(thisItemString); + + thisItemString = resultString; + } + } + + *pTreeString = thisItemString; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(thisItemString); + } + + PKIX_DECREF(nextIndentFormat); + PKIX_DECREF(thisNodeFormat); + PKIX_DECREF(childrenFormat); + PKIX_DECREF(nextIndentString); + PKIX_DECREF(childString); + PKIX_DECREF(childNode); + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pTreeString, + void *plContext) +{ + PKIX_PolicyNode *rootNode = NULL; + PKIX_PL_String *resultString = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString"); + + PKIX_NULLCHECK_TWO(object, pTreeString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYNODE); + + rootNode = (PKIX_PolicyNode *)object; + + PKIX_CHECK(pkix_PolicyNode_ToString_Helper + (rootNode, NULL, &resultString, plContext), + PKIX_ERRORCREATINGSUBTREESTRING); + + *pTreeString = resultString; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PolicyNode *node = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYNODE); + + node = (PKIX_PolicyNode*)object; + + node->criticality = PKIX_FALSE; + PKIX_DECREF(node->validPolicy); + PKIX_DECREF(node->qualifierSet); + PKIX_DECREF(node->expectedPolicySet); + PKIX_DECREF(node->children); + + /* + * Note: the link to parent is not reference-counted. See comment + * in pkix_PolicyNode_AddToParent for more details. + */ + node->parent = NULL; + node->depth = 0; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_SinglePolicyNode_Hashcode + * DESCRIPTION: + * + * Computes the hashcode of the attributes of the PolicyNode pointed to by + * "node", other than its parents and children, and stores the result at + * "pHashcode". + * + * PARAMETERS: + * "node" + * Address of PolicyNode to be hashcoded; must be non-NULL + * "pHashcode" + * Address where UInt32 result will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_SinglePolicyNode_Hashcode( + PKIX_PolicyNode *node, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 componentHash = 0; + PKIX_UInt32 nodeHash = 0; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Hashcode"); + PKIX_NULLCHECK_TWO(node, pHashcode); + PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet); + + PKIX_HASHCODE + (node->qualifierSet, + &nodeHash, + plContext, + PKIX_FAILUREHASHINGLISTQUALIFIERSET); + + if (PKIX_TRUE == (node->criticality)) { + nodeHash = 31*nodeHash + 0xff; + } else { + nodeHash = 31*nodeHash + 0x00; + } + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)node->validPolicy, + &componentHash, + plContext), + PKIX_FAILUREHASHINGOIDVALIDPOLICY); + + nodeHash = 31*nodeHash + componentHash; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)node->expectedPolicySet, + &componentHash, + plContext), + PKIX_FAILUREHASHINGLISTEXPECTEDPOLICYSET); + + nodeHash = 31*nodeHash + componentHash; + + *pHashcode = nodeHash; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PolicyNode *node = NULL; + PKIX_UInt32 childrenHash = 0; + PKIX_UInt32 nodeHash = 0; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYNODE); + + node = (PKIX_PolicyNode *)object; + + PKIX_CHECK(pkix_SinglePolicyNode_Hashcode + (node, &nodeHash, plContext), + PKIX_SINGLEPOLICYNODEHASHCODEFAILED); + + nodeHash = 31*nodeHash + (PKIX_UInt32)((char *)node->parent - (char *)NULL); + + PKIX_HASHCODE + (node->children, + &childrenHash, + plContext, + PKIX_OBJECTHASHCODEFAILED); + + nodeHash = 31*nodeHash + childrenHash; + + *pHashcode = nodeHash; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_SinglePolicyNode_Equals + * DESCRIPTION: + * + * Compares for equality the components of the PolicyNode pointed to by + * "firstPN", other than its parents and children, with those of the + * PolicyNode pointed to by "secondPN" and stores the result at "pResult" + * (PKIX_TRUE if equal; PKIX_FALSE if not). + * + * PARAMETERS: + * "firstPN" + * Address of first of the PolicyNodes to be compared; must be non-NULL + * "secondPN" + * Address of second of the PolicyNodes to be compared; must be non-NULL + * "pResult" + * Address where Boolean will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_SinglePolicyNode_Equals( + PKIX_PolicyNode *firstPN, + PKIX_PolicyNode *secondPN, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Equals"); + PKIX_NULLCHECK_THREE(firstPN, secondPN, pResult); + + /* If both references are identical, they must be equal */ + if (firstPN == secondPN) { + compResult = PKIX_TRUE; + goto cleanup; + } + + /* + * It seems we have to do the comparisons. Do + * the easiest ones first. + */ + if ((firstPN->criticality) != (secondPN->criticality)) { + goto cleanup; + } + if ((firstPN->depth) != (secondPN->depth)) { + goto cleanup; + } + + PKIX_EQUALS + (firstPN->qualifierSet, + secondPN->qualifierSet, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + /* These fields must be non-NULL */ + PKIX_NULLCHECK_TWO(firstPN->validPolicy, secondPN->validPolicy); + + PKIX_EQUALS + (firstPN->validPolicy, + secondPN->validPolicy, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + /* These fields must be non-NULL */ + PKIX_NULLCHECK_TWO + (firstPN->expectedPolicySet, secondPN->expectedPolicySet); + + PKIX_EQUALS + (firstPN->expectedPolicySet, + secondPN->expectedPolicySet, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS); + +cleanup: + + *pResult = compResult; + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PolicyNode *firstPN = NULL; + PKIX_PolicyNode *secondPN = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a PolicyNode */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_FIRSTOBJECTNOTPOLICYNODE); + + /* + * Since we know firstObject is a PolicyNode, + * if both references are identical, they must be equal + */ + if (firstObject == secondObject){ + compResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a PolicyNode, we + * don't throw an error. We simply return FALSE. + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + if (secondType != PKIX_CERTPOLICYNODE_TYPE) { + goto cleanup; + } + + /* + * Oh, well, we have to do the comparisons. Do + * the easiest ones first. + */ + firstPN = (PKIX_PolicyNode *)firstObject; + secondPN = (PKIX_PolicyNode *)secondObject; + + /* + * We don't require the parents to be identical. In the + * course of traversing the tree, we will have checked the + * attributes of the parent nodes, and checking the lists + * of children will determine whether they match. + */ + + PKIX_EQUALS + (firstPN->children, + secondPN->children, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILEDONCHILDREN); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + PKIX_CHECK(pkix_SinglePolicyNode_Equals + (firstPN, secondPN, &compResult, plContext), + PKIX_SINGLEPOLICYNODEEQUALSFAILED); + +cleanup: + + *pResult = compResult; + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_DuplicateHelper + * DESCRIPTION: + * + * Duplicates the PolicyNode whose address is pointed to by "original", + * and stores the result at "pNewNode", if a non-NULL pointer is provided + * for "pNewNode". In addition, the created PolicyNode is added as a child + * to "parent", if a non-NULL pointer is provided for "parent". Then this + * function is called recursively to duplicate each of the children of + * "original". At the top level this function is called with a null + * "parent" and a non-NULL "pNewNode". Below the top level "parent" will + * be non-NULL and "pNewNode" will be NULL. + * + * PARAMETERS: + * "original" + * Address of PolicyNode to be copied; must be non-NULL + * "parent" + * Address of PolicyNode to which the created node is to be added as a + * child; NULL for the top-level call and non-NULL below the top level + * "pNewNode" + * Address to store the node created; should be NULL if "parent" is + * non-NULL and vice versa + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_PolicyNode_DuplicateHelper( + PKIX_PolicyNode *original, + PKIX_PolicyNode *parent, + PKIX_PolicyNode **pNewNode, + void *plContext) +{ + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 childIndex = 0; + PKIX_List *children = NULL; /* List of PKIX_PolicyNode */ + PKIX_PolicyNode *copy = NULL; + PKIX_PolicyNode *child = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_DuplicateHelper"); + + PKIX_NULLCHECK_THREE + (original, original->validPolicy, original->expectedPolicySet); + + /* + * These components are immutable, so copying the pointers + * is sufficient. The create function increments the reference + * counts as it stores the pointers into the new object. + */ + PKIX_CHECK(pkix_PolicyNode_Create + (original->validPolicy, + original->qualifierSet, + original->criticality, + original->expectedPolicySet, + ©, + plContext), + PKIX_POLICYNODECREATEFAILED); + + if (parent) { + PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, copy, plContext), + PKIX_POLICYNODEADDTOPARENTFAILED); + } + + /* Are there any children to duplicate? */ + children = original->children; + + if (children) { + PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + for (childIndex = 0; childIndex < numChildren; childIndex++) { + PKIX_CHECK(PKIX_List_GetItem + (children, + childIndex, + (PKIX_PL_Object **)&child, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyNode_DuplicateHelper + (child, copy, NULL, plContext), + PKIX_POLICYNODEDUPLICATEHELPERFAILED); + + PKIX_DECREF(child); + } + + if (pNewNode) { + *pNewNode = copy; + copy = NULL; /* no DecRef if we give our handle away */ + } + +cleanup: + PKIX_DECREF(copy); + PKIX_DECREF(child); + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Duplicate + * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_PolicyNode *original = NULL; + PKIX_PolicyNode *copy = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Duplicate"); + + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYNODE); + + original = (PKIX_PolicyNode *)object; + + PKIX_CHECK(pkix_PolicyNode_DuplicateHelper + (original, NULL, ©, plContext), + PKIX_POLICYNODEDUPLICATEHELPERFAILED); + + *pNewObject = (PKIX_PL_Object *)copy; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_RegisterSelf + * DESCRIPTION: + * + * Registers PKIX_CERTPOLICYNODE_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_PolicyNode_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_RegisterSelf"); + + entry.description = "PolicyNode"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PolicyNode); + entry.destructor = pkix_PolicyNode_Destroy; + entry.equalsFunction = pkix_PolicyNode_Equals; + entry.hashcodeFunction = pkix_PolicyNode_Hashcode; + entry.toStringFunction = pkix_PolicyNode_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_PolicyNode_Duplicate; + + systemClasses[PKIX_CERTPOLICYNODE_TYPE] = entry; + + PKIX_RETURN(CERTPOLICYNODE); +} + + +/* --Public-PolicyNode-Functions----------------------------------- */ + +/* + * FUNCTION: PKIX_PolicyNode_GetChildren + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetChildren( + PKIX_PolicyNode *node, + PKIX_List **pChildren, /* list of PKIX_PolicyNode */ + void *plContext) +{ + PKIX_List *children = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetChildren"); + + PKIX_NULLCHECK_TWO(node, pChildren); + + PKIX_INCREF(node->children); + children = node->children; + + if (!children) { + PKIX_CHECK(PKIX_List_Create(&children, plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_SetImmutable(children, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pChildren = children; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(children); + } + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetParent + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetParent( + PKIX_PolicyNode *node, + PKIX_PolicyNode **pParent, + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetParent"); + + PKIX_NULLCHECK_TWO(node, pParent); + + PKIX_INCREF(node->parent); + *pParent = node->parent; + +cleanup: + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetValidPolicy + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetValidPolicy( + PKIX_PolicyNode *node, + PKIX_PL_OID **pValidPolicy, + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetValidPolicy"); + + PKIX_NULLCHECK_TWO(node, pValidPolicy); + + PKIX_INCREF(node->validPolicy); + *pValidPolicy = node->validPolicy; + +cleanup: + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetPolicyQualifiers( + PKIX_PolicyNode *node, + PKIX_List **pQualifiers, /* list of PKIX_PL_CertPolicyQualifier */ + void *plContext) +{ + PKIX_List *qualifiers = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetPolicyQualifiers"); + + PKIX_NULLCHECK_TWO(node, pQualifiers); + + PKIX_INCREF(node->qualifierSet); + qualifiers = node->qualifierSet; + + if (!qualifiers) { + PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_SetImmutable(qualifiers, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pQualifiers = qualifiers; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetExpectedPolicies( + PKIX_PolicyNode *node, + PKIX_List **pExpPolicies, /* list of PKIX_PL_OID */ + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetExpectedPolicies"); + + PKIX_NULLCHECK_TWO(node, pExpPolicies); + + PKIX_INCREF(node->expectedPolicySet); + *pExpPolicies = node->expectedPolicySet; + +cleanup: + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_IsCritical + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_IsCritical( + PKIX_PolicyNode *node, + PKIX_Boolean *pCritical, + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_IsCritical"); + + PKIX_NULLCHECK_TWO(node, pCritical); + + *pCritical = node->criticality; + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetDepth + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetDepth( + PKIX_PolicyNode *node, + PKIX_UInt32 *pDepth, + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetDepth"); + + PKIX_NULLCHECK_TWO(node, pDepth); + + *pDepth = node->depth; + + PKIX_RETURN(CERTPOLICYNODE); +} diff --git a/security/nss/lib/libpkix/pkix/results/pkix_policynode.h b/security/nss/lib/libpkix/pkix/results/pkix_policynode.h new file mode 100644 index 0000000000..799b7a60aa --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.h @@ -0,0 +1,74 @@ +/* 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_policynode.h + * + * PolicyNode Type Definitions + * + */ + +#ifndef _PKIX_POLICYNODE_H +#define _PKIX_POLICYNODE_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This structure reflects the contents of a policy node... + */ +struct PKIX_PolicyNodeStruct { + PKIX_PL_OID *validPolicy; + PKIX_List *qualifierSet; /* CertPolicyQualifiers */ + PKIX_Boolean criticality; + PKIX_List *expectedPolicySet; /* OIDs */ + PKIX_PolicyNode *parent; + PKIX_List *children; /* PolicyNodes */ + PKIX_UInt32 depth; +}; + +PKIX_Error * +pkix_SinglePolicyNode_ToString( + PKIX_PolicyNode *node, + PKIX_PL_String **pString, + void *plContext); + +PKIX_Error * +pkix_PolicyNode_GetChildrenMutable( + PKIX_PolicyNode *node, + PKIX_List **pChildren, /* PolicyNodes */ + void *plContext); + +PKIX_Error * +pkix_PolicyNode_Create( + PKIX_PL_OID *validPolicy, + PKIX_List *qualifierSet, /* CertPolicyQualifiers */ + PKIX_Boolean criticality, + PKIX_List *expectedPolicySet, /* OIDs */ + PKIX_PolicyNode **pObject, + void *plContext); + +PKIX_Error * +pkix_PolicyNode_AddToParent( + PKIX_PolicyNode *parentNode, + PKIX_PolicyNode *child, + void *plContext); + +PKIX_Error * +pkix_PolicyNode_Prune( + PKIX_PolicyNode *node, + PKIX_UInt32 depth, + PKIX_Boolean *pDelete, + void *plContext); + +PKIX_Error * +pkix_PolicyNode_RegisterSelf( + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_POLICYNODE_H */ diff --git a/security/nss/lib/libpkix/pkix/results/pkix_valresult.c b/security/nss/lib/libpkix/pkix/results/pkix_valresult.c new file mode 100644 index 0000000000..25b69e59c3 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_valresult.c @@ -0,0 +1,442 @@ +/* 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_valresult.c + * + * ValidateResult Object Functions + * + */ + +#include "pkix_valresult.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_ValidateResult_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateResult_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ValidateResult *result = NULL; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a validate result object */ + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext), + PKIX_OBJECTNOTVALIDATERESULT); + + result = (PKIX_ValidateResult *)object; + + PKIX_DECREF(result->anchor); + PKIX_DECREF(result->pubKey); + PKIX_DECREF(result->policyTree); + +cleanup: + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateResult_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_ValidateResult *firstValResult = NULL; + PKIX_ValidateResult *secondValResult = NULL; + PKIX_TrustAnchor *firstAnchor = NULL; + PKIX_TrustAnchor *secondAnchor = NULL; + PKIX_PolicyNode *firstTree = NULL; + PKIX_PolicyNode *secondTree = NULL; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_VALIDATERESULT_TYPE, plContext), + PKIX_FIRSTOBJECTNOTVALIDATERESULT); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_VALIDATERESULT_TYPE) goto cleanup; + + firstValResult = (PKIX_ValidateResult *)first; + secondValResult = (PKIX_ValidateResult *)second; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstValResult->pubKey, + (PKIX_PL_Object *)secondValResult->pubKey, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + firstAnchor = firstValResult->anchor; + secondAnchor = secondValResult->anchor; + + if ((firstAnchor != NULL) && (secondAnchor != NULL)) { + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstAnchor, + (PKIX_PL_Object *)secondAnchor, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + } else { + cmpResult = (firstAnchor == secondAnchor); + } + + if (!cmpResult) goto cleanup; + + firstTree = firstValResult->policyTree; + secondTree = secondValResult->policyTree; + + if ((firstTree != NULL) && (secondTree != NULL)) { + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstTree, + (PKIX_PL_Object *)secondTree, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + } else { + cmpResult = (firstTree == secondTree); + } + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateResult_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_ValidateResult *valResult = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 pubKeyHash = 0; + PKIX_UInt32 anchorHash = 0; + PKIX_UInt32 policyTreeHash = 0; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext), + PKIX_OBJECTNOTVALIDATERESULT); + + valResult = (PKIX_ValidateResult*)object; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)valResult->pubKey, &pubKeyHash, plContext), + PKIX_OBJECTHASHCODEFAILED); + + if (valResult->anchor) { + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)valResult->anchor, + &anchorHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + } + + if (valResult->policyTree) { + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)valResult->policyTree, + &policyTreeHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + } + + hash = 31*(31 * pubKeyHash + anchorHash) + policyTreeHash; + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateResult_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_ValidateResult *valResult = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *valResultString = NULL; + + PKIX_TrustAnchor *anchor = NULL; + PKIX_PL_PublicKey *pubKey = NULL; + PKIX_PolicyNode *policyTree = NULL; + + PKIX_PL_String *anchorString = NULL; + PKIX_PL_String *pubKeyString = NULL; + PKIX_PL_String *treeString = NULL; + char *asciiNullString = "(null)"; + char *asciiFormat = + "[\n" + "\tTrustAnchor: \t\t%s" + "\tPubKey: \t\t%s\n" + "\tPolicyTree: \t\t%s\n" + "]\n"; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext), + PKIX_OBJECTNOTVALIDATERESULT); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + + valResult = (PKIX_ValidateResult*)object; + + anchor = valResult->anchor; + + if (anchor) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)anchor, &anchorString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiNullString, + 0, + &anchorString, + plContext), + PKIX_STRINGCREATEFAILED); + } + + pubKey = valResult->pubKey; + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)pubKey, &pubKeyString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + policyTree = valResult->policyTree; + + if (policyTree) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)policyTree, &treeString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiNullString, + 0, + &treeString, + plContext), + PKIX_STRINGCREATEFAILED); + } + + PKIX_CHECK(PKIX_PL_Sprintf + (&valResultString, + plContext, + formatString, + anchorString, + pubKeyString, + treeString), + PKIX_SPRINTFFAILED); + + *pString = valResultString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(anchorString); + PKIX_DECREF(pubKeyString); + PKIX_DECREF(treeString); + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_RegisterSelf + * DESCRIPTION: + * Registers PKIX_VALIDATERESULT_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_ValidateResult_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_RegisterSelf"); + + entry.description = "ValidateResult"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_ValidateResult); + entry.destructor = pkix_ValidateResult_Destroy; + entry.equalsFunction = pkix_ValidateResult_Equals; + entry.hashcodeFunction = pkix_ValidateResult_Hashcode; + entry.toStringFunction = pkix_ValidateResult_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_VALIDATERESULT_TYPE] = entry; + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_Create + * DESCRIPTION: + * + * Creates a new ValidateResult Object using the PublicKey pointed to by + * "pubKey", the TrustAnchor pointed to by "anchor", and the PolicyNode + * pointed to by "policyTree", and stores it at "pResult". + * + * PARAMETERS + * "pubKey" + * PublicKey of the desired ValidateResult. Must be non-NULL. + * "anchor" + * TrustAnchor of the desired Validateresult. May be NULL. + * "policyTree" + * PolicyNode of the desired ValidateResult; may be NULL + * "pResult" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_ValidateResult_Create( + PKIX_PL_PublicKey *pubKey, + PKIX_TrustAnchor *anchor, + PKIX_PolicyNode *policyTree, + PKIX_ValidateResult **pResult, + void *plContext) +{ + PKIX_ValidateResult *result = NULL; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Create"); + PKIX_NULLCHECK_TWO(pubKey, pResult); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_VALIDATERESULT_TYPE, + sizeof (PKIX_ValidateResult), + (PKIX_PL_Object **)&result, + plContext), + PKIX_COULDNOTCREATEVALIDATERESULTOBJECT); + + /* initialize fields */ + + PKIX_INCREF(pubKey); + result->pubKey = pubKey; + + PKIX_INCREF(anchor); + result->anchor = anchor; + + PKIX_INCREF(policyTree); + result->policyTree = policyTree; + + *pResult = result; + result = NULL; + +cleanup: + + PKIX_DECREF(result); + + PKIX_RETURN(VALIDATERESULT); + +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_ValidateResult_GetPublicKey + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_ValidateResult_GetPublicKey( + PKIX_ValidateResult *result, + PKIX_PL_PublicKey **pPublicKey, + void *plContext) +{ + PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetPublicKey"); + PKIX_NULLCHECK_TWO(result, pPublicKey); + + PKIX_INCREF(result->pubKey); + *pPublicKey = result->pubKey; + +cleanup: + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: PKIX_ValidateResult_GetTrustAnchor + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_ValidateResult_GetTrustAnchor( + PKIX_ValidateResult *result, + PKIX_TrustAnchor **pTrustAnchor, + void *plContext) +{ + PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetTrustAnchor"); + PKIX_NULLCHECK_TWO(result, pTrustAnchor); + + PKIX_INCREF(result->anchor); + *pTrustAnchor = result->anchor; + +cleanup: + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: PKIX_ValidateResult_GetPolicyTree + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_ValidateResult_GetPolicyTree( + PKIX_ValidateResult *result, + PKIX_PolicyNode **pPolicyTree, + void *plContext) +{ + PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetPolicyTree"); + PKIX_NULLCHECK_TWO(result, pPolicyTree); + + PKIX_INCREF(result->policyTree); + (*pPolicyTree) = result->policyTree; + +cleanup: + PKIX_RETURN(VALIDATERESULT); +} diff --git a/security/nss/lib/libpkix/pkix/results/pkix_valresult.h b/security/nss/lib/libpkix/pkix/results/pkix_valresult.h new file mode 100644 index 0000000000..8011ae8c8f --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_valresult.h @@ -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_valresult.h + * + * ValidateResult Object Type Definition + * + */ + +#ifndef _PKIX_VALIDATERESULT_H +#define _PKIX_VALIDATERESULT_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_ValidateResultStruct { + PKIX_PL_PublicKey *pubKey; + PKIX_TrustAnchor *anchor; + PKIX_PolicyNode *policyTree; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_ValidateResult_Create( + PKIX_PL_PublicKey *pubKey, + PKIX_TrustAnchor *anchor, + PKIX_PolicyNode *policyTree, + PKIX_ValidateResult **pResult, + void *plContext); + +PKIX_Error *pkix_ValidateResult_RegisterSelf(void *plContext); + + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_VALIDATERESULT_H */ diff --git a/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c new file mode 100644 index 0000000000..b52f83fcab --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c @@ -0,0 +1,1182 @@ +/* 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_verifynode.c + * + * Verify Node Object Type Definition + * + */ + +#include "pkix_verifynode.h" + +/* --Private-VerifyNode-Functions---------------------------------- */ + +/* + * FUNCTION: pkix_VerifyNode_Create + * DESCRIPTION: + * + * This function creates a VerifyNode using the Cert pointed to by "cert", + * the depth given by "depth", and the Error pointed to by "error", storing + * the result at "pObject". + * + * PARAMETERS + * "cert" + * Address of Cert for the node. Must be non-NULL + * "depth" + * UInt32 value of the depth for this node. + * "error" + * Address of Error for the node. + * "pObject" + * Address where the VerifyNode 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_Create( + PKIX_PL_Cert *cert, + PKIX_UInt32 depth, + PKIX_Error *error, + PKIX_VerifyNode **pObject, + void *plContext) +{ + PKIX_VerifyNode *node = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Create"); + PKIX_NULLCHECK_TWO(cert, pObject); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_VERIFYNODE_TYPE, + sizeof (PKIX_VerifyNode), + (PKIX_PL_Object **)&node, + plContext), + PKIX_COULDNOTCREATEVERIFYNODEOBJECT); + + PKIX_INCREF(cert); + node->verifyCert = cert; + + PKIX_INCREF(error); + node->error = error; + + node->depth = depth; + + node->children = NULL; + + *pObject = node; + node = NULL; + +cleanup: + + PKIX_DECREF(node); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_AddToChain + * DESCRIPTION: + * + * Adds the VerifyNode pointed to by "child", at the appropriate depth, to the + * List of children of the VerifyNode pointed to by "parentNode". The chain of + * VerifyNodes is traversed until a VerifyNode is found at a depth one less + * than that specified in "child". An Error is returned if there is no parent + * at a suitable depth. + * + * If "parentNode" has a NULL pointer for the List of children, a new List is + * created containing "child". Otherwise "child" is appended to the existing + * List. + * + * Depth, in this context, means distance from the root node, which + * is at depth zero. + * + * PARAMETERS: + * "parentNode" + * Address of VerifyNode whose List of child VerifyNodes is to be + * created or appended to. Must be non-NULL. + * "child" + * Address of VerifyNode to be added to parentNode's List. 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 VerifyNode 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_VerifyNode_AddToChain( + PKIX_VerifyNode *parentNode, + PKIX_VerifyNode *child, + void *plContext) +{ + PKIX_VerifyNode *successor = NULL; + PKIX_List *listOfChildren = NULL; + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 parentDepth = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToChain"); + PKIX_NULLCHECK_TWO(parentNode, child); + + parentDepth = parentNode->depth; + listOfChildren = parentNode->children; + if (listOfChildren == NULL) { + + if (parentDepth != (child->depth - 1)) { + PKIX_ERROR(PKIX_NODESMISSINGFROMCHAIN); + } + + PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (listOfChildren, (PKIX_PL_Object *)child, plContext), + PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST); + + parentNode->children = listOfChildren; + } else { + /* get number of children */ + PKIX_CHECK(PKIX_List_GetLength + (listOfChildren, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numChildren != 1) { + PKIX_ERROR(PKIX_AMBIGUOUSPARENTAGEOFVERIFYNODE); + } + + /* successor = listOfChildren[0] */ + PKIX_CHECK(PKIX_List_GetItem + (listOfChildren, + 0, + (PKIX_PL_Object **)&successor, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_VerifyNode_AddToChain + (successor, child, plContext), + PKIX_VERIFYNODEADDTOCHAINFAILED); + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)parentNode, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + PKIX_DECREF(successor); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_SetDepth + * DESCRIPTION: + * + * The function sets the depth field of each VerifyNode in the List "children" + * to the value given by "depth", and recursively sets the depth of any + * successive generations to the successive values. + * + * PARAMETERS: + * "children" + * The List of VerifyNodes. Must be non-NULL. + * "depth" + * The value of the depth field to be set in members of the List. + * "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 Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_VerifyNode_SetDepth(PKIX_List *children, + PKIX_UInt32 depth, + void *plContext) +{ + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 chIx = 0; + PKIX_VerifyNode *child = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_SetDepth"); + PKIX_NULLCHECK_ONE(children); + + PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (chIx = 0; chIx < numChildren; chIx++) { + PKIX_CHECK(PKIX_List_GetItem + (children, chIx, (PKIX_PL_Object **)&child, plContext), + PKIX_LISTGETITEMFAILED); + + child->depth = depth; + + if (child->children != NULL) { + PKIX_CHECK(pkix_VerifyNode_SetDepth + (child->children, depth + 1, plContext), + PKIX_VERIFYNODESETDEPTHFAILED); + } + + PKIX_DECREF(child); + } + +cleanup: + + PKIX_DECREF(child); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_AddToTree + * DESCRIPTION: + * + * Adds the VerifyNode pointed to by "child" to the List of children of the + * VerifyNode pointed to by "parentNode". If "parentNode" has a NULL pointer + * for the List of children, a new List is created containing "child". + * Otherwise "child" is appended to the existing List. The depth field of + * "child" is set to one more than the corresponding value in "parent", and + * if the "child" itself has child nodes, their depth fields are updated + * accordingly. + * + * Depth, in this context, means distance from the root node, which + * is at depth zero. + * + * PARAMETERS: + * "parentNode" + * Address of VerifyNode whose List of child VerifyNodes is to be + * created or appended to. Must be non-NULL. + * "child" + * Address of VerifyNode to be added to parentNode's List. 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_AddToTree( + PKIX_VerifyNode *parentNode, + PKIX_VerifyNode *child, + void *plContext) +{ + PKIX_List *listOfChildren = NULL; + PKIX_UInt32 parentDepth = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToTree"); + PKIX_NULLCHECK_TWO(parentNode, child); + + parentDepth = parentNode->depth; + listOfChildren = parentNode->children; + if (listOfChildren == NULL) { + + PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext), + PKIX_LISTCREATEFAILED); + + parentNode->children = listOfChildren; + } + + child->depth = parentDepth + 1; + + PKIX_CHECK(PKIX_List_AppendItem + (parentNode->children, (PKIX_PL_Object *)child, plContext), + PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST); + + if (child->children != NULL) { + PKIX_CHECK(pkix_VerifyNode_SetDepth + (child->children, child->depth + 1, plContext), + PKIX_VERIFYNODESETDEPTHFAILED); + } + + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_SingleVerifyNode_ToString + * DESCRIPTION: + * + * Creates a String representation of the attributes of the VerifyNode pointed + * to by "node", other than its children, and stores the result at "pString". + * + * PARAMETERS: + * "node" + * Address of VerifyNode to be described by the string. Must be non-NULL. + * "pString" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +PKIX_Error * +pkix_SingleVerifyNode_ToString( + PKIX_VerifyNode *node, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *fmtString = NULL; + PKIX_PL_String *errorString = NULL; + PKIX_PL_String *outString = NULL; + + PKIX_PL_X500Name *issuerName = NULL; + PKIX_PL_X500Name *subjectName = NULL; + PKIX_PL_String *issuerString = NULL; + PKIX_PL_String *subjectString = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_ToString"); + PKIX_NULLCHECK_THREE(node, pString, node->verifyCert); + + PKIX_TOSTRING(node->error, &errorString, plContext, + PKIX_ERRORTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetIssuer + (node->verifyCert, &issuerName, plContext), + PKIX_CERTGETISSUERFAILED); + + PKIX_TOSTRING(issuerName, &issuerString, plContext, + PKIX_X500NAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetSubject + (node->verifyCert, &subjectName, plContext), + PKIX_CERTGETSUBJECTFAILED); + + PKIX_TOSTRING(subjectName, &subjectString, plContext, + PKIX_X500NAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "CERT[Issuer:%s, Subject:%s], depth=%d, error=%s", + 0, + &fmtString, + plContext), + PKIX_CANTCREATESTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, + plContext, + fmtString, + issuerString, + subjectString, + node->depth, + errorString), + PKIX_SPRINTFFAILED); + + *pString = outString; + +cleanup: + + PKIX_DECREF(fmtString); + PKIX_DECREF(errorString); + PKIX_DECREF(issuerName); + PKIX_DECREF(subjectName); + PKIX_DECREF(issuerString); + PKIX_DECREF(subjectString); + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_ToString_Helper + * DESCRIPTION: + * + * Produces a String representation of a VerifyNode tree below the VerifyNode + * pointed to by "rootNode", with each line of output prefixed by the String + * pointed to by "indent", and stores the result at "pTreeString". It is + * called recursively, with ever-increasing indentation, for successively + * lower nodes on the tree. + * + * PARAMETERS: + * "rootNode" + * Address of VerifyNode subtree. Must be non-NULL. + * "indent" + * Address of String to be prefixed to each line of output. May be NULL + * if no indentation is desired + * "pTreeString" + * Address where the resulting String will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a VerifyNode 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_VerifyNode_ToString_Helper( + PKIX_VerifyNode *rootNode, + PKIX_PL_String *indent, + PKIX_PL_String **pTreeString, + void *plContext) +{ + PKIX_PL_String *nextIndentFormat = NULL; + PKIX_PL_String *thisNodeFormat = NULL; + PKIX_PL_String *childrenFormat = NULL; + PKIX_PL_String *nextIndentString = NULL; + PKIX_PL_String *resultString = NULL; + PKIX_PL_String *thisItemString = NULL; + PKIX_PL_String *childString = NULL; + PKIX_VerifyNode *childNode = NULL; + PKIX_UInt32 numberOfChildren = 0; + PKIX_UInt32 childIndex = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString_Helper"); + + PKIX_NULLCHECK_TWO(rootNode, pTreeString); + + /* Create a string for this node */ + PKIX_CHECK(pkix_SingleVerifyNode_ToString + (rootNode, &thisItemString, plContext), + PKIX_ERRORINSINGLEVERIFYNODETOSTRING); + + if (indent) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s%s", + 0, + &thisNodeFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + thisNodeFormat, + indent, + thisItemString), + PKIX_ERRORINSPRINTF); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s", + 0, + &thisNodeFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + thisNodeFormat, + thisItemString), + PKIX_ERRORINSPRINTF); + } + + PKIX_DECREF(thisItemString); + thisItemString = resultString; + + /* if no children, we are done */ + if (rootNode->children) { + PKIX_CHECK(PKIX_List_GetLength + (rootNode->children, &numberOfChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + if (numberOfChildren != 0) { + /* + * We create a string for each child in turn, + * concatenating them to thisItemString. + */ + + /* Prepare an indent string for each child */ + if (indent) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s. ", + 0, + &nextIndentFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&nextIndentString, + plContext, + nextIndentFormat, + indent), + PKIX_ERRORINSPRINTF); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + ". ", + 0, + &nextIndentString, + plContext), + PKIX_ERRORCREATINGINDENTSTRING); + } + + /* Prepare the format for concatenation. */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s\n%s", + 0, + &childrenFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + for (childIndex = 0; + childIndex < numberOfChildren; + childIndex++) { + PKIX_CHECK(PKIX_List_GetItem + (rootNode->children, + childIndex, + (PKIX_PL_Object **)&childNode, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_VerifyNode_ToString_Helper + (childNode, + nextIndentString, + &childString, + plContext), + PKIX_ERRORCREATINGCHILDSTRING); + + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + childrenFormat, + thisItemString, + childString), + PKIX_ERRORINSPRINTF); + + PKIX_DECREF(childNode); + PKIX_DECREF(childString); + PKIX_DECREF(thisItemString); + + thisItemString = resultString; + } + } + + *pTreeString = thisItemString; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(thisItemString); + } + + PKIX_DECREF(nextIndentFormat); + PKIX_DECREF(thisNodeFormat); + PKIX_DECREF(childrenFormat); + PKIX_DECREF(nextIndentString); + PKIX_DECREF(childString); + PKIX_DECREF(childNode); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pTreeString, + void *plContext) +{ + PKIX_VerifyNode *rootNode = NULL; + PKIX_PL_String *resultString = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString"); + + PKIX_NULLCHECK_TWO(object, pTreeString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_OBJECTNOTVERIFYNODE); + + rootNode = (PKIX_VerifyNode *)object; + + PKIX_CHECK(pkix_VerifyNode_ToString_Helper + (rootNode, NULL, &resultString, plContext), + PKIX_ERRORCREATINGSUBTREESTRING); + + *pTreeString = resultString; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_VerifyNode *node = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_OBJECTNOTVERIFYNODE); + + node = (PKIX_VerifyNode*)object; + + PKIX_DECREF(node->verifyCert); + PKIX_DECREF(node->children); + PKIX_DECREF(node->error); + + node->depth = 0; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_SingleVerifyNode_Hashcode + * DESCRIPTION: + * + * Computes the hashcode of the attributes of the VerifyNode pointed to by + * "node", other than its parents and children, and stores the result at + * "pHashcode". + * + * PARAMETERS: + * "node" + * Address of VerifyNode to be hashcoded; must be non-NULL + * "pHashcode" + * Address where UInt32 result will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_SingleVerifyNode_Hashcode( + PKIX_VerifyNode *node, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 errorHash = 0; + PKIX_UInt32 nodeHash = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Hashcode"); + PKIX_NULLCHECK_TWO(node, pHashcode); + + PKIX_HASHCODE + (node->verifyCert, + &nodeHash, + plContext, + PKIX_FAILUREHASHINGCERT); + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)node->error, + &errorHash, + plContext), + PKIX_FAILUREHASHINGERROR); + + nodeHash = 31*nodeHash + errorHash; + *pHashcode = nodeHash; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_VerifyNode *node = NULL; + PKIX_UInt32 childrenHash = 0; + PKIX_UInt32 nodeHash = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_OBJECTNOTVERIFYNODE); + + node = (PKIX_VerifyNode *)object; + + PKIX_CHECK(pkix_SingleVerifyNode_Hashcode + (node, &nodeHash, plContext), + PKIX_SINGLEVERIFYNODEHASHCODEFAILED); + + PKIX_HASHCODE + (node->children, + &childrenHash, + plContext, + PKIX_OBJECTHASHCODEFAILED); + + nodeHash = 31*nodeHash + childrenHash; + + *pHashcode = nodeHash; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_SingleVerifyNode_Equals + * DESCRIPTION: + * + * Compares for equality the components of the VerifyNode pointed to by + * "firstPN", other than its parents and children, with those of the + * VerifyNode pointed to by "secondPN" and stores the result at "pResult" + * (PKIX_TRUE if equal; PKIX_FALSE if not). + * + * PARAMETERS: + * "firstPN" + * Address of first of the VerifyNodes to be compared; must be non-NULL + * "secondPN" + * Address of second of the VerifyNodes to be compared; must be non-NULL + * "pResult" + * Address where Boolean will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_SingleVerifyNode_Equals( + PKIX_VerifyNode *firstVN, + PKIX_VerifyNode *secondVN, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Equals"); + PKIX_NULLCHECK_THREE(firstVN, secondVN, pResult); + + /* If both references are identical, they must be equal */ + if (firstVN == secondVN) { + compResult = PKIX_TRUE; + goto cleanup; + } + + /* + * It seems we have to do the comparisons. Do + * the easiest ones first. + */ + if ((firstVN->depth) != (secondVN->depth)) { + goto cleanup; + } + + /* These fields must be non-NULL */ + PKIX_NULLCHECK_TWO(firstVN->verifyCert, secondVN->verifyCert); + + PKIX_EQUALS + (firstVN->verifyCert, + secondVN->verifyCert, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + PKIX_EQUALS + (firstVN->error, + secondVN->error, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + +cleanup: + + *pResult = compResult; + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_VerifyNode *firstVN = NULL; + PKIX_VerifyNode *secondVN = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a VerifyNode */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_FIRSTOBJECTNOTVERIFYNODE); + + /* + * Since we know firstObject is a VerifyNode, + * if both references are identical, they must be equal + */ + if (firstObject == secondObject){ + compResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a VerifyNode, we + * don't throw an error. We simply return FALSE. + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + if (secondType != PKIX_VERIFYNODE_TYPE) { + goto cleanup; + } + + /* + * Oh, well, we have to do the comparisons. Do + * the easiest ones first. + */ + firstVN = (PKIX_VerifyNode *)firstObject; + secondVN = (PKIX_VerifyNode *)secondObject; + + PKIX_CHECK(pkix_SingleVerifyNode_Equals + (firstVN, secondVN, &compResult, plContext), + PKIX_SINGLEVERIFYNODEEQUALSFAILED); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + PKIX_EQUALS + (firstVN->children, + secondVN->children, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILEDONCHILDREN); + +cleanup: + + *pResult = compResult; + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_DuplicateHelper + * DESCRIPTION: + * + * Duplicates the VerifyNode whose address is pointed to by "original", + * and stores the result at "pNewNode", if a non-NULL pointer is provided + * for "pNewNode". In addition, the created VerifyNode is added as a child + * to "parent", if a non-NULL pointer is provided for "parent". Then this + * function is called recursively to duplicate each of the children of + * "original". At the top level this function is called with a null + * "parent" and a non-NULL "pNewNode". Below the top level "parent" will + * be non-NULL and "pNewNode" will be NULL. + * + * PARAMETERS: + * "original" + * Address of VerifyNode to be copied; must be non-NULL + * "parent" + * Address of VerifyNode to which the created node is to be added as a + * child; NULL for the top-level call and non-NULL below the top level + * "pNewNode" + * Address to store the node created; should be NULL if "parent" is + * non-NULL and vice versa + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_VerifyNode_DuplicateHelper( + PKIX_VerifyNode *original, + PKIX_VerifyNode *parent, + PKIX_VerifyNode **pNewNode, + void *plContext) +{ + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 childIndex = 0; + PKIX_List *children = NULL; /* List of PKIX_VerifyNode */ + PKIX_VerifyNode *copy = NULL; + PKIX_VerifyNode *child = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_DuplicateHelper"); + + PKIX_NULLCHECK_TWO + (original, original->verifyCert); + + /* + * These components are immutable, so copying the pointers + * is sufficient. The create function increments the reference + * counts as it stores the pointers into the new object. + */ + PKIX_CHECK(pkix_VerifyNode_Create + (original->verifyCert, + original->depth, + original->error, + ©, + plContext), + PKIX_VERIFYNODECREATEFAILED); + + /* Are there any children to duplicate? */ + children = original->children; + + if (children) { + PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + for (childIndex = 0; childIndex < numChildren; childIndex++) { + PKIX_CHECK(PKIX_List_GetItem + (children, + childIndex, + (PKIX_PL_Object **)&child, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_VerifyNode_DuplicateHelper + (child, copy, NULL, plContext), + PKIX_VERIFYNODEDUPLICATEHELPERFAILED); + + PKIX_DECREF(child); + } + + if (pNewNode) { + *pNewNode = copy; + copy = NULL; /* no DecRef if we give our handle away */ + } + +cleanup: + PKIX_DECREF(copy); + PKIX_DECREF(child); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_Duplicate + * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_VerifyNode *original = NULL; + PKIX_VerifyNode *copy = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Duplicate"); + + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_OBJECTNOTVERIFYNODE); + + original = (PKIX_VerifyNode *)object; + + PKIX_CHECK(pkix_VerifyNode_DuplicateHelper + (original, NULL, ©, plContext), + PKIX_VERIFYNODEDUPLICATEHELPERFAILED); + + *pNewObject = (PKIX_PL_Object *)copy; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_RegisterSelf + * DESCRIPTION: + * + * Registers PKIX_VERIFYNODE_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_VerifyNode_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_RegisterSelf"); + + entry.description = "VerifyNode"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_VerifyNode); + entry.destructor = pkix_VerifyNode_Destroy; + entry.equalsFunction = pkix_VerifyNode_Equals; + entry.hashcodeFunction = pkix_VerifyNode_Hashcode; + entry.toStringFunction = pkix_VerifyNode_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_VerifyNode_Duplicate; + + systemClasses[PKIX_VERIFYNODE_TYPE] = entry; + + PKIX_RETURN(VERIFYNODE); +} + +/* --Public-VerifyNode-Functions----------------------------------- */ + +/* + * FUNCTION: PKIX_VerifyNode_SetError + * DESCRIPTION: + * + * This function sets the Error field of the VerifyNode pointed to by "node" + * to contain the Error pointed to by "error". + * + * PARAMETERS: + * "node" + * The address of the VerifyNode to be modified. Must be non-NULL. + * "error" + * The address of the Error to be stored. + * "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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_SetError( + PKIX_VerifyNode *node, + PKIX_Error *error, + void *plContext) +{ + + PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_SetError"); + + PKIX_NULLCHECK_TWO(node, error); + + PKIX_DECREF(node->error); /* should have been NULL */ + PKIX_INCREF(error); + node->error = error; + +cleanup: + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: PKIX_VerifyNode_FindError + * DESCRIPTION: + * + * Finds meaningful error in the log. For now, just returns the first + * error it finds in. In the future the function should be changed to + * return a top priority error. + * + * PARAMETERS: + * "node" + * The address of the VerifyNode to be modified. Must be non-NULL. + * "error" + * The address of a pointer the error will be returned to. + * "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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_FindError( + PKIX_VerifyNode *node, + PKIX_Error **error, + void *plContext) +{ + PKIX_VerifyNode *childNode = NULL; + + PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_FindError"); + + /* Make sure the return address is initialized with NULL */ + PKIX_DECREF(*error); + + if (!node) + goto cleanup; + + /* First, try to get error from lowest level. */ + if (node->children) { + PKIX_UInt32 length = 0; + PKIX_UInt32 index = 0; + + PKIX_CHECK( + PKIX_List_GetLength(node->children, &length, + plContext), + PKIX_LISTGETLENGTHFAILED); + for (index = 0;index < length;index++) { + PKIX_CHECK( + PKIX_List_GetItem(node->children, index, + (PKIX_PL_Object**)&childNode, plContext), + PKIX_LISTGETITEMFAILED); + if (!childNode) + continue; + PKIX_CHECK( + pkix_VerifyNode_FindError(childNode, error, + plContext), + PKIX_VERIFYNODEFINDERRORFAILED); + PKIX_DECREF(childNode); + if (*error) { + goto cleanup; + } + } + } + + if (node->error && node->error->plErr) { + PKIX_INCREF(node->error); + *error = node->error; + } + +cleanup: + PKIX_DECREF(childNode); + + PKIX_RETURN(VERIFYNODE); +} diff --git a/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h new file mode 100644 index 0000000000..c943ae4ddc --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h @@ -0,0 +1,75 @@ +/* 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_verifynode.h + * + * VerifyNode Type Definitions + * + */ + +#ifndef _PKIX_VERIFYNODE_H +#define _PKIX_VERIFYNODE_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This structure reflects the contents of a verify node... + */ +struct PKIX_VerifyNodeStruct { + PKIX_PL_Cert *verifyCert; + PKIX_List *children; /* VerifyNodes */ + PKIX_UInt32 depth; + PKIX_Error *error; +}; + +PKIX_Error * +pkix_SingleVerifyNode_ToString( + PKIX_VerifyNode *node, + PKIX_PL_String **pString, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_Create( + PKIX_PL_Cert *verifyCert, + PKIX_UInt32 depth, + PKIX_Error *error, + PKIX_VerifyNode **pObject, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_AddToChain( + PKIX_VerifyNode *parentNode, + PKIX_VerifyNode *child, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_AddToTree( + PKIX_VerifyNode *parentNode, + PKIX_VerifyNode *child, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_SetError( + PKIX_VerifyNode *node, + PKIX_Error *error, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_RegisterSelf( + void *plContext); + +PKIX_Error * +pkix_VerifyNode_FindError( + PKIX_VerifyNode *node, + PKIX_Error **error, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_VERIFYNODE_H */ diff --git a/security/nss/lib/libpkix/pkix/results/results.gyp b/security/nss/lib/libpkix/pkix/results/results.gyp new file mode 100644 index 0000000000..962fdb9481 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/results.gyp @@ -0,0 +1,26 @@ +# 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': 'pkixresults', + 'type': 'static_library', + 'sources': [ + 'pkix_buildresult.c', + 'pkix_policynode.c', + 'pkix_valresult.c', + 'pkix_verifynode.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix/store/Makefile b/security/nss/lib/libpkix/pkix/store/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/store/Makefile @@ -0,0 +1,46 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/store/exports.gyp b/security/nss/lib/libpkix/pkix/store/exports.gyp new file mode 100644 index 0000000000..52f13f5ae7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/store/exports.gyp @@ -0,0 +1,25 @@ +# 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_store_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_store.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/store/manifest.mn b/security/nss/lib/libpkix/pkix/store/manifest.mn new file mode 100644 index 0000000000..53a54d6cc6 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/store/manifest.mn @@ -0,0 +1,18 @@ +# +# 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 = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_store.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_store.c \ + $(NULL) + +LIBRARY_NAME = pkixstore +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/store/pkix_store.c b/security/nss/lib/libpkix/pkix/store/pkix_store.c new file mode 100644 index 0000000000..af8be2bb2c --- /dev/null +++ b/security/nss/lib/libpkix/pkix/store/pkix_store.c @@ -0,0 +1,415 @@ +/* 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_store.c + * + * CertStore Function Definitions + * + */ + +#include "pkix_store.h" + +/* --CertStore-Private-Functions----------------------------------------- */ + +/* + * FUNCTION: pkix_CertStore_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CertStore_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_CertStore *certStore = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_CertStore_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a CertStore object */ + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSTORE_TYPE, plContext), + PKIX_OBJECTNOTCERTSTORE); + + certStore = (PKIX_CertStore *)object; + + certStore->certCallback = NULL; + certStore->crlCallback = NULL; + certStore->certContinue = NULL; + certStore->crlContinue = NULL; + certStore->trustCallback = NULL; + + PKIX_DECREF(certStore->certStoreContext); + +cleanup: + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_CertStore_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CertStore_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_CertStore *certStore = NULL; + PKIX_UInt32 tempHash = 0; + + PKIX_ENTER(CERTSTORE, "pkix_CertStore_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSTORE_TYPE, plContext), + PKIX_OBJECTNOTCERTSTORE); + + certStore = (PKIX_CertStore *)object; + + if (certStore->certStoreContext) { + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *) certStore->certStoreContext, + &tempHash, + plContext), + PKIX_CERTSTOREHASHCODEFAILED); + } + + *pHashcode = (PKIX_UInt32)((char *)certStore->certCallback - (char *)NULL) + + (PKIX_UInt32)((char *)certStore->crlCallback - (char *)NULL) + + (PKIX_UInt32)((char *)certStore->certContinue - (char *)NULL) + + (PKIX_UInt32)((char *)certStore->crlContinue - (char *)NULL) + + (PKIX_UInt32)((char *)certStore->trustCallback - (char *)NULL) + + (tempHash << 7); + +cleanup: + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_CertStore_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CertStore_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_CertStore *firstCS = NULL; + PKIX_CertStore *secondCS = NULL; + PKIX_Boolean cmpResult = PKIX_FALSE; + + PKIX_ENTER(CERTSTORE, "pkix_CertStore_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + PKIX_CHECK(pkix_CheckTypes + (firstObject, secondObject, PKIX_CERTSTORE_TYPE, plContext), + PKIX_ARGUMENTSNOTDATES); + + firstCS = (PKIX_CertStore *)firstObject; + secondCS = (PKIX_CertStore *)secondObject; + + cmpResult = (firstCS->certCallback == secondCS->certCallback) && + (firstCS->crlCallback == secondCS->crlCallback) && + (firstCS->certContinue == secondCS->certContinue) && + (firstCS->crlContinue == secondCS->crlContinue) && + (firstCS->trustCallback == secondCS->trustCallback); + + if (cmpResult && + (firstCS->certStoreContext != secondCS->certStoreContext)) { + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *) firstCS->certStoreContext, + (PKIX_PL_Object *) secondCS->certStoreContext, + &cmpResult, + plContext), + PKIX_CERTSTOREEQUALSFAILED); + } + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_CertStore_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CERTSTORE_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_CertStore_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTSTORE, "pkix_CertStore_RegisterSelf"); + + entry.description = "CertStore"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_CertStore); + entry.destructor = pkix_CertStore_Destroy; + entry.equalsFunction = pkix_CertStore_Equals; + entry.hashcodeFunction = pkix_CertStore_Hashcode; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_CERTSTORE_TYPE] = entry; + + PKIX_RETURN(CERTSTORE); +} + +/* --CertStore-Public-Functions------------------------------------------ */ + +/* + * FUNCTION: PKIX_CertStore_Create (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_Create( + PKIX_CertStore_CertCallback certCallback, + PKIX_CertStore_CRLCallback crlCallback, + PKIX_CertStore_CertContinueFunction certContinue, + PKIX_CertStore_CrlContinueFunction crlContinue, + PKIX_CertStore_CheckTrustCallback trustCallback, + PKIX_CertStore_ImportCrlCallback importCrlCallback, + PKIX_CertStore_CheckRevokationByCrlCallback checkRevByCrlCallback, + PKIX_PL_Object *certStoreContext, + PKIX_Boolean cacheFlag, + PKIX_Boolean localFlag, + PKIX_CertStore **pStore, + void *plContext) +{ + PKIX_CertStore *certStore = NULL; + + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_Create"); + PKIX_NULLCHECK_THREE(certCallback, crlCallback, pStore); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTSTORE_TYPE, + sizeof (PKIX_CertStore), + (PKIX_PL_Object **)&certStore, + plContext), + PKIX_COULDNOTCREATECERTSTOREOBJECT); + + certStore->certCallback = certCallback; + certStore->crlCallback = crlCallback; + certStore->certContinue = certContinue; + certStore->crlContinue = crlContinue; + certStore->trustCallback = trustCallback; + certStore->importCrlCallback = importCrlCallback; + certStore->checkRevByCrlCallback = checkRevByCrlCallback; + certStore->cacheFlag = cacheFlag; + certStore->localFlag = localFlag; + + PKIX_INCREF(certStoreContext); + certStore->certStoreContext = certStoreContext; + + *pStore = certStore; + certStore = NULL; + +cleanup: + + PKIX_DECREF(certStore); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_GetCertCallback (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_GetCertCallback( + PKIX_CertStore *store, + PKIX_CertStore_CertCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertCallback"); + PKIX_NULLCHECK_TWO(store, pCallback); + + *pCallback = store->certCallback; + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_GetCRLCallback (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_GetCRLCallback( + PKIX_CertStore *store, + PKIX_CertStore_CRLCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCRLCallback"); + PKIX_NULLCHECK_TWO(store, pCallback); + + *pCallback = store->crlCallback; + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_CertContinue (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_CertContinue( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCertList, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_CertContinue"); + PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList); + + PKIX_CHECK(store->certContinue + (store, selector, verifyNode, + pNBIOContext, pCertList, plContext), + PKIX_CERTSTORECERTCONTINUEFUNCTIONFAILED); + +cleanup: + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_CrlContinue (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_CrlContinue( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrlList, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_CrlContinue"); + PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList); + + PKIX_CHECK(store->crlContinue + (store, selector, pNBIOContext, pCrlList, plContext), + PKIX_CERTSTORECRLCONTINUEFAILED); + +cleanup: + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_GetTrustCallback (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_GetTrustCallback( + PKIX_CertStore *store, + PKIX_CertStore_CheckTrustCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback"); + PKIX_NULLCHECK_TWO(store, pCallback); + + *pCallback = store->trustCallback; + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_GetImportCrlCallback (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_GetImportCrlCallback( + PKIX_CertStore *store, + PKIX_CertStore_ImportCrlCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback"); + PKIX_NULLCHECK_TWO(store, pCallback); + + *pCallback = store->importCrlCallback; + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_GetCheckRevByCrl (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_GetCrlCheckerFn( + PKIX_CertStore *store, + PKIX_CertStore_CheckRevokationByCrlCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback"); + PKIX_NULLCHECK_TWO(store, pCallback); + + *pCallback = store->checkRevByCrlCallback; + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_GetCertStoreContext + * (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_GetCertStoreContext( + PKIX_CertStore *store, + PKIX_PL_Object **pCertStoreContext, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertStoreContext"); + PKIX_NULLCHECK_TWO(store, pCertStoreContext); + + PKIX_INCREF(store->certStoreContext); + *pCertStoreContext = store->certStoreContext; + +cleanup: + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_GetCertStoreCacheFlag + * (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_GetCertStoreCacheFlag( + PKIX_CertStore *store, + PKIX_Boolean *pCacheFlag, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertStoreCacheFlag"); + PKIX_NULLCHECK_TWO(store, pCacheFlag); + + *pCacheFlag = store->cacheFlag; + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_CertStore_GetLocalFlag + * (see comments in pkix_certstore.h) + */ +PKIX_Error * +PKIX_CertStore_GetLocalFlag( + PKIX_CertStore *store, + PKIX_Boolean *pLocalFlag, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetLocalFlag"); + PKIX_NULLCHECK_TWO(store, pLocalFlag); + + *pLocalFlag = store->localFlag; + + PKIX_RETURN(CERTSTORE); +} diff --git a/security/nss/lib/libpkix/pkix/store/pkix_store.h b/security/nss/lib/libpkix/pkix/store/pkix_store.h new file mode 100644 index 0000000000..9d116ffbda --- /dev/null +++ b/security/nss/lib/libpkix/pkix/store/pkix_store.h @@ -0,0 +1,41 @@ +/* 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_store.h + * + * CertStore Object Type Definition + * + */ + +#ifndef _PKIX_STORE_H +#define _PKIX_STORE_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_CertStoreStruct { + PKIX_CertStore_CertCallback certCallback; + PKIX_CertStore_CRLCallback crlCallback; + PKIX_CertStore_CertContinueFunction certContinue; + PKIX_CertStore_CrlContinueFunction crlContinue; + PKIX_CertStore_CheckTrustCallback trustCallback; + PKIX_CertStore_ImportCrlCallback importCrlCallback; + PKIX_CertStore_CheckRevokationByCrlCallback checkRevByCrlCallback; + PKIX_PL_Object *certStoreContext; + PKIX_Boolean cacheFlag; + PKIX_Boolean localFlag; /* TRUE if CertStore is local */ +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_CertStore_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_STORE_H */ diff --git a/security/nss/lib/libpkix/pkix/store/store.gyp b/security/nss/lib/libpkix/pkix/store/store.gyp new file mode 100644 index 0000000000..43aa177688 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/store/store.gyp @@ -0,0 +1,23 @@ +# 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': 'pkixstore', + 'type': 'static_library', + 'sources': [ + 'pkix_store.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix/top/Makefile b/security/nss/lib/libpkix/pkix/top/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/Makefile @@ -0,0 +1,46 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/top/exports.gyp b/security/nss/lib/libpkix/pkix/top/exports.gyp new file mode 100644 index 0000000000..d41f2b5ec4 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/exports.gyp @@ -0,0 +1,27 @@ +# 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_top_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_build.h', + 'pkix_lifecycle.h', + 'pkix_validate.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/top/manifest.mn b/security/nss/lib/libpkix/pkix/top/manifest.mn new file mode 100644 index 0000000000..5bdd3f300d --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/manifest.mn @@ -0,0 +1,22 @@ +# +# 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 = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_build.h \ + pkix_lifecycle.h \ + pkix_validate.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_validate.c \ + pkix_lifecycle.c \ + pkix_build.c \ + $(NULL) + +LIBRARY_NAME = pkixtop +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/top/pkix_build.c b/security/nss/lib/libpkix/pkix/top/pkix_build.c new file mode 100644 index 0000000000..aebfeebade --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/pkix_build.c @@ -0,0 +1,3763 @@ +/* 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_build.c + * + * Top level buildChain function + * + */ + +/* #define PKIX_BUILDDEBUG 1 */ +/* #define PKIX_FORWARDBUILDERSTATEDEBUG 1 */ + +#include "pkix_build.h" + +extern PRLogModuleInfo *pkixLog; + +/* + * List of critical extension OIDs associate with what build chain has + * checked. Those OIDs need to be removed from the unresolved critical + * extension OIDs list manually (instead of by checker automatically). + */ +static SECOidTag buildCheckedCritExtOIDs[] = { + PKIX_CERTKEYUSAGE_OID, + PKIX_CERTSUBJALTNAME_OID, + PKIX_BASICCONSTRAINTS_OID, + PKIX_NAMECONSTRAINTS_OID, + PKIX_EXTENDEDKEYUSAGE_OID, + PKIX_NSCERTTYPE_OID, + PKIX_UNKNOWN_OID +}; + +/* --Private-ForwardBuilderState-Functions---------------------------------- */ + +/* + * FUNCTION: pkix_ForwardBuilderState_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ForwardBuilderState_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ForwardBuilderState *state = NULL; + + PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext), + PKIX_OBJECTNOTFORWARDBUILDERSTATE); + + state = (PKIX_ForwardBuilderState *)object; + + state->status = BUILD_INITIAL; + state->traversedCACerts = 0; + state->certStoreIndex = 0; + state->numCerts = 0; + state->numAias = 0; + state->certIndex = 0; + state->aiaIndex = 0; + state->certCheckedIndex = 0; + state->checkerIndex = 0; + state->hintCertIndex = 0; + state->numFanout = 0; + state->numDepth = 0; + state->reasonCode = 0; + state->canBeCached = PKIX_FALSE; + state->useOnlyLocal = PKIX_FALSE; + state->revChecking = PKIX_FALSE; + state->usingHintCerts = PKIX_FALSE; + state->certLoopingDetected = PKIX_FALSE; + PKIX_DECREF(state->validityDate); + PKIX_DECREF(state->prevCert); + PKIX_DECREF(state->candidateCert); + PKIX_DECREF(state->traversedSubjNames); + PKIX_DECREF(state->trustChain); + PKIX_DECREF(state->aia); + PKIX_DECREF(state->candidateCerts); + PKIX_DECREF(state->reversedCertChain); + PKIX_DECREF(state->checkedCritExtOIDs); + PKIX_DECREF(state->checkerChain); + PKIX_DECREF(state->certSel); + PKIX_DECREF(state->verifyNode); + PKIX_DECREF(state->client); + + /* + * If we ever add a child link we have to be careful not to have loops + * in the Destroy process. But with one-way links we should be okay. + */ + if (state->parentState == NULL) { + state->buildConstants.numAnchors = 0; + state->buildConstants.numCertStores = 0; + state->buildConstants.numHintCerts = 0; + state->buildConstants.procParams = 0; + PKIX_DECREF(state->buildConstants.testDate); + PKIX_DECREF(state->buildConstants.timeLimit); + PKIX_DECREF(state->buildConstants.targetCert); + PKIX_DECREF(state->buildConstants.targetPubKey); + PKIX_DECREF(state->buildConstants.certStores); + PKIX_DECREF(state->buildConstants.anchors); + PKIX_DECREF(state->buildConstants.userCheckers); + PKIX_DECREF(state->buildConstants.hintCerts); + PKIX_DECREF(state->buildConstants.revChecker); + PKIX_DECREF(state->buildConstants.aiaMgr); + } else { + PKIX_DECREF(state->parentState); + } + +cleanup: + + PKIX_RETURN(FORWARDBUILDERSTATE); +} + +/* + * FUNCTION: pkix_ForwardBuilderState_Create + * + * DESCRIPTION: + * Allocate and initialize a ForwardBuilderState. + * + * PARAMETERS + * "traversedCACerts" + * Number of CA certificates traversed. + * "numFanout" + * Number of Certs that can be considered at this level (0 = no limit) + * "numDepth" + * Number of additional levels that can be searched (0 = no limit) + * "canBeCached" + * Boolean value indicating whether all certs on the chain can be cached. + * "validityDate" + * Address of Date at which build chain Certs' most restricted validity + * time is kept. May be NULL. + * "prevCert" + * Address of Cert just traversed. Must be non-NULL. + * "traversedSubjNames" + * Address of List of GeneralNames that have been traversed. + * Must be non-NULL. + * "trustChain" + * Address of List of certificates traversed. Must be non-NULL. + * "parentState" + * Address of previous ForwardBuilderState + * "pState" + * Address where ForwardBuilderState 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 Build 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_ForwardBuilderState_Create( + PKIX_Int32 traversedCACerts, + PKIX_UInt32 numFanout, + PKIX_UInt32 numDepth, + PKIX_Boolean canBeCached, + PKIX_PL_Date *validityDate, + PKIX_PL_Cert *prevCert, + PKIX_List *traversedSubjNames, + PKIX_List *trustChain, + PKIX_ForwardBuilderState *parentState, + PKIX_ForwardBuilderState **pState, + void *plContext) +{ + PKIX_ForwardBuilderState *state = NULL; + + PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Create"); + PKIX_NULLCHECK_FOUR(prevCert, traversedSubjNames, pState, trustChain); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_FORWARDBUILDERSTATE_TYPE, + sizeof (PKIX_ForwardBuilderState), + (PKIX_PL_Object **)&state, + plContext), + PKIX_COULDNOTCREATEFORWARDBUILDERSTATEOBJECT); + + state->status = BUILD_INITIAL; + state->traversedCACerts = traversedCACerts; + state->certStoreIndex = 0; + state->numCerts = 0; + state->numAias = 0; + state->certIndex = 0; + state->aiaIndex = 0; + state->certCheckedIndex = 0; + state->checkerIndex = 0; + state->hintCertIndex = 0; + state->numFanout = numFanout; + state->numDepth = numDepth; + state->reasonCode = 0; + state->revChecking = numDepth; + state->canBeCached = canBeCached; + state->useOnlyLocal = PKIX_TRUE; + state->revChecking = PKIX_FALSE; + state->usingHintCerts = PKIX_FALSE; + state->certLoopingDetected = PKIX_FALSE; + + PKIX_INCREF(validityDate); + state->validityDate = validityDate; + + PKIX_INCREF(prevCert); + state->prevCert = prevCert; + + state->candidateCert = NULL; + + PKIX_INCREF(traversedSubjNames); + state->traversedSubjNames = traversedSubjNames; + + PKIX_INCREF(trustChain); + state->trustChain = trustChain; + + state->aia = NULL; + state->candidateCerts = NULL; + state->reversedCertChain = NULL; + state->checkedCritExtOIDs = NULL; + state->checkerChain = NULL; + state->certSel = NULL; + state->verifyNode = NULL; + state->client = NULL; + + PKIX_INCREF(parentState); + state->parentState = parentState; + + if (parentState != NULL) { + state->buildConstants.numAnchors = + parentState->buildConstants.numAnchors; + state->buildConstants.numCertStores = + parentState->buildConstants.numCertStores; + state->buildConstants.numHintCerts = + parentState->buildConstants.numHintCerts; + state->buildConstants.maxFanout = + parentState->buildConstants.maxFanout; + state->buildConstants.maxDepth = + parentState->buildConstants.maxDepth; + state->buildConstants.maxTime = + parentState->buildConstants.maxTime; + state->buildConstants.procParams = + parentState->buildConstants.procParams; + state->buildConstants.testDate = + parentState->buildConstants.testDate; + state->buildConstants.timeLimit = + parentState->buildConstants.timeLimit; + state->buildConstants.targetCert = + parentState->buildConstants.targetCert; + state->buildConstants.targetPubKey = + parentState->buildConstants.targetPubKey; + state->buildConstants.certStores = + parentState->buildConstants.certStores; + state->buildConstants.anchors = + parentState->buildConstants.anchors; + state->buildConstants.userCheckers = + parentState->buildConstants.userCheckers; + state->buildConstants.hintCerts = + parentState->buildConstants.hintCerts; + state->buildConstants.revChecker = + parentState->buildConstants.revChecker; + state->buildConstants.aiaMgr = + parentState->buildConstants.aiaMgr; + state->buildConstants.trustOnlyUserAnchors = + parentState->buildConstants.trustOnlyUserAnchors; + } + + *pState = state; + state = NULL; +cleanup: + + PKIX_DECREF(state); + + PKIX_RETURN(FORWARDBUILDERSTATE); +} + +/* + * FUNCTION: pkix_Build_GetResourceLimits + * + * DESCRIPTION: + * Retrieve Resource Limits from ProcessingParams and initialize them in + * BuildConstants. + * + * PARAMETERS + * "buildConstants" + * Address of a BuildConstants structure containing objects and values + * that remain constant throughout the building of a chain. 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 Build 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_Build_GetResourceLimits( + BuildConstants *buildConstants, + void *plContext) +{ + PKIX_ResourceLimits *resourceLimits = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_GetResourceLimits"); + PKIX_NULLCHECK_ONE(buildConstants); + + PKIX_CHECK(PKIX_ProcessingParams_GetResourceLimits + (buildConstants->procParams, &resourceLimits, plContext), + PKIX_PROCESSINGPARAMSGETRESOURCELIMITSFAILED); + + buildConstants->maxFanout = 0; + buildConstants->maxDepth = 0; + buildConstants->maxTime = 0; + + if (resourceLimits) { + + PKIX_CHECK(PKIX_ResourceLimits_GetMaxFanout + (resourceLimits, &buildConstants->maxFanout, plContext), + PKIX_RESOURCELIMITSGETMAXFANOUTFAILED); + + PKIX_CHECK(PKIX_ResourceLimits_GetMaxDepth + (resourceLimits, &buildConstants->maxDepth, plContext), + PKIX_RESOURCELIMITSGETMAXDEPTHFAILED); + + PKIX_CHECK(PKIX_ResourceLimits_GetMaxTime + (resourceLimits, &buildConstants->maxTime, plContext), + PKIX_RESOURCELIMITSGETMAXTIMEFAILED); + } + +cleanup: + + PKIX_DECREF(resourceLimits); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_ForwardBuilderState_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ForwardBuilderState_ToString + (PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_ForwardBuilderState *state = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *resultString = NULL; + PKIX_PL_String *buildStatusString = NULL; + PKIX_PL_String *validityDateString = NULL; + PKIX_PL_String *prevCertString = NULL; + PKIX_PL_String *candidateCertString = NULL; + PKIX_PL_String *traversedSubjNamesString = NULL; + PKIX_PL_String *trustChainString = NULL; + PKIX_PL_String *candidateCertsString = NULL; + PKIX_PL_String *certSelString = NULL; + PKIX_PL_String *verifyNodeString = NULL; + PKIX_PL_String *parentStateString = NULL; + char *asciiFormat = "\n" + "\t{buildStatus: \t%s\n" + "\ttraversedCACerts: \t%d\n" + "\tcertStoreIndex: \t%d\n" + "\tnumCerts: \t%d\n" + "\tnumAias: \t%d\n" + "\tcertIndex: \t%d\n" + "\taiaIndex: \t%d\n" + "\tnumFanout: \t%d\n" + "\tnumDepth: \t%d\n" + "\treasonCode: \t%d\n" + "\tcanBeCached: \t%d\n" + "\tuseOnlyLocal: \t%d\n" + "\trevChecking: \t%d\n" + "\tvalidityDate: \t%s\n" + "\tprevCert: \t%s\n" + "\tcandidateCert: \t%s\n" + "\ttraversedSubjNames: \t%s\n" + "\ttrustChain: \t%s\n" + "\tcandidateCerts: \t%s\n" + "\tcertSel: \t%s\n" + "\tverifyNode: \t%s\n" + "\tparentState: \t%s}\n"; + char *asciiStatus = NULL; + + PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext), + PKIX_OBJECTNOTFORWARDBUILDERSTATE); + + state = (PKIX_ForwardBuilderState *)object; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + + switch (state->status) { + case BUILD_SHORTCUTPENDING: asciiStatus = "BUILD_SHORTCUTPENDING"; + break; + case BUILD_INITIAL: asciiStatus = "BUILD_INITIAL"; + break; + case BUILD_TRYAIA: asciiStatus = "BUILD_TRYAIA"; + break; + case BUILD_AIAPENDING: asciiStatus = "BUILD_AIAPENDING"; + break; + case BUILD_COLLECTINGCERTS: asciiStatus = "BUILD_COLLECTINGCERTS"; + break; + case BUILD_GATHERPENDING: asciiStatus = "BUILD_GATHERPENDING"; + break; + case BUILD_CERTVALIDATING: asciiStatus = "BUILD_CERTVALIDATING"; + break; + case BUILD_ABANDONNODE: asciiStatus = "BUILD_ABANDONNODE"; + break; + case BUILD_DATEPREP: asciiStatus = "BUILD_DATEPREP"; + break; + case BUILD_CHECKTRUSTED: asciiStatus = "BUILD_CHECKTRUSTED"; + break; + case BUILD_CHECKTRUSTED2: asciiStatus = "BUILD_CHECKTRUSTED2"; + break; + case BUILD_ADDTOCHAIN: asciiStatus = "BUILD_ADDTOCHAIN"; + break; + case BUILD_VALCHAIN: asciiStatus = "BUILD_VALCHAIN"; + break; + case BUILD_VALCHAIN2: asciiStatus = "BUILD_VALCHAIN2"; + break; + case BUILD_EXTENDCHAIN: asciiStatus = "BUILD_EXTENDCHAIN"; + break; + case BUILD_GETNEXTCERT: asciiStatus = "BUILD_GETNEXTCERT"; + break; + default: asciiStatus = "INVALID STATUS"; + break; + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiStatus, 0, &buildStatusString, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_TOSTRING + (state->validityDate, &validityDateString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->prevCert, &prevCertString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->candidateCert, &candidateCertString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->traversedSubjNames, + &traversedSubjNamesString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->trustChain, &trustChainString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->candidateCerts, &candidateCertsString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->certSel, &certSelString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->verifyNode, &verifyNodeString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (state->parentState, &parentStateString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + formatString, + buildStatusString, + (PKIX_Int32)state->traversedCACerts, + (PKIX_UInt32)state->certStoreIndex, + (PKIX_UInt32)state->numCerts, + (PKIX_UInt32)state->numAias, + (PKIX_UInt32)state->certIndex, + (PKIX_UInt32)state->aiaIndex, + (PKIX_UInt32)state->numFanout, + (PKIX_UInt32)state->numDepth, + (PKIX_UInt32)state->reasonCode, + state->canBeCached, + state->useOnlyLocal, + state->revChecking, + validityDateString, + prevCertString, + candidateCertString, + traversedSubjNamesString, + trustChainString, + candidateCertsString, + certSelString, + verifyNodeString, + parentStateString), + PKIX_SPRINTFFAILED); + + *pString = resultString; + +cleanup: + PKIX_DECREF(formatString); + PKIX_DECREF(buildStatusString); + PKIX_DECREF(validityDateString); + PKIX_DECREF(prevCertString); + PKIX_DECREF(candidateCertString); + PKIX_DECREF(traversedSubjNamesString); + PKIX_DECREF(trustChainString); + PKIX_DECREF(candidateCertsString); + PKIX_DECREF(certSelString); + PKIX_DECREF(verifyNodeString); + PKIX_DECREF(parentStateString); + + PKIX_RETURN(FORWARDBUILDERSTATE); + +} + +/* + * FUNCTION: pkix_ForwardBuilderState_RegisterSelf + * + * DESCRIPTION: + * Registers PKIX_FORWARDBUILDERSTATE_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_ForwardBuilderState_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(FORWARDBUILDERSTATE, + "pkix_ForwardBuilderState_RegisterSelf"); + + entry.description = "ForwardBuilderState"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_ForwardBuilderState); + entry.destructor = pkix_ForwardBuilderState_Destroy; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = pkix_ForwardBuilderState_ToString; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_FORWARDBUILDERSTATE_TYPE] = entry; + + PKIX_RETURN(FORWARDBUILDERSTATE); +} + +#if PKIX_FORWARDBUILDERSTATEDEBUG +/* + * FUNCTION: pkix_ForwardBuilderState_DumpState + * + * DESCRIPTION: + * This function invokes the ToString function on the argument pointed to + * by "state". + * PARAMETERS: + * "state" + * The address of the ForwardBuilderState object. Must be non-NULL. + * + * THREAD SAFETY: + * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) + */ +PKIX_Error * +pkix_ForwardBuilderState_DumpState( + PKIX_ForwardBuilderState *state, + void *plContext) +{ + PKIX_PL_String *stateString = NULL; + char *stateAscii = NULL; + PKIX_UInt32 length; + + PKIX_ENTER(FORWARDBUILDERSTATE,"pkix_ForwardBuilderState_DumpState"); + PKIX_NULLCHECK_ONE(state); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)state, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)state, &stateString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stateString, + PKIX_ESCASCII, + (void **)&stateAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_DEBUG_ARG("In Phase 1: state = %s\n", stateAscii); + + PKIX_FREE(stateAscii); + PKIX_DECREF(stateString); + +cleanup: + PKIX_RETURN(FORWARDBUILDERSTATE); +} +#endif + +/* + * FUNCTION: pkix_ForwardBuilderState_IsIOPending + * DESCRIPTION: + * + * This function determines whether the state of the ForwardBuilderState + * pointed to by "state" indicates I/O is in progress, and stores the Boolean + * result at "pPending". + * + * PARAMETERS: + * "state" + * The address of the ForwardBuilderState object. Must be non-NULL. + * "pPending" + * The address at which the result is 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 ForwardBuilderState 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_ForwardBuilderState_IsIOPending( + PKIX_ForwardBuilderState *state, + PKIX_Boolean *pPending, + void *plContext) +{ + PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_IsIOPending"); + PKIX_NULLCHECK_TWO(state, pPending); + + if ((state->status == BUILD_GATHERPENDING) || + (state->status == BUILD_CHECKTRUSTED2) || + (state->status == BUILD_VALCHAIN2) || + (state->status == BUILD_AIAPENDING)) { + *pPending = PKIX_TRUE; + } else { + *pPending = PKIX_FALSE; + } + + PKIX_RETURN(FORWARDBUILDERSTATE); +} + +/* --Private-BuildChain-Functions------------------------------------------- */ + +/* + * FUNCTION: pkix_Build_SortCertComparator + * DESCRIPTION: + * + * This Function takes two Certificates cast in "obj1" and "obj2", + * compares them to determine which is a more preferable certificate + * for chain building. This Function is suitable for use as a + * comparator callback for pkix_List_BubbleSort, setting "*pResult" to + * > 0 if "obj1" is less desirable than "obj2" and < 0 if "obj1" + * is more desirable than "obj2". + * + * PARAMETERS: + * "obj1" + * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert. + * Must be non-NULL. + * "obj2" + * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert. + * Must be non-NULL. + * "pResult" + * Address where the comparison 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 Build 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_Build_SortCertComparator( + PKIX_PL_Object *obj1, + PKIX_PL_Object *obj2, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_PL_Date *date1 = NULL; + PKIX_PL_Date *date2 = NULL; + PKIX_Int32 result = 0; + + PKIX_ENTER(BUILD, "pkix_Build_SortCertComparator"); + PKIX_NULLCHECK_THREE(obj1, obj2, pResult); + + /* + * For sorting candidate certificates, we use NotAfter date as the + * comparison key for now (can be expanded if desired in the future). + * + * In PKIX_BuildChain, the List of CertStores was reordered so that + * trusted CertStores are ahead of untrusted CertStores. That sort, or + * this one, could be taken out if it is determined that it doesn't help + * performance, or in some way hinders the solution of choosing desired + * candidates. + */ + + PKIX_CHECK(pkix_CheckType(obj1, PKIX_CERT_TYPE, plContext), + PKIX_OBJECTNOTCERT); + PKIX_CHECK(pkix_CheckType(obj2, PKIX_CERT_TYPE, plContext), + PKIX_OBJECTNOTCERT); + + PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter + ((PKIX_PL_Cert *)obj1, &date1, plContext), + PKIX_CERTGETVALIDITYNOTAFTERFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter + ((PKIX_PL_Cert *)obj2, &date2, plContext), + PKIX_CERTGETVALIDITYNOTAFTERFAILED); + + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)date1, + (PKIX_PL_Object *)date2, + &result, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + + /* + * Invert the result, so that if date1 is greater than date2, + * obj1 is sorted before obj2. This is because pkix_List_BubbleSort + * sorts in ascending order. + */ + *pResult = -result; + +cleanup: + + PKIX_DECREF(date1); + PKIX_DECREF(date2); + + PKIX_RETURN(BUILD); +} + +/* This local error check macro */ +#define ERROR_CHECK(errCode) \ + if (pkixErrorResult) { \ + if (pkixLog) { \ + PR_LOG(pkixLog, PR_LOG_DEBUG, ("====> ERROR_CHECK code %s\n", #errCode)); \ + } \ + pkixTempErrorReceived = PKIX_TRUE; \ + pkixErrorClass = pkixErrorResult->errClass; \ + if (pkixErrorClass == PKIX_FATAL_ERROR) { \ + goto cleanup; \ + } \ + if (verifyNode) { \ + PKIX_DECREF(verifyNode->error); \ + PKIX_INCREF(pkixErrorResult); \ + verifyNode->error = pkixErrorResult; \ + } \ + pkixErrorCode = errCode; \ + goto cleanup; \ + } + +/* + * FUNCTION: pkix_Build_VerifyCertificate + * DESCRIPTION: + * + * Checks whether the previous Cert stored in the ForwardBuilderState pointed + * to by "state" successfully chains, including signature verification, to the + * candidate Cert also stored in "state", using the Boolean value in "trusted" + * to determine whether "candidateCert" is trusted. + * + * First it checks whether "candidateCert" has already been traversed by + * determining whether it is contained in the List of traversed Certs. It then + * checks the candidate Cert with user checkers, if any, in the List pointed to + * by "userCheckers". Finally, it runs the signature validation. + * + * If this Certificate fails verification, and state->verifyNode is non-NULL, + * this function sets the Error code into the verifyNode. + * + * PARAMETERS: + * "state" + * Address of ForwardBuilderState to be used. Must be non-NULL. + * "userCheckers" + * Address of a List of CertChainCheckers to be used, if present, to + * validate the candidateCert. + * "trusted" + * Boolean value of trust for the candidate Cert + * "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 Build 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_Build_VerifyCertificate( + PKIX_ForwardBuilderState *state, + PKIX_List *userCheckers, + PKIX_Boolean *pTrusted, + PKIX_VerifyNode *verifyNode, + void *plContext) +{ + PKIX_UInt32 numUserCheckers = 0; + PKIX_UInt32 i = 0; + PKIX_Boolean loopFound = PKIX_FALSE; + PKIX_Boolean supportForwardChecking = PKIX_FALSE; + PKIX_Boolean trusted = PKIX_FALSE; + PKIX_PL_Cert *candidateCert = NULL; + PKIX_PL_PublicKey *candidatePubKey = NULL; + PKIX_CertChainChecker *userChecker = NULL; + PKIX_CertChainChecker_CheckCallback checkerCheck = NULL; + PKIX_PL_TrustAnchorMode trustAnchorMode = + PKIX_PL_TrustAnchorMode_Ignore; + void *nbioContext = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_VerifyCertificate"); + PKIX_NULLCHECK_TWO(state, pTrusted); + PKIX_NULLCHECK_THREE + (state->candidateCerts, state->prevCert, state->trustChain); + + PKIX_INCREF(state->candidateCert); + candidateCert = state->candidateCert; + + if (state->buildConstants.numAnchors) { + if (state->buildConstants.trustOnlyUserAnchors) { + trustAnchorMode = PKIX_PL_TrustAnchorMode_Exclusive; + } else { + trustAnchorMode = PKIX_PL_TrustAnchorMode_Additive; + } + } else { + trustAnchorMode = PKIX_PL_TrustAnchorMode_Ignore; + } + + PKIX_CHECK( + PKIX_PL_Cert_IsCertTrusted(candidateCert, trustAnchorMode, + &trusted, plContext), + PKIX_CERTISCERTTRUSTEDFAILED); + + *pTrusted = trusted; + + /* check for loops */ + PKIX_CHECK(pkix_List_Contains + (state->trustChain, + (PKIX_PL_Object *)candidateCert, + &loopFound, + plContext), + PKIX_LISTCONTAINSFAILED); + + if (loopFound) { + if (verifyNode != NULL) { + PKIX_Error *verifyError = NULL; + PKIX_ERROR_CREATE + (BUILD, + PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED, + verifyError); + PKIX_DECREF(verifyNode->error); + verifyNode->error = verifyError; + } + /* Even if error logged, still need to abort + * if cert is not trusted. */ + if (!trusted) { + PKIX_ERROR(PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED); + } + state->certLoopingDetected = PKIX_TRUE; + } + + if (userCheckers != NULL) { + + PKIX_CHECK(PKIX_List_GetLength + (userCheckers, &numUserCheckers, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numUserCheckers; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (userCheckers, + i, + (PKIX_PL_Object **) &userChecker, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK + (PKIX_CertChainChecker_IsForwardCheckingSupported + (userChecker, &supportForwardChecking, plContext), + PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); + + if (supportForwardChecking == PKIX_TRUE) { + + PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback + (userChecker, &checkerCheck, plContext), + PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED); + + pkixErrorResult = + checkerCheck(userChecker, candidateCert, NULL, + &nbioContext, plContext); + + ERROR_CHECK(PKIX_USERCHECKERCHECKFAILED); + } + + PKIX_DECREF(userChecker); + } + } + + /* Check that public key of the trusted dsa cert has + * dsa parameters */ + if (trusted) { + PKIX_Boolean paramsNeeded = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey + (candidateCert, &candidatePubKey, plContext), + PKIX_CERTGETSUBJECTPUBLICKEYFAILED); + PKIX_CHECK(PKIX_PL_PublicKey_NeedsDSAParameters + (candidatePubKey, ¶msNeeded, plContext), + PKIX_PUBLICKEYNEEDSDSAPARAMETERSFAILED); + if (paramsNeeded) { + PKIX_ERROR(PKIX_MISSINGDSAPARAMETERS); + } + } + +cleanup: + PKIX_DECREF(candidateCert); + PKIX_DECREF(candidatePubKey); + PKIX_DECREF(userChecker); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_Build_ValidationCheckers + * DESCRIPTION: + * + * Creates a List of Objects to be used in determining whether the List of + * Certs pointed to by "certChain" successfully validates using the + * ForwardBuilderState pointed to by "state", and the TrustAnchor pointed to by + * "anchor". These objects are a reversed Cert Chain, consisting of the certs + * in "certChain" in reversed order, suitable for presenting to the + * CertChainCheckers; a List of critical extension OIDS that have already been + * processed in forward building; a List of CertChainCheckers to be called, and + * a List of RevocationCheckers to be called. These results are stored in + * fields of "state". + * + * PARAMETERS: + * "state" + * Address of ForwardBuilderState to be used. Must be non-NULL. + * "certChain" + * Address of List of Certs to be validated. Must be non-NULL. + * "anchor" + * Address of TrustAnchor to be used. Must be non-NULL. + * "addEkuChecker" + * Boolean flags that tells to add eku checker to the list + * of checkers. Only needs to be done for existing chain revalidation. + * "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 Build 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_Build_ValidationCheckers( + PKIX_ForwardBuilderState *state, + PKIX_List *certChain, + PKIX_TrustAnchor *anchor, + PKIX_Boolean chainRevalidationStage, + void *plContext) +{ + PKIX_List *checkers = NULL; + PKIX_List *initialPolicies = NULL; + PKIX_List *reversedCertChain = NULL; + PKIX_List *buildCheckedCritExtOIDsList = NULL; + PKIX_ProcessingParams *procParams = NULL; + PKIX_PL_Cert *trustedCert = NULL; + PKIX_PL_PublicKey *trustedPubKey = NULL; + PKIX_PL_CertNameConstraints *trustedNC = NULL; + PKIX_CertChainChecker *sigChecker = NULL; + PKIX_CertChainChecker *policyChecker = NULL; + PKIX_CertChainChecker *userChecker = NULL; + PKIX_CertChainChecker *nameConstraintsChecker = NULL; + PKIX_CertChainChecker *checker = NULL; + PKIX_CertSelector *certSelector = NULL; + PKIX_List *userCheckerExtOIDs = NULL; + PKIX_PL_OID *oid = NULL; + PKIX_Boolean supportForwardChecking = PKIX_FALSE; + PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; + PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; + PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; + PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; + PKIX_UInt32 numChainCerts; + PKIX_UInt32 numCertCheckers; + PKIX_UInt32 i; + + PKIX_ENTER(BUILD, "pkix_Build_ValidationCheckers"); + PKIX_NULLCHECK_THREE(state, certChain, anchor); + + PKIX_CHECK(PKIX_List_Create(&checkers, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_ReverseList + (certChain, &reversedCertChain, plContext), + PKIX_LISTREVERSELISTFAILED); + + PKIX_CHECK(PKIX_List_GetLength + (reversedCertChain, &numChainCerts, plContext), + PKIX_LISTGETLENGTHFAILED); + + procParams = state->buildConstants.procParams; + + /* Do need to add a number of checker to revalidate + * a built chain. KU, EKU, CertType and Validity Date + * get checked by certificate selector during chain + * construction, but needed to be checked for chain from + * the cache.*/ + if (chainRevalidationStage) { + PKIX_CHECK(pkix_ExpirationChecker_Initialize + (state->buildConstants.testDate, &checker, plContext), + PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)checker, plContext), + PKIX_LISTAPPENDITEMFAILED); + PKIX_DECREF(checker); + + PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints + (procParams, &certSelector, plContext), + PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); + + PKIX_CHECK(pkix_TargetCertChecker_Initialize + (certSelector, numChainCerts, &checker, plContext), + PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)checker, plContext), + PKIX_LISTAPPENDITEMFAILED); + PKIX_DECREF(checker); + } + + PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies + (procParams, &initialPolicies, plContext), + PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected + (procParams, &policyQualifiersRejected, plContext), + PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited + (procParams, &initialPolicyMappingInhibit, plContext), + PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited + (procParams, &initialAnyPolicyInhibit, plContext), + PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired + (procParams, &initialExplicitPolicy, plContext), + PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED); + + PKIX_CHECK(pkix_PolicyChecker_Initialize + (initialPolicies, + policyQualifiersRejected, + initialPolicyMappingInhibit, + initialExplicitPolicy, + initialAnyPolicyInhibit, + numChainCerts, + &policyChecker, + plContext), + PKIX_POLICYCHECKERINITIALIZEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)policyChecker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + /* + * Create an OID list that contains critical extensions processed + * by BuildChain. These are specified in a static const array. + */ + PKIX_CHECK(PKIX_List_Create(&buildCheckedCritExtOIDsList, plContext), + PKIX_LISTCREATEFAILED); + + for (i = 0; buildCheckedCritExtOIDs[i] != PKIX_UNKNOWN_OID; i++) { + PKIX_CHECK(PKIX_PL_OID_Create + (buildCheckedCritExtOIDs[i], &oid, plContext), + PKIX_OIDCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (buildCheckedCritExtOIDsList, + (PKIX_PL_Object *) oid, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(oid); + } + + if (state->buildConstants.userCheckers != NULL) { + + PKIX_CHECK(PKIX_List_GetLength + (state->buildConstants.userCheckers, + &numCertCheckers, + plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numCertCheckers; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (state->buildConstants.userCheckers, + i, + (PKIX_PL_Object **) &userChecker, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK + (PKIX_CertChainChecker_IsForwardCheckingSupported + (userChecker, &supportForwardChecking, plContext), + PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); + + /* + * If this userChecker supports forwardChecking then it + * should have been checked during build chain. Skip + * checking but need to add checker's extension OIDs + * to buildCheckedCritExtOIDsList. + */ + if (supportForwardChecking == PKIX_TRUE) { + + PKIX_CHECK + (PKIX_CertChainChecker_GetSupportedExtensions + (userChecker, &userCheckerExtOIDs, plContext), + PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); + + if (userCheckerExtOIDs != NULL) { + PKIX_CHECK(pkix_List_AppendList + (buildCheckedCritExtOIDsList, + userCheckerExtOIDs, + plContext), + PKIX_LISTAPPENDLISTFAILED); + } + + } else { + PKIX_CHECK(PKIX_List_AppendItem + (checkers, + (PKIX_PL_Object *)userChecker, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + PKIX_DECREF(userCheckerExtOIDs); + PKIX_DECREF(userChecker); + } + } + + /* Enabling post chain building signature check on the certs. */ + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert + (anchor, &trustedCert, plContext), + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey + (trustedCert, &trustedPubKey, plContext), + PKIX_CERTGETSUBJECTPUBLICKEYFAILED); + + PKIX_CHECK(pkix_SignatureChecker_Initialize + (trustedPubKey, + numChainCerts, + &sigChecker, + plContext), + PKIX_SIGNATURECHECKERINITIALIZEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, + (PKIX_PL_Object *)sigChecker, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + /* Enabling post chain building name constraints check on the certs. */ + PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints + (anchor, &trustedNC, plContext), + PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED); + + PKIX_CHECK(pkix_NameConstraintsChecker_Initialize + (trustedNC, numChainCerts, &nameConstraintsChecker, + plContext), + PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, + (PKIX_PL_Object *)nameConstraintsChecker, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + + PKIX_DECREF(state->reversedCertChain); + PKIX_INCREF(reversedCertChain); + state->reversedCertChain = reversedCertChain; + PKIX_DECREF(state->checkedCritExtOIDs); + PKIX_INCREF(buildCheckedCritExtOIDsList); + state->checkedCritExtOIDs = buildCheckedCritExtOIDsList; + PKIX_DECREF(state->checkerChain); + state->checkerChain = checkers; + checkers = NULL; + state->certCheckedIndex = 0; + state->checkerIndex = 0; + state->revChecking = PKIX_FALSE; + + +cleanup: + + PKIX_DECREF(oid); + PKIX_DECREF(reversedCertChain); + PKIX_DECREF(buildCheckedCritExtOIDsList); + PKIX_DECREF(checker); + PKIX_DECREF(checkers); + PKIX_DECREF(initialPolicies); + PKIX_DECREF(trustedCert); + PKIX_DECREF(trustedPubKey); + PKIX_DECREF(certSelector); + PKIX_DECREF(sigChecker); + PKIX_DECREF(trustedNC); + PKIX_DECREF(nameConstraintsChecker); + PKIX_DECREF(policyChecker); + PKIX_DECREF(userChecker); + PKIX_DECREF(userCheckerExtOIDs); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_Build_ValidateEntireChain + * DESCRIPTION: + * + * Checks whether the current List of Certs successfully validates using the + * TrustAnchor pointed to by "anchor" and other parameters contained, as was + * the Cert List, in "state". + * + * If a checker using non-blocking I/O returns with a non-NULL non-blocking I/O + * context (NBIOContext), an indication that I/O is in progress and the + * checking has not been completed, this function stores that context at + * "pNBIOContext". Otherwise, it stores NULL at "pNBIOContext". + * + * If not awaiting I/O and if successful, a ValidateResult is created + * containing the Public Key of the target certificate (including DSA parameter + * inheritance, if any) and the PolicyNode representing the policy tree output + * by the validation algorithm. If not successful, an Error pointer is + * returned. + * + * PARAMETERS: + * "state" + * Address of ForwardBuilderState to be used. Must be non-NULL. + * "anchor" + * Address of TrustAnchor to be used. Must be non-NULL. + * "pNBIOContext" + * Address at which the NBIOContext is stored indicating whether the + * validation is complete. Must be non-NULL. + * "pValResult" + * Address at which the ValidateResult is 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 Build 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_Build_ValidateEntireChain( + PKIX_ForwardBuilderState *state, + PKIX_TrustAnchor *anchor, + void **pNBIOContext, + PKIX_ValidateResult **pValResult, + PKIX_VerifyNode *verifyNode, + void *plContext) +{ + PKIX_UInt32 numChainCerts = 0; + PKIX_PL_PublicKey *subjPubKey = NULL; + PKIX_PolicyNode *policyTree = NULL; + PKIX_ValidateResult *valResult = NULL; + void *nbioContext = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_ValidateEntireChain"); + PKIX_NULLCHECK_FOUR(state, anchor, pNBIOContext, pValResult); + + *pNBIOContext = NULL; /* prepare for case of error exit */ + + PKIX_CHECK(PKIX_List_GetLength + (state->reversedCertChain, &numChainCerts, plContext), + PKIX_LISTGETLENGTHFAILED); + + pkixErrorResult = + pkix_CheckChain(state->reversedCertChain, numChainCerts, anchor, + state->checkerChain, + state->buildConstants.revChecker, + state->checkedCritExtOIDs, + state->buildConstants.procParams, + &state->certCheckedIndex, &state->checkerIndex, + &state->revChecking, &state->reasonCode, + &nbioContext, &subjPubKey, &policyTree, NULL, + plContext); + + if (nbioContext != NULL) { + *pNBIOContext = nbioContext; + goto cleanup; + } + + ERROR_CHECK(PKIX_CHECKCHAINFAILED); + + /* XXX Remove this assertion after 2014-12-31. See bug 946984. */ + PORT_Assert(state->reasonCode == 0); + + PKIX_CHECK(pkix_ValidateResult_Create + (subjPubKey, anchor, policyTree, &valResult, plContext), + PKIX_VALIDATERESULTCREATEFAILED); + + *pValResult = valResult; + valResult = NULL; + +cleanup: + PKIX_DECREF(subjPubKey); + PKIX_DECREF(policyTree); + PKIX_DECREF(valResult); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_Build_SortCandidateCerts + * DESCRIPTION: + * + * This function sorts a List of candidate Certs pointed to by "candidates" + * using an algorithm that places Certs most likely to produce a successful + * chain at the front of the list, storing the resulting sorted List at + * "pSortedCandidates". + * + * At present the only sort criterion is that trusted Certs go ahead of + * untrusted Certs. + * + * PARAMETERS: + * "candidates" + * Address of List of Candidate Certs to be sorted. Must be non-NULL. + * "pSortedCandidates" + * Address at which sorted List is 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 Build 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_Build_SortCandidateCerts( + PKIX_List *candidates, + PKIX_List **pSortedCandidates, + void *plContext) +{ + PKIX_List *sortedList = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_SortCandidateCerts"); + PKIX_NULLCHECK_TWO(candidates, pSortedCandidates); + + /* + * Both bubble and quick sort algorithms are available. + * For a list of fewer than around 100 items, the bubble sort is more + * efficient. (This number was determined by experimenting with both + * algorithms on a Java List.) + * If the candidate list is very small, using the sort can drag down + * the performance a little bit. + */ + + PKIX_CHECK(pkix_List_BubbleSort + (candidates, + pkix_Build_SortCertComparator, + &sortedList, + plContext), + PKIX_LISTBUBBLESORTFAILED); + + *pSortedCandidates = sortedList; + +cleanup: + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_Build_BuildSelectorAndParams + * DESCRIPTION: + * + * This function creates a CertSelector, initialized with an appropriate + * ComCertSelParams, using the variables provided in the ForwardBuilderState + * pointed to by "state". The CertSelector created is stored in the certsel + * element of "state". + * + * PARAMETERS: + * "state" + * Address of ForwardBuilderState to be used. 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 Build 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_Build_BuildSelectorAndParams( + PKIX_ForwardBuilderState *state, + void *plContext) +{ + PKIX_ComCertSelParams *certSelParams = NULL; + PKIX_CertSelector *certSel = NULL; + PKIX_PL_X500Name *currentIssuer = NULL; + PKIX_PL_ByteArray *authKeyId = NULL; + PKIX_PL_Date *testDate = NULL; + PKIX_CertSelector *callerCertSelector = NULL; + PKIX_ComCertSelParams *callerComCertSelParams = NULL; + PKIX_UInt32 reqKu = 0; + PKIX_List *reqEkuOids = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_BuildSelectorAndParams"); + PKIX_NULLCHECK_THREE(state, state->prevCert, state->traversedSubjNames); + + PKIX_CHECK(PKIX_PL_Cert_GetIssuer + (state->prevCert, ¤tIssuer, plContext), + PKIX_CERTGETISSUERFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier + (state->prevCert, &authKeyId, plContext), + PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_Create(&certSelParams, plContext), + PKIX_COMCERTSELPARAMSCREATEFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_SetSubject + (certSelParams, currentIssuer, plContext), + PKIX_COMCERTSELPARAMSSETSUBJECTFAILED); + + if (authKeyId != NULL) { + PKIX_CHECK(PKIX_ComCertSelParams_SetSubjKeyIdentifier + (certSelParams, authKeyId, plContext), + PKIX_COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED); + } + + PKIX_INCREF(state->buildConstants.testDate); + testDate = state->buildConstants.testDate; + + PKIX_CHECK(PKIX_ComCertSelParams_SetCertificateValid + (certSelParams, testDate, plContext), + PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_SetBasicConstraints + (certSelParams, state->traversedCACerts, plContext), + PKIX_COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_SetPathToNames + (certSelParams, state->traversedSubjNames, plContext), + PKIX_COMCERTSELPARAMSSETPATHTONAMESFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints + (state->buildConstants.procParams, + &callerCertSelector, plContext), + PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); + + if (callerCertSelector != NULL) { + + /* Get initial EKU OIDs from ComCertSelParams, if set */ + PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams + (callerCertSelector, &callerComCertSelParams, plContext), + PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); + + if (callerComCertSelParams != NULL) { + PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage + (callerComCertSelParams, &reqEkuOids, plContext), + PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage + (callerComCertSelParams, &reqKu, plContext), + PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); + } + } + + PKIX_CHECK( + PKIX_ComCertSelParams_SetKeyUsage(certSelParams, reqKu, + plContext), + PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED); + + PKIX_CHECK( + PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams, + reqEkuOids, + plContext), + PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED); + + PKIX_CHECK(PKIX_CertSelector_Create + (NULL, NULL, &state->certSel, plContext), + PKIX_CERTSELECTORCREATEFAILED); + + PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams + (state->certSel, certSelParams, plContext), + PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); + + PKIX_CHECK(PKIX_List_Create(&state->candidateCerts, plContext), + PKIX_LISTCREATEFAILED); + + state->certStoreIndex = 0; + +cleanup: + PKIX_DECREF(certSelParams); + PKIX_DECREF(certSel); + PKIX_DECREF(currentIssuer); + PKIX_DECREF(authKeyId); + PKIX_DECREF(testDate); + PKIX_DECREF(reqEkuOids); + PKIX_DECREF(callerComCertSelParams); + PKIX_DECREF(callerCertSelector); + + PKIX_RETURN(BUILD); +} + +/* Match trust anchor to select params in order to find next cert. */ +static PKIX_Error* +pkix_Build_SelectCertsFromTrustAnchors( + PKIX_List *trustAnchorsList, + PKIX_ComCertSelParams *certSelParams, + PKIX_List **pMatchList, + void *plContext) +{ + unsigned int anchorIndex = 0; + PKIX_TrustAnchor *anchor = NULL; + PKIX_PL_Cert *trustedCert = NULL; + PKIX_List *matchList = NULL; + PKIX_CertSelector *certSel = NULL; + PKIX_CertSelector_MatchCallback selectorMatchCB = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_SelectCertsFromTrustAnchors"); + + PKIX_CHECK(PKIX_CertSelector_Create + (NULL, NULL, &certSel, plContext), + PKIX_CERTSELECTORCREATEFAILED); + PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams + (certSel, certSelParams, plContext), + PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); + PKIX_CHECK(PKIX_CertSelector_GetMatchCallback + (certSel, &selectorMatchCB, plContext), + PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); + + for (anchorIndex = 0;anchorIndex < trustAnchorsList->length; anchorIndex++) { + PKIX_CHECK( + PKIX_List_GetItem(trustAnchorsList, + anchorIndex, + (PKIX_PL_Object **)&anchor, + plContext), + PKIX_LISTGETITEMFAILED); + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert + (anchor, &trustedCert, plContext), + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); + pkixErrorResult = + (*selectorMatchCB)(certSel, trustedCert, plContext); + if (!pkixErrorResult) { + if (!matchList) { + PKIX_CHECK(PKIX_List_Create(&matchList, + plContext), + PKIX_LISTCREATEFAILED); + } + PKIX_CHECK( + PKIX_List_AppendItem(matchList, + (PKIX_PL_Object*)trustedCert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } else { + PKIX_DECREF(pkixErrorResult); + } + PKIX_DECREF(trustedCert); + PKIX_DECREF(anchor); + } + + *pMatchList = matchList; + matchList = NULL; + +cleanup: + PKIX_DECREF(matchList); + PKIX_DECREF(trustedCert); + PKIX_DECREF(anchor); + PKIX_DECREF(certSel); + + PKIX_RETURN(BUILD); +} + + +static PKIX_Error* +pkix_Build_RemoveDupUntrustedCerts( + PKIX_List *trustedCertList, + PKIX_List *certsFound, + void *plContext) +{ + PKIX_UInt32 trustIndex; + PKIX_PL_Cert *trustCert = NULL, *cert = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_RemoveDupUntrustedCerts"); + if (trustedCertList == NULL || certsFound == NULL) { + goto cleanup; + } + for (trustIndex = 0;trustIndex < trustedCertList->length; + trustIndex++) { + PKIX_UInt32 certIndex = 0; + PKIX_CHECK( + PKIX_List_GetItem(trustedCertList, + trustIndex, + (PKIX_PL_Object **)&trustCert, + plContext), + PKIX_LISTGETITEMFAILED); + + while (certIndex < certsFound->length) { + PKIX_Boolean result = PKIX_FALSE; + PKIX_DECREF(cert); + PKIX_CHECK( + PKIX_List_GetItem(certsFound, certIndex, + (PKIX_PL_Object **)&cert, + plContext), + PKIX_LISTGETITEMFAILED); + PKIX_CHECK( + PKIX_PL_Object_Equals((PKIX_PL_Object *)trustCert, + (PKIX_PL_Object *)cert, + &result, + plContext), + PKIX_OBJECTEQUALSFAILED); + if (!result) { + certIndex += 1; + continue; + } + PKIX_CHECK( + PKIX_List_DeleteItem(certsFound, certIndex, + plContext), + PKIX_LISTDELETEITEMFAILED); + } + PKIX_DECREF(trustCert); + } +cleanup: + PKIX_DECREF(cert); + PKIX_DECREF(trustCert); + + PKIX_RETURN(BUILD); +} + + +/* + * FUNCTION: pkix_Build_GatherCerts + * DESCRIPTION: + * + * This function traverses the CertStores in the List of CertStores contained + * in "state", using the certSelector and other parameters contained in + * "state", to obtain a List of all available Certs that satisfy the criteria. + * If a CertStore has a cache, "certSelParams" is used both to query the cache + * and, if an actual CertStore search occurred, to update the cache. (Behavior + * is undefined if "certSelParams" is different from the parameters that were + * used to initialize the certSelector in "state".) + * + * If a CertStore using non-blocking I/O returns with an indication that I/O is + * in progress and the checking has not been completed, this function stores + * platform-dependent information at "pNBIOContext". Otherwise it stores NULL + * at "pNBIOContext", and state is updated with the results of the search. + * + * PARAMETERS: + * "state" + * Address of ForwardBuilderState to be used. Must be non-NULL. + * "certSelParams" + * Address of ComCertSelParams which were used in creating the current + * CertSelector, and to be used in querying and updating any caches that + * may be associated with with the CertStores. + * "pNBIOContext" + * Address at which platform-dependent information is returned if request + * is suspended for non-blocking I/O. 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 Build Error if the function fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +/* return NULL if wouldblock, empty list if none found, else list of found */ +static PKIX_Error * +pkix_Build_GatherCerts( + PKIX_ForwardBuilderState *state, + PKIX_ComCertSelParams *certSelParams, + void **pNBIOContext, + void *plContext) +{ + PKIX_Boolean certStoreIsCached = PKIX_FALSE; + PKIX_Boolean certStoreIsLocal = PKIX_FALSE; + PKIX_Boolean foundInCache = PKIX_FALSE; + PKIX_CertStore *certStore = NULL; + PKIX_CertStore_CertCallback getCerts = NULL; + PKIX_List *certsFound = NULL; + PKIX_List *trustedCertList = NULL; + void *nbioContext = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_GatherCerts"); + PKIX_NULLCHECK_THREE(state, certSelParams, pNBIOContext); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + PKIX_DECREF(state->candidateCerts); + + while (state->certStoreIndex < state->buildConstants.numCertStores) { + + /* Get the current CertStore */ + PKIX_CHECK(PKIX_List_GetItem + (state->buildConstants.certStores, + state->certStoreIndex, + (PKIX_PL_Object **)&certStore, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_CertStore_GetLocalFlag + (certStore, &certStoreIsLocal, plContext), + PKIX_CERTSTOREGETLOCALFLAGFAILED); + + if (state->useOnlyLocal == certStoreIsLocal) { + /* If GATHERPENDING, we've already checked the cache */ + if (state->status == BUILD_GATHERPENDING) { + certStoreIsCached = PKIX_FALSE; + foundInCache = PKIX_FALSE; + } else { + PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag + (certStore, &certStoreIsCached, plContext), + PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED); + + if (certStoreIsCached) { + /* + * Look for Certs in the cache, using the SubjectName as + * the key. Then the ComCertSelParams are used to filter + * for qualified certs. If none are found, then the + * certStores are queried. When we eventually add items + * to the cache, we will only add items that passed the + * ComCertSelParams filter, rather than all Certs which + * matched the SubjectName. + */ + + PKIX_CHECK(pkix_CacheCert_Lookup + (certStore, + certSelParams, + state->buildConstants.testDate, + &foundInCache, + &certsFound, + plContext), + PKIX_CACHECERTCHAINLOOKUPFAILED); + + } + } + + /* + * XXX need to verify if Cert is trusted, hence may not + * be worth it to have the Cert Cached or + * If it is trusted, don't cache, but once there is cached + * certs, we won't get certs from database any more. + * can use flag to force not getting certs from cache + */ + if (!foundInCache) { + + if (nbioContext == NULL) { + PKIX_CHECK(PKIX_CertStore_GetCertCallback + (certStore, &getCerts, plContext), + PKIX_CERTSTOREGETCERTCALLBACKFAILED); + + PKIX_CHECK(getCerts + (certStore, + state->certSel, + state->verifyNode, + &nbioContext, + &certsFound, + plContext), + PKIX_GETCERTSFAILED); + } else { + PKIX_CHECK(PKIX_CertStore_CertContinue + (certStore, + state->certSel, + state->verifyNode, + &nbioContext, + &certsFound, + plContext), + PKIX_CERTSTORECERTCONTINUEFAILED); + } + + if (certStoreIsCached && certsFound) { + + PKIX_CHECK(pkix_CacheCert_Add + (certStore, + certSelParams, + certsFound, + plContext), + PKIX_CACHECERTADDFAILED); + } + } + + /* + * getCerts returns an empty list for "NONE FOUND", + * a NULL list for "would block" + */ + if (certsFound == NULL) { + state->status = BUILD_GATHERPENDING; + *pNBIOContext = nbioContext; + goto cleanup; + } + } + + /* Are there any more certStores to query? */ + PKIX_DECREF(certStore); + ++(state->certStoreIndex); + } + + if (certsFound && certsFound->length > 1) { + PKIX_List *sorted = NULL; + + /* sort Certs to try to optimize search */ + PKIX_CHECK(pkix_Build_SortCandidateCerts + (certsFound, &sorted, plContext), + PKIX_BUILDSORTCANDIDATECERTSFAILED); + PKIX_DECREF(certsFound); + certsFound = sorted; + } + + PKIX_CHECK( + pkix_Build_SelectCertsFromTrustAnchors( + state->buildConstants.anchors, + certSelParams, &trustedCertList, + plContext), + PKIX_FAILTOSELECTCERTSFROMANCHORS); + PKIX_CHECK( + pkix_Build_RemoveDupUntrustedCerts(trustedCertList, + certsFound, + plContext), + PKIX_REMOVEDUPUNTRUSTEDCERTSFAILED); + + PKIX_CHECK( + pkix_List_MergeLists(trustedCertList, + certsFound, + &state->candidateCerts, + plContext), + PKIX_LISTMERGEFAILED); + + /* No, return the list we have gathered */ + PKIX_CHECK(PKIX_List_GetLength + (state->candidateCerts, &state->numCerts, plContext), + PKIX_LISTGETLENGTHFAILED); + + state->certIndex = 0; + +cleanup: + PKIX_DECREF(trustedCertList); + PKIX_DECREF(certStore); + PKIX_DECREF(certsFound); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_Build_UpdateDate + * DESCRIPTION: + * + * This function updates the validityDate contained in "state", for the current + * CertChain contained in "state", to include the validityDate of the + * candidateCert contained in "state". The validityDate of a chain is the + * earliest of all the notAfter dates contained in the respective Certificates. + * + * PARAMETERS: + * "state" + * Address of ForwardBuilderState to be used. 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 Build 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_Build_UpdateDate( + PKIX_ForwardBuilderState *state, + void *plContext) +{ + PKIX_Boolean canBeCached = PKIX_FALSE; + PKIX_Int32 comparison = 0; + PKIX_PL_Date *notAfter = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_UpdateDate"); + PKIX_NULLCHECK_ONE(state); + + PKIX_CHECK(PKIX_PL_Cert_GetCacheFlag + (state->candidateCert, &canBeCached, plContext), + PKIX_CERTGETCACHEFLAGFAILED); + + state->canBeCached = state->canBeCached && canBeCached; + if (state->canBeCached == PKIX_TRUE) { + + /* + * So far, all certs can be cached. Update cert + * chain validity time, which is the earliest of + * all certs' notAfter times. + */ + PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter + (state->candidateCert, ¬After, plContext), + PKIX_CERTGETVALIDITYNOTAFTERFAILED); + + if (state->validityDate == NULL) { + state->validityDate = notAfter; + notAfter = NULL; + } else { + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)state->validityDate, + (PKIX_PL_Object *)notAfter, + &comparison, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + if (comparison > 0) { + PKIX_DECREF(state->validityDate); + state->validityDate = notAfter; + notAfter = NULL; + } + } + } + +cleanup: + + PKIX_DECREF(notAfter); + + PKIX_RETURN(BUILD); +} + +/* Prepare 'state' for the AIA round. */ +static void +pkix_PrepareForwardBuilderStateForAIA( + PKIX_ForwardBuilderState *state) +{ + PORT_Assert(state->useOnlyLocal == PKIX_TRUE); + state->useOnlyLocal = PKIX_FALSE; + state->certStoreIndex = 0; + state->numFanout = state->buildConstants.maxFanout; + state->status = BUILD_TRYAIA; +} + +extern SECStatus +isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert, + CERTCertificate *referenceCert); + +/* + * FUNCTION: pkix_BuildForwardDepthFirstSearch + * DESCRIPTION: + * + * This function performs a depth first search in the "forward" direction (from + * the target Cert to the trust anchor). A non-NULL targetCert must be stored + * in the ForwardBuilderState before this function is called. It is not written + * recursively since execution may be suspended in in any of several places + * pending completion of non-blocking I/O. This iterative structure makes it + * much easier to resume where it left off. + * + * Since the nature of the search is recursive, the recursion is handled by + * chaining states. That is, each new step involves creating a new + * ForwardBuilderState linked to its predecessor. If a step turns out to be + * fruitless, the state of the predecessor is restored and the next alternative + * is tried. When a search is successful, values needed from the last state + * (canBeCached and validityDate) are copied to the state provided by the + * caller, so that the caller can retrieve those values. + * + * There are three return arguments, the NBIOContext, the ValidateResult and + * the ForwardBuilderState. If NBIOContext is non-NULL, it means the search is + * suspended until the results of a non-blocking IO become available. The + * caller may wait for the completion using platform-dependent methods and then + * call this function again, allowing it to resume the search. If NBIOContext + * is NULL and the ValidateResult is non-NULL, it means the search has + * concluded successfully. If the NBIOContext is NULL but the ValidateResult is + * NULL, it means the search was unsuccessful. + * + * This function performs several steps at each node in the constructed chain: + * + * 1) It retrieves Certs from the registered CertStores that match the + * criteria established by the ForwardBuilderState pointed to by "state", such + * as a subject name matching the issuer name of the previous Cert. If there + * are no matching Certs, the function returns to the previous, or "parent", + * state and tries to continue the chain building with another of the Certs + * obtained from the CertStores as possible issuers for that parent Cert. + * + * 2) For each candidate Cert returned by the CertStores, this function checks + * whether the Cert is valid. If it is trusted, this function checks whether + * this Cert might serve as a TrustAnchor for a complete chain. + * + * 3) It determines whether this Cert, in conjunction with any of the + * TrustAnchors, might complete a chain. A complete chain, from this or the + * preceding step, is checked to see whether it is valid as a complete + * chain, including the checks that cannot be done in the forward direction. + * + * 4) If this Cert chains successfully, but is not a complete chain, that is, + * we have not reached a trusted Cert, a new ForwardBuilderState is created + * with this Cert as the immediate predecessor, and we continue in step (1), + * attempting to get Certs from the CertStores with this Certs "issuer" as + * their subject. + * + * 5) If an entire chain validates successfully, then we are done. A + * ValidateResult is created containing the Public Key of the target + * certificate (including DSA parameter inheritance, if any) and the + * PolicyNode representing the policy tree output by the validation algorithm, + * and stored at pValResult, and the function exits returning NULL. + * + * 5) If the entire chain does not validate successfully, the algorithm + * discards the latest Cert and continues in step 2 with the next candidate + * Cert, backing up to a parent state when no more possibilities exist at a + * given level, and returning failure when we try to back up but discover we + * are at the top level. + * + * PARAMETERS: + * "pNBIOContext" + * Address at which platform-dependent information is returned if building + * is suspended for non-blocking I/O. Must be non-NULL. + * "pState" + * Address at which input ForwardBuilderState is found, and at which output + * ForwardBuilderState is stored. Must be non-NULL. + * "pValResult" + * Address at which the ValidateResult is 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 Build 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_BuildForwardDepthFirstSearch( + void **pNBIOContext, + PKIX_ForwardBuilderState *state, + PKIX_ValidateResult **pValResult, + void *plContext) +{ + PKIX_Boolean outOfOptions = PKIX_FALSE; + PKIX_Boolean trusted = PKIX_FALSE; + PKIX_Boolean isSelfIssued = PKIX_FALSE; + PKIX_Boolean canBeCached = PKIX_FALSE; + PKIX_Boolean ioPending = PKIX_FALSE; + PKIX_PL_Date *validityDate = NULL; + PKIX_PL_Date *currTime = NULL; + PKIX_Int32 childTraversedCACerts = 0; + PKIX_UInt32 numSubjectNames = 0; + PKIX_UInt32 numChained = 0; + PKIX_Int32 cmpTimeResult = 0; + PKIX_UInt32 i = 0; + PKIX_UInt32 certsSoFar = 0; + PKIX_List *childTraversedSubjNames = NULL; + PKIX_List *subjectNames = NULL; + PKIX_List *unfilteredCerts = NULL; + PKIX_List *filteredCerts = NULL; + PKIX_PL_Object *subjectName = NULL; + PKIX_ValidateResult *valResult = NULL; + PKIX_ForwardBuilderState *childState = NULL; + PKIX_ForwardBuilderState *parentState = NULL; + PKIX_PL_Object *revCheckerState = NULL; + PKIX_ComCertSelParams *certSelParams = NULL; + PKIX_TrustAnchor *trustAnchor = NULL; + PKIX_PL_Cert *trustedCert = NULL; + PKIX_PL_Cert *targetCert = NULL; + PKIX_VerifyNode *verifyNode = NULL; + PKIX_Error *verifyError = NULL; + PKIX_Error *finalError = NULL; + void *nbio = NULL; + PKIX_UInt32 numIterations = 0; + + PKIX_ENTER(BUILD, "pkix_BuildForwardDepthFirstSearch"); + PKIX_NULLCHECK_THREE(pNBIOContext, state, pValResult); + + nbio = *pNBIOContext; + *pNBIOContext = NULL; + PKIX_INCREF(state->validityDate); + validityDate = state->validityDate; + canBeCached = state->canBeCached; + PKIX_DECREF(*pValResult); + targetCert = state->buildConstants.targetCert; + + /* + * We return if successful; if we fall off the end + * of this "while" clause our search has failed. + */ + while (outOfOptions == PKIX_FALSE) { + /* + * The maximum number of iterations works around a bug that + * causes this while loop to never exit when AIA and cross + * certificates are involved. See bug xxxxx. + */ + if (numIterations++ > 250) + PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS); + + if (state->buildConstants.maxTime != 0) { + PKIX_DECREF(currTime); + PKIX_CHECK(PKIX_PL_Date_Create_UTCTime + (NULL, &currTime, plContext), + PKIX_DATECREATEUTCTIMEFAILED); + + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)state->buildConstants.timeLimit, + (PKIX_PL_Object *)currTime, + &cmpTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + + if (cmpTimeResult < 0) { + if (state->verifyNode != NULL) { + PKIX_ERROR_CREATE + (BUILD, + PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS, + verifyError); + PKIX_CHECK_FATAL(pkix_VerifyNode_SetError + (state->verifyNode, + verifyError, + plContext), + PKIX_VERIFYNODESETERRORFAILED); + PKIX_DECREF(finalError); + finalError = verifyError; + verifyError = NULL; + } + /* Even if we logged error, we still have to abort */ + PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS); + } + } + + if (state->status == BUILD_INITIAL) { + + PKIX_CHECK(pkix_Build_BuildSelectorAndParams(state, plContext), + PKIX_BUILDBUILDSELECTORANDPARAMSFAILED); + + /* + * If the caller supplied a partial certChain (hintCerts) try + * the next one from that List before we go to the certStores. + */ + if (state->buildConstants.numHintCerts > 0) { + /* How many Certs does our trust chain have already? */ + PKIX_CHECK(PKIX_List_GetLength + (state->trustChain, &certsSoFar, plContext), + PKIX_LISTGETLENGTHFAILED); + + /* That includes the target Cert. Don't count it. */ + certsSoFar--; + + /* Are we still within range of the partial chain? */ + if (certsSoFar >= state->buildConstants.numHintCerts) { + state->status = BUILD_TRYAIA; + } else { + /* + * If we already have n certs, we want the n+1th + * (i.e., index = n) from the list of hints. + */ + PKIX_DECREF(state->candidateCert); + PKIX_CHECK(PKIX_List_GetItem + (state->buildConstants.hintCerts, + certsSoFar, + (PKIX_PL_Object **)&state->candidateCert, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (state->candidateCerts, + (PKIX_PL_Object *)state->candidateCert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + state->numCerts = 1; + state->usingHintCerts = PKIX_TRUE; + state->status = BUILD_CERTVALIDATING; + } + } else { + state->status = BUILD_TRYAIA; + } + + } + + if (state->status == BUILD_TRYAIA) { + if (state->useOnlyLocal == PKIX_TRUE) { + state->status = BUILD_COLLECTINGCERTS; + } else { + state->status = BUILD_AIAPENDING; + } + } + + if (state->status == BUILD_AIAPENDING && + state->buildConstants.aiaMgr) { + pkixErrorResult = PKIX_PL_AIAMgr_GetAIACerts + (state->buildConstants.aiaMgr, + state->prevCert, + &nbio, + &unfilteredCerts, + plContext); + + if (nbio != NULL) { + /* IO still pending, resume later */ + *pNBIOContext = nbio; + goto cleanup; + } + state->numCerts = 0; + if (pkixErrorResult) { + pkixErrorClass = pkixErrorResult->errClass; + if (pkixErrorClass == PKIX_FATAL_ERROR) { + goto fatal; + } + PKIX_DECREF(finalError); + finalError = pkixErrorResult; + pkixErrorResult = NULL; + if (state->verifyNode != NULL) { + /* state->verifyNode is the object that contains a list + * of verifyNodes. verifyNodes contains cert chain + * build failures that occurred on this level of chain + * building. Here, creating new verify node + * to log the failure and adding it to the list. */ + PKIX_CHECK_FATAL(pkix_VerifyNode_Create + (state->prevCert, + 0, NULL, + &verifyNode, + plContext), + PKIX_VERIFYNODECREATEFAILED); + PKIX_CHECK_FATAL(pkix_VerifyNode_SetError + (verifyNode, finalError, plContext), + PKIX_VERIFYNODESETERRORFAILED); + PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree + (state->verifyNode, + verifyNode, + plContext), + PKIX_VERIFYNODEADDTOTREEFAILED); + PKIX_DECREF(verifyNode); + } + } +#ifdef PKIX_BUILDDEBUG + /* Turn this on to trace the List of Certs, before CertSelect */ + { + PKIX_PL_String *unString; + char *unAscii; + PKIX_UInt32 length; + PKIX_TOSTRING + ((PKIX_PL_Object*)unfilteredCerts, + &unString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (unString, + PKIX_ESCASCII, + (void **)&unAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_DEBUG_ARG + ("unfilteredCerts = %s\n", unAscii); + PKIX_DECREF(unString); + PKIX_FREE(unAscii); + } +#endif + + /* Note: Certs winnowed here don't get into VerifyTree. */ + if (unfilteredCerts) { + PKIX_CHECK(pkix_CertSelector_Select + (state->certSel, + unfilteredCerts, + &filteredCerts, + plContext), + PKIX_CERTSELECTORSELECTFAILED); + + PKIX_DECREF(unfilteredCerts); + + PKIX_CHECK(PKIX_List_GetLength + (filteredCerts, &(state->numCerts), plContext), + PKIX_LISTGETLENGTHFAILED); + +#ifdef PKIX_BUILDDEBUG + /* Turn this on to trace the List of Certs, after CertSelect */ + { + PKIX_PL_String *unString; + char *unAscii; + PKIX_UInt32 length; + PKIX_TOSTRING + ((PKIX_PL_Object*)filteredCerts, + &unString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (unString, + PKIX_ESCASCII, + (void **)&unAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_DEBUG_ARG("filteredCerts = %s\n", unAscii); + PKIX_DECREF(unString); + PKIX_FREE(unAscii); + } +#endif + + PKIX_DECREF(state->candidateCerts); + state->candidateCerts = filteredCerts; + state->certIndex = 0; + filteredCerts = NULL; + } + + /* Are there any Certs to try? */ + if (state->numCerts > 0) { + state->status = BUILD_CERTVALIDATING; + } else { + state->status = BUILD_COLLECTINGCERTS; + } + } + + PKIX_DECREF(certSelParams); + PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams + (state->certSel, &certSelParams, plContext), + PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); + + /* **** Querying the CertStores ***** */ + if ((state->status == BUILD_COLLECTINGCERTS) || + (state->status == BUILD_GATHERPENDING)) { + +#if PKIX_FORWARDBUILDERSTATEDEBUG + PKIX_CHECK(pkix_ForwardBuilderState_DumpState + (state, plContext), + PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED); +#endif + + PKIX_CHECK(pkix_Build_GatherCerts + (state, certSelParams, &nbio, plContext), + PKIX_BUILDGATHERCERTSFAILED); + + if (nbio != NULL) { + /* IO still pending, resume later */ + *pNBIOContext = nbio; + goto cleanup; + } + + /* Are there any Certs to try? */ + if (state->numCerts > 0) { + state->status = BUILD_CERTVALIDATING; + } else { + state->status = BUILD_ABANDONNODE; + } + } + + /* ****Phase 2 - Chain building***** */ + +#if PKIX_FORWARDBUILDERSTATEDEBUG + PKIX_CHECK(pkix_ForwardBuilderState_DumpState(state, plContext), + PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED); +#endif + + if (state->status == BUILD_CERTVALIDATING) { + PKIX_DECREF(state->candidateCert); + PKIX_CHECK(PKIX_List_GetItem + (state->candidateCerts, + state->certIndex, + (PKIX_PL_Object **)&(state->candidateCert), + plContext), + PKIX_LISTGETITEMFAILED); + + if (isIssuerCertAllowedAtCertIssuanceTime( + state->candidateCert->nssCert, targetCert->nssCert) + != SECSuccess) { + PKIX_ERROR(PKIX_CERTISBLOCKLISTEDATISSUANCETIME); + } + + if ((state->verifyNode) != NULL) { + PKIX_CHECK_FATAL(pkix_VerifyNode_Create + (state->candidateCert, + 0, + NULL, + &verifyNode, + plContext), + PKIX_VERIFYNODECREATEFAILED); + } + + /* If failure, this function sets Error in verifyNode */ + verifyError = pkix_Build_VerifyCertificate + (state, + state->buildConstants.userCheckers, + &trusted, + verifyNode, + plContext); + + if (verifyError) { + pkixTempErrorReceived = PKIX_TRUE; + pkixErrorClass = verifyError->errClass; + if (pkixErrorClass == PKIX_FATAL_ERROR) { + pkixErrorResult = verifyError; + verifyError = NULL; + goto fatal; + } + } + + if (PKIX_ERROR_RECEIVED) { + if (state->verifyNode != NULL) { + PKIX_CHECK_FATAL(pkix_VerifyNode_SetError + (verifyNode, verifyError, plContext), + PKIX_VERIFYNODESETERRORFAILED); + PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree + (state->verifyNode, + verifyNode, + plContext), + PKIX_VERIFYNODEADDTOTREEFAILED); + PKIX_DECREF(verifyNode); + } + pkixTempErrorReceived = PKIX_FALSE; + PKIX_DECREF(finalError); + finalError = verifyError; + verifyError = NULL; + if (state->certLoopingDetected) { + PKIX_ERROR + (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED); + } + state->status = BUILD_GETNEXTCERT; + } else { + state->status = BUILD_DATEPREP; + } + } + + if (state->status == BUILD_DATEPREP) { + /* Keep track of whether this chain can be cached */ + PKIX_CHECK(pkix_Build_UpdateDate(state, plContext), + PKIX_BUILDUPDATEDATEFAILED); + + canBeCached = state->canBeCached; + PKIX_DECREF(validityDate); + PKIX_INCREF(state->validityDate); + validityDate = state->validityDate; + if (trusted == PKIX_TRUE) { + state->status = BUILD_CHECKTRUSTED; + } else { + state->status = BUILD_ADDTOCHAIN; + } + } + + if (state->status == BUILD_CHECKTRUSTED) { + + /* + * If this cert is trusted, try to validate the entire + * chain using this certificate as trust anchor. + */ + PKIX_CHECK(PKIX_TrustAnchor_CreateWithCert + (state->candidateCert, + &trustAnchor, + plContext), + PKIX_TRUSTANCHORCREATEWITHCERTFAILED); + + PKIX_CHECK(pkix_Build_ValidationCheckers + (state, + state->trustChain, + trustAnchor, + PKIX_FALSE, /* do not add eku checker + * since eku was already + * checked */ + plContext), + PKIX_BUILDVALIDATIONCHECKERSFAILED); + + state->status = BUILD_CHECKTRUSTED2; + } + + if (state->status == BUILD_CHECKTRUSTED2) { + verifyError = + pkix_Build_ValidateEntireChain(state, + trustAnchor, + &nbio, &valResult, + verifyNode, + plContext); + if (nbio != NULL) { + /* IO still pending, resume later */ + goto cleanup; + } else { + /* checking the error for fatal status */ + if (verifyError) { + pkixTempErrorReceived = PKIX_TRUE; + pkixErrorClass = verifyError->errClass; + if (pkixErrorClass == PKIX_FATAL_ERROR) { + pkixErrorResult = verifyError; + verifyError = NULL; + goto fatal; + } + } + if (state->verifyNode != NULL) { + PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree + (state->verifyNode, + verifyNode, + plContext), + PKIX_VERIFYNODEADDTOTREEFAILED); + PKIX_DECREF(verifyNode); + } + if (!PKIX_ERROR_RECEIVED) { + *pValResult = valResult; + valResult = NULL; + /* Change state so IsIOPending is FALSE */ + state->status = BUILD_CHECKTRUSTED; + goto cleanup; + } + PKIX_DECREF(finalError); + finalError = verifyError; + verifyError = NULL; + /* Reset temp error that was set by + * PKIX_CHECK_ONLY_FATAL and continue */ + pkixTempErrorReceived = PKIX_FALSE; + PKIX_DECREF(trustAnchor); + } + + /* + * If chain doesn't validate with a trusted Cert, + * adding more Certs to it can't help. + */ + if (state->certLoopingDetected) { + PKIX_DECREF(verifyError); + PKIX_ERROR_CREATE(BUILD, + PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED, + verifyError); + PKIX_CHECK_FATAL( + pkix_VerifyNode_SetError(state->verifyNode, + verifyError, + plContext), + PKIX_VERIFYNODESETERRORFAILED); + PKIX_DECREF(verifyError); + } + state->status = BUILD_GETNEXTCERT; + } + + /* + * This Cert was not trusted. Add it to our chain, and + * continue building. If we don't reach a trust anchor, + * we'll take it off later and continue without it. + */ + if (state->status == BUILD_ADDTOCHAIN) { + PKIX_CHECK(PKIX_List_AppendItem + (state->trustChain, + (PKIX_PL_Object *)state->candidateCert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + state->status = BUILD_EXTENDCHAIN; + } + + if (state->status == BUILD_EXTENDCHAIN) { + + /* Check whether we are allowed to extend the chain */ + if ((state->buildConstants.maxDepth != 0) && + (state->numDepth <= 1)) { + + if (state->verifyNode != NULL) { + PKIX_ERROR_CREATE + (BUILD, + PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS, + verifyError); + PKIX_CHECK_FATAL(pkix_VerifyNode_SetError + (verifyNode, verifyError, plContext), + PKIX_VERIFYNODESETERRORFAILED); + PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree + (state->verifyNode, verifyNode, plContext), + PKIX_VERIFYNODEADDTOTREEFAILED); + PKIX_DECREF(verifyNode); + PKIX_DECREF(finalError); + finalError = verifyError; + verifyError = NULL; + } + /* Even if error logged, still need to abort */ + PKIX_ERROR(PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS); + } + + PKIX_CHECK(pkix_IsCertSelfIssued + (state->candidateCert, &isSelfIssued, plContext), + PKIX_ISCERTSELFISSUEDFAILED); + + PKIX_CHECK(PKIX_PL_Object_Duplicate + ((PKIX_PL_Object *)state->traversedSubjNames, + (PKIX_PL_Object **)&childTraversedSubjNames, + plContext), + PKIX_OBJECTDUPLICATEFAILED); + + if (isSelfIssued) { + childTraversedCACerts = state->traversedCACerts; + } else { + childTraversedCACerts = state->traversedCACerts + 1; + + PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames + (state->candidateCert, + &subjectNames, + plContext), + PKIX_CERTGETALLSUBJECTNAMESFAILED); + + if (subjectNames) { + PKIX_CHECK(PKIX_List_GetLength + (subjectNames, + &numSubjectNames, + plContext), + PKIX_LISTGETLENGTHFAILED); + + } else { + numSubjectNames = 0; + } + + for (i = 0; i < numSubjectNames; i++) { + PKIX_CHECK(PKIX_List_GetItem + (subjectNames, + i, + &subjectName, + plContext), + PKIX_LISTGETITEMFAILED); + PKIX_NULLCHECK_ONE + (state->traversedSubjNames); + PKIX_CHECK(PKIX_List_AppendItem + (state->traversedSubjNames, + subjectName, + plContext), + PKIX_LISTAPPENDITEMFAILED); + PKIX_DECREF(subjectName); + } + PKIX_DECREF(subjectNames); + } + + PKIX_CHECK(pkix_ForwardBuilderState_Create + (childTraversedCACerts, + state->buildConstants.maxFanout, + state->numDepth - 1, + canBeCached, + validityDate, + state->candidateCert, + childTraversedSubjNames, + state->trustChain, + state, + &childState, + plContext), + PKIX_FORWARDBUILDSTATECREATEFAILED); + + PKIX_DECREF(childTraversedSubjNames); + PKIX_DECREF(certSelParams); + childState->verifyNode = verifyNode; + verifyNode = NULL; + PKIX_DECREF(state); + state = childState; /* state->status == BUILD_INITIAL */ + childState = NULL; + continue; /* with while (!outOfOptions) */ + } + + if (state->status == BUILD_GETNEXTCERT) { + pkixTempErrorReceived = PKIX_FALSE; + PKIX_DECREF(state->candidateCert); + + /* + * If we were using a Cert from the callier-supplied partial + * chain, delete it and go to the certStores. + */ + if (state->usingHintCerts == PKIX_TRUE) { + PKIX_DECREF(state->candidateCerts); + PKIX_CHECK(PKIX_List_Create + (&state->candidateCerts, plContext), + PKIX_LISTCREATEFAILED); + + state->numCerts = 0; + state->usingHintCerts = PKIX_FALSE; + state->status = BUILD_TRYAIA; + continue; + } else if (++(state->certIndex) < (state->numCerts)) { + if ((state->buildConstants.maxFanout != 0) && + (--(state->numFanout) == 0)) { + + if (state->verifyNode != NULL) { + PKIX_ERROR_CREATE + (BUILD, + PKIX_FANOUTEXCEEDSRESOURCELIMITS, + verifyError); + PKIX_CHECK_FATAL + (pkix_VerifyNode_SetError + (state->verifyNode, + verifyError, + plContext), + PKIX_VERIFYNODESETERRORFAILED); + PKIX_DECREF(finalError); + finalError = verifyError; + verifyError = NULL; + } + /* Even if error logged, still need to abort */ + PKIX_ERROR + (PKIX_FANOUTEXCEEDSRESOURCELIMITS); + } + state->status = BUILD_CERTVALIDATING; + continue; + } + } + + /* + * Adding the current cert to the chain didn't help. If our search + * has been restricted to local certStores, try opening up the + * search and see whether that helps. Otherwise, back up to the + * parent cert, and see if there are any more to try. + */ + if (state->useOnlyLocal == PKIX_TRUE) { + pkix_PrepareForwardBuilderStateForAIA(state); + } else do { + if (state->parentState == NULL) { + /* We are at the top level, and can't back up! */ + outOfOptions = PKIX_TRUE; + } else { + /* + * Try the next cert, if any, for this parent. + * Otherwise keep backing up until we reach a + * parent with more certs to try. + */ + PKIX_CHECK(PKIX_List_GetLength + (state->trustChain, &numChained, plContext), + PKIX_LISTGETLENGTHFAILED); + PKIX_CHECK(PKIX_List_DeleteItem + (state->trustChain, numChained - 1, plContext), + PKIX_LISTDELETEITEMFAILED); + + /* local and aia fetching returned no good certs. + * Creating a verify node in the parent that tells + * us this. */ + if (!state->verifyNode) { + PKIX_CHECK_FATAL( + pkix_VerifyNode_Create(state->prevCert, + 0, NULL, + &state->verifyNode, + plContext), + PKIX_VERIFYNODECREATEFAILED); + } + /* Updating the log with the error. */ + PKIX_DECREF(verifyError); + PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER, + verifyError); + PKIX_CHECK_FATAL( + pkix_VerifyNode_SetError(state->verifyNode, + verifyError, + plContext), + PKIX_VERIFYNODESETERRORFAILED); + PKIX_DECREF(verifyError); + + PKIX_INCREF(state->parentState); + parentState = state->parentState; + PKIX_DECREF(verifyNode); + verifyNode = state->verifyNode; + state->verifyNode = NULL; + PKIX_DECREF(state); + state = parentState; + parentState = NULL; + if (state->verifyNode != NULL && verifyNode) { + PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree + (state->verifyNode, + verifyNode, + plContext), + PKIX_VERIFYNODEADDTOTREEFAILED); + PKIX_DECREF(verifyNode); + } + PKIX_DECREF(validityDate); + PKIX_INCREF(state->validityDate); + validityDate = state->validityDate; + canBeCached = state->canBeCached; + + /* Are there any more Certs to try? */ + if (++(state->certIndex) < (state->numCerts)) { + state->status = BUILD_CERTVALIDATING; + PKIX_DECREF(state->candidateCert); + break; + } + if (state->useOnlyLocal == PKIX_TRUE) { + /* Clean up and go for AIA round. */ + pkix_PrepareForwardBuilderStateForAIA(state); + break; + } + } + PKIX_DECREF(state->candidateCert); + } while (outOfOptions == PKIX_FALSE); + + } /* while (outOfOptions == PKIX_FALSE) */ + +cleanup: + + if (pkixErrorClass == PKIX_FATAL_ERROR) { + goto fatal; + } + + /* verifyNode should be equal to NULL at this point. Assert it. + * Temporarelly use verifyError to store an error ref to which we + * have in pkixErrorResult. This is done to prevent error cloberring + * while using macros below. */ + PORT_Assert(verifyError == NULL); + verifyError = pkixErrorResult; + + /* + * We were called with an initialState that had no parent. If we are + * returning with an error or with a result, we must destroy any state + * that we created (any state with a parent). + */ + + PKIX_CHECK_FATAL(pkix_ForwardBuilderState_IsIOPending + (state, &ioPending, plContext), + PKIX_FORWARDBUILDERSTATEISIOPENDINGFAILED); + + if (ioPending == PKIX_FALSE) { + while (state->parentState) { + PKIX_INCREF(state->parentState); + parentState = state->parentState; + PKIX_DECREF(verifyNode); + verifyNode = state->verifyNode; + state->verifyNode = NULL; + PKIX_DECREF(state); + state = parentState; + parentState = NULL; + if (state->verifyNode != NULL && verifyNode) { + PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree + (state->verifyNode, + verifyNode, + plContext), + PKIX_VERIFYNODEADDTOTREEFAILED); + PKIX_DECREF(verifyNode); + } + } + state->canBeCached = canBeCached; + PKIX_DECREF(state->validityDate); + state->validityDate = validityDate; + validityDate = NULL; + } + if (!*pValResult && !verifyError) { + if (!finalError) { + PKIX_CHECK_FATAL( + pkix_VerifyNode_FindError(state->verifyNode, + &finalError, + plContext), + PKIX_VERIFYNODEFINDERRORFAILED); + } + if (finalError) { + pkixErrorResult = finalError; + pkixErrorCode = PKIX_BUILDFORWARDDEPTHFIRSTSEARCHFAILED; + finalError = NULL; + goto fatal; + } + pkixErrorCode = PKIX_SECERRORUNKNOWNISSUER; + pkixErrorReceived = PKIX_TRUE; + PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER, + verifyError); + PKIX_CHECK_FATAL( + pkix_VerifyNode_SetError(state->verifyNode, verifyError, + plContext), + PKIX_VERIFYNODESETERRORFAILED); + } else { + pkixErrorResult = verifyError; + verifyError = NULL; + } + +fatal: + if (state->parentState) { + /* parentState in "state" object should be NULL at this point. + * If itn't, that means that we got fatal error(we have jumped to + * "fatal" label) and we should destroy all state except the top one. */ + while (state->parentState) { + PKIX_Error *error = NULL; + PKIX_ForwardBuilderState *prntState = state->parentState; + /* Dumb: need to increment parentState to avoid destruction + * of "build constants"(they get destroyed when parentState is + * set to NULL. */ + PKIX_INCREF(prntState); + error = PKIX_PL_Object_DecRef((PKIX_PL_Object*)state, plContext); + if (error) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext); + } + /* No need to decref the parent state. It was already done by + * pkix_ForwardBuilderState_Destroy function. */ + state = prntState; + } + } + PKIX_DECREF(parentState); + PKIX_DECREF(childState); + PKIX_DECREF(valResult); + PKIX_DECREF(verifyError); + PKIX_DECREF(finalError); + PKIX_DECREF(verifyNode); + PKIX_DECREF(childTraversedSubjNames); + PKIX_DECREF(certSelParams); + PKIX_DECREF(subjectNames); + PKIX_DECREF(subjectName); + PKIX_DECREF(trustAnchor); + PKIX_DECREF(validityDate); + PKIX_DECREF(revCheckerState); + PKIX_DECREF(currTime); + PKIX_DECREF(filteredCerts); + PKIX_DECREF(unfilteredCerts); + PKIX_DECREF(trustedCert); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_Build_CheckInCache + * DESCRIPTION: + * + * The function tries to locate a chain for a cert in the cert chain cache. + * If found, the chain goes through revocation chacking and returned back to + * caller. Chains that fail revocation check get removed from cache. + * + * PARAMETERS: + * "state" + * Address of ForwardBuilderState to be used. Must be non-NULL. + * "pBuildResult" + * Address at which the BuildResult is stored, after a successful build. + * Must be non-NULL. + * "pNBIOContext" + * Address at which the NBIOContext is stored indicating whether the + * validation is complete. 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 Build 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_Build_CheckInCache( + PKIX_ForwardBuilderState *state, + PKIX_BuildResult **pBuildResult, + void **pNBIOContext, + void *plContext) +{ + PKIX_PL_Cert *targetCert = NULL; + PKIX_List *anchors = NULL; + PKIX_PL_Date *testDate = NULL; + PKIX_BuildResult *buildResult = NULL; + PKIX_ValidateResult *valResult = NULL; + PKIX_Error *buildError = NULL; + PKIX_TrustAnchor *matchingAnchor = NULL; + PKIX_PL_Cert *trustedCert = NULL; + PKIX_List *certList = NULL; + PKIX_Boolean cacheHit = PKIX_FALSE; + PKIX_Boolean trusted = PKIX_FALSE; + PKIX_Boolean stillValid = PKIX_FALSE; + void *nbioContext = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_CheckInCache"); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + targetCert = state->buildConstants.targetCert; + anchors = state->buildConstants.anchors; + testDate = state->buildConstants.testDate; + + /* Check whether this cert verification has been cached. */ + PKIX_CHECK(pkix_CacheCertChain_Lookup + (targetCert, + anchors, + testDate, + &cacheHit, + &buildResult, + plContext), + PKIX_CACHECERTCHAINLOOKUPFAILED); + + if (!cacheHit) { + goto cleanup; + } + + /* + * We found something in cache. Verify that the anchor + * cert is still trusted, + */ + PKIX_CHECK(PKIX_BuildResult_GetValidateResult + (buildResult, &valResult, plContext), + PKIX_BUILDRESULTGETVALIDATERESULTFAILED); + + PKIX_CHECK(PKIX_ValidateResult_GetTrustAnchor + (valResult, &matchingAnchor, plContext), + PKIX_VALIDATERESULTGETTRUSTANCHORFAILED); + + PKIX_DECREF(valResult); + + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert + (matchingAnchor, &trustedCert, plContext), + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); + + if (anchors && state->buildConstants.numAnchors) { + /* Check if it is one of the trust anchors */ + PKIX_CHECK( + pkix_List_Contains(anchors, + (PKIX_PL_Object *)matchingAnchor, + &trusted, + plContext), + PKIX_LISTCONTAINSFAILED); + } + + if ((!trusted && !state->buildConstants.trustOnlyUserAnchors) || + !state->buildConstants.numAnchors) { + /* If it is not one of the trust anchors and the trust anchors + * are supplemental, or if there are no trust anchors, then check + * if the cert is trusted directly. + */ + PKIX_CHECK( + PKIX_PL_Cert_IsCertTrusted(trustedCert, + PKIX_PL_TrustAnchorMode_Ignore, + &trusted, plContext), + PKIX_CERTISCERTTRUSTEDFAILED); + } + + if (!trusted) { + goto cleanup; + } + /* + * Since the key usage may vary for different + * applications, we need to verify the chain again. + * Reverification will be improved with a fix for 397805. + */ + PKIX_CHECK(PKIX_BuildResult_GetCertChain + (buildResult, &certList, plContext), + PKIX_BUILDRESULTGETCERTCHAINFAILED); + + PKIX_CHECK(pkix_Build_ValidationCheckers + (state, + certList, + matchingAnchor, + PKIX_TRUE, /* Chain revalidation stage. */ + plContext), + PKIX_BUILDVALIDATIONCHECKERSFAILED); + + PKIX_CHECK_ONLY_FATAL( + pkix_Build_ValidateEntireChain(state, matchingAnchor, + &nbioContext, &valResult, + state->verifyNode, plContext), + PKIX_BUILDVALIDATEENTIRECHAINFAILED); + + if (nbioContext != NULL) { + /* IO still pending, resume later */ + *pNBIOContext = nbioContext; + goto cleanup; + } + if (!PKIX_ERROR_RECEIVED) { + /* The result from cache is still valid. But we replace an old*/ + *pBuildResult = buildResult; + buildResult = NULL; + stillValid = PKIX_TRUE; + } + +cleanup: + + if (!nbioContext && cacheHit && !(trusted && stillValid)) { + /* The anchor of this chain is no longer trusted or + * chain cert(s) has been revoked. + * Invalidate this result in the cache */ + buildError = pkixErrorResult; + PKIX_CHECK_FATAL(pkix_CacheCertChain_Remove + (targetCert, + anchors, + plContext), + PKIX_CACHECERTCHAINREMOVEFAILED); + pkixErrorResult = buildError; + buildError = NULL; + } + +fatal: + PKIX_DECREF(buildResult); + PKIX_DECREF(valResult); + PKIX_DECREF(buildError); + PKIX_DECREF(certList); + PKIX_DECREF(matchingAnchor); + PKIX_DECREF(trustedCert); + + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_Build_InitiateBuildChain + * DESCRIPTION: + * + * This function initiates the search for a BuildChain, using the parameters + * provided in "procParams" and, if continuing a search that was suspended + * for I/O, using the ForwardBuilderState pointed to by "pState". + * + * If a successful chain is built, this function stores the BuildResult at + * "pBuildResult". Alternatively, if an operation using non-blocking I/O + * is in progress and the operation has not been completed, this function + * stores the platform-dependent non-blocking I/O context (nbioContext) at + * "pNBIOContext", the FowardBuilderState at "pState", and NULL at + * "pBuildResult". Finally, if chain building was unsuccessful, this function + * stores NULL at both "pState" and at "pBuildResult". + * + * Note: This function is re-entered only for the case of non-blocking I/O + * in the "short-cut" attempt to build a chain using the target Certificate + * directly with one of the trustAnchors. For all other cases, resumption + * after non-blocking I/O is via pkix_Build_ResumeBuildChain. + * + * PARAMETERS: + * "procParams" + * Address of the ProcessingParams for the search. Must be non-NULL. + * "pNBIOContext" + * Address at which the NBIOContext is stored indicating whether the + * validation is complete. Must be non-NULL. + * "pState" + * Address at which the ForwardBuilderState is stored, if the chain + * building is suspended for waiting I/O; also, the address at which the + * ForwardBuilderState is provided for resumption of the chain building + * attempt. Must be non-NULL. + * "pBuildResult" + * Address at which the BuildResult is stored, after a successful build. + * Must be non-NULL. + * "pVerifyNode" + * Address at which a VerifyNode chain is returned, if 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 Build 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_Build_InitiateBuildChain( + PKIX_ProcessingParams *procParams, + void **pNBIOContext, + PKIX_ForwardBuilderState **pState, + PKIX_BuildResult **pBuildResult, + PKIX_VerifyNode **pVerifyNode, + void *plContext) +{ + PKIX_UInt32 numAnchors = 0; + PKIX_UInt32 numCertStores = 0; + PKIX_UInt32 numHintCerts = 0; + PKIX_UInt32 i = 0; + PKIX_Boolean isDuplicate = PKIX_FALSE; + PKIX_PL_Cert *trustedCert = NULL; + PKIX_CertSelector *targetConstraints = NULL; + PKIX_ComCertSelParams *targetParams = NULL; + PKIX_List *anchors = NULL; + PKIX_List *targetSubjNames = NULL; + PKIX_PL_Cert *targetCert = NULL; + PKIX_PL_Object *firstHintCert = NULL; + PKIX_RevocationChecker *revChecker = NULL; + PKIX_List *certStores = NULL; + PKIX_CertStore *certStore = NULL; + PKIX_List *userCheckers = NULL; + PKIX_List *hintCerts = NULL; + PKIX_PL_Date *testDate = NULL; + PKIX_PL_PublicKey *targetPubKey = NULL; + void *nbioContext = NULL; + BuildConstants buildConstants; + + PKIX_List *tentativeChain = NULL; + PKIX_ValidateResult *valResult = NULL; + PKIX_BuildResult *buildResult = NULL; + PKIX_List *certList = NULL; + PKIX_ForwardBuilderState *state = NULL; + PKIX_CertStore_CheckTrustCallback trustCallback = NULL; + PKIX_CertSelector_MatchCallback selectorCallback = NULL; + PKIX_Boolean trusted = PKIX_FALSE; + PKIX_PL_AIAMgr *aiaMgr = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_InitiateBuildChain"); + PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + state = *pState; + *pState = NULL; /* no net change in reference count */ + + if (state == NULL) { + PKIX_CHECK(PKIX_ProcessingParams_GetDate + (procParams, &testDate, plContext), + PKIX_PROCESSINGPARAMSGETDATEFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors + (procParams, &anchors, plContext), + PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED); + + PKIX_CHECK(PKIX_List_GetLength(anchors, &numAnchors, plContext), + PKIX_LISTGETLENGTHFAILED); + + /* retrieve stuff from targetCertConstraints */ + PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints + (procParams, &targetConstraints, plContext), + PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); + + PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams + (targetConstraints, &targetParams, plContext), + PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate + (targetParams, &targetCert, plContext), + PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED); + + PKIX_CHECK( + PKIX_ComCertSelParams_SetLeafCertFlag(targetParams, + PKIX_TRUE, plContext), + PKIX_COMCERTSELPARAMSSETLEAFCERTFLAGFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetHintCerts + (procParams, &hintCerts, plContext), + PKIX_PROCESSINGPARAMSGETHINTCERTSFAILED); + + if (hintCerts != NULL) { + PKIX_CHECK(PKIX_List_GetLength + (hintCerts, &numHintCerts, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + /* + * Caller must provide either a target Cert + * (in ComCertSelParams->Certificate) or a partial Cert + * chain (in ProcParams->HintCerts). + */ + + if (targetCert == NULL) { + + /* Use first cert of hintCerts as the targetCert */ + if (numHintCerts == 0) { + PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED); + } + + PKIX_CHECK(PKIX_List_GetItem + (hintCerts, + 0, + (PKIX_PL_Object **)&targetCert, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_DeleteItem(hintCerts, 0, plContext), + PKIX_LISTGETITEMFAILED); + } else { + + /* + * If the first hintCert is the same as the targetCert, + * delete it from hintCerts. + */ + if (numHintCerts != 0) { + PKIX_CHECK(PKIX_List_GetItem + (hintCerts, 0, &firstHintCert, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)targetCert, + firstHintCert, + &isDuplicate, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (isDuplicate) { + PKIX_CHECK(PKIX_List_DeleteItem + (hintCerts, 0, plContext), + PKIX_LISTGETITEMFAILED); + } + PKIX_DECREF(firstHintCert); + } + + } + + if (targetCert == NULL) { + PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED); + } + + PKIX_CHECK(PKIX_PL_Cert_IsLeafCertTrusted + (targetCert, + &trusted, + plContext), + PKIX_CERTISCERTTRUSTEDFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames + (targetCert, + &targetSubjNames, + plContext), + PKIX_CERTGETALLSUBJECTNAMESFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey + (targetCert, &targetPubKey, plContext), + PKIX_CERTGETSUBJECTPUBLICKEYFAILED); + + PKIX_CHECK(PKIX_List_Create(&tentativeChain, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (tentativeChain, (PKIX_PL_Object *)targetCert, plContext), + PKIX_LISTAPPENDITEMFAILED); + + if (procParams->qualifyTargetCert) { + /* EE cert validation */ + /* Sync up the time on the target selector parameter struct. */ + PKIX_CHECK( + PKIX_ComCertSelParams_SetCertificateValid(targetParams, + testDate, + plContext), + PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED); + + PKIX_CHECK(PKIX_CertSelector_GetMatchCallback + (targetConstraints, &selectorCallback, plContext), + PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); + + pkixErrorResult = + (*selectorCallback)(targetConstraints, targetCert, + plContext); + if (pkixErrorResult) { + pkixErrorClass = pkixErrorResult->errClass; + if (pkixErrorClass == PKIX_FATAL_ERROR) { + goto cleanup; + } + if (pVerifyNode != NULL) { + PKIX_Error *tempResult = + pkix_VerifyNode_Create(targetCert, 0, + pkixErrorResult, + pVerifyNode, + plContext); + if (tempResult) { + PKIX_DECREF(pkixErrorResult); + pkixErrorResult = tempResult; + pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; + } + } + pkixErrorCode = PKIX_CERTCHECKVALIDITYFAILED; + goto cleanup; + } + } + + /* If the EE cert is trusted, force success. We only want to do + * this if we aren't validating against a policy (like EV). */ + if (trusted && procParams->initialPolicies == NULL) { + if (pVerifyNode != NULL) { + PKIX_Error *tempResult = + pkix_VerifyNode_Create(targetCert, 0, NULL, + pVerifyNode, + plContext); + if (tempResult) { + pkixErrorResult = tempResult; + pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; + } + } + PKIX_CHECK(pkix_ValidateResult_Create + (targetPubKey, NULL /* anchor */, + NULL /* policyTree */, &valResult, plContext), + PKIX_VALIDATERESULTCREATEFAILED); + PKIX_CHECK( + pkix_BuildResult_Create(valResult, tentativeChain, + &buildResult, plContext), + PKIX_BUILDRESULTCREATEFAILED); + *pBuildResult = buildResult; + /* Note that *pState is NULL. The only side effect is that + * the cert chain won't be cached in PKIX_BuildChain, which + * is fine. */ + goto cleanup; + } + + PKIX_CHECK(PKIX_ProcessingParams_GetCertStores + (procParams, &certStores, plContext), + PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); + + PKIX_CHECK(PKIX_List_GetLength + (certStores, &numCertStores, plContext), + PKIX_LISTGETLENGTHFAILED); + + /* Reorder CertStores so trusted are at front of the List */ + if (numCertStores > 1) { + for (i = numCertStores - 1; i > 0; i--) { + PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem + (certStores, + i, + (PKIX_PL_Object **)&certStore, + plContext), + PKIX_LISTGETITEMFAILED); + PKIX_CHECK_ONLY_FATAL(PKIX_CertStore_GetTrustCallback + (certStore, &trustCallback, plContext), + PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); + + if (trustCallback != NULL) { + /* Is a trusted Cert, move CertStore to front */ + PKIX_CHECK(PKIX_List_DeleteItem + (certStores, i, plContext), + PKIX_LISTDELETEITEMFAILED); + PKIX_CHECK(PKIX_List_InsertItem + (certStores, + 0, + (PKIX_PL_Object *)certStore, + plContext), + PKIX_LISTINSERTITEMFAILED); + + } + + PKIX_DECREF(certStore); + } + } + + PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers + (procParams, &userCheckers, plContext), + PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker + (procParams, &revChecker, plContext), + PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); + /* Do not initialize AIA manager if we are not going to fetch + * cert using aia url. */ + if (procParams->useAIAForCertFetching) { + PKIX_CHECK(PKIX_PL_AIAMgr_Create(&aiaMgr, plContext), + PKIX_AIAMGRCREATEFAILED); + } + + /* + * We initialize all the fields of buildConstants here, in one place, + * just to help keep track and ensure that we got everything. + */ + + buildConstants.numAnchors = numAnchors; + buildConstants.numCertStores = numCertStores; + buildConstants.numHintCerts = numHintCerts; + buildConstants.procParams = procParams; + buildConstants.testDate = testDate; + buildConstants.timeLimit = NULL; + buildConstants.targetCert = targetCert; + buildConstants.targetPubKey = targetPubKey; + buildConstants.certStores = certStores; + buildConstants.anchors = anchors; + buildConstants.userCheckers = userCheckers; + buildConstants.hintCerts = hintCerts; + buildConstants.revChecker = revChecker; + buildConstants.aiaMgr = aiaMgr; + buildConstants.trustOnlyUserAnchors = + procParams->useOnlyTrustAnchors; + + PKIX_CHECK(pkix_Build_GetResourceLimits(&buildConstants, plContext), + PKIX_BUILDGETRESOURCELIMITSFAILED); + + PKIX_CHECK(pkix_ForwardBuilderState_Create + (0, /* PKIX_UInt32 traversedCACerts */ + buildConstants.maxFanout, + buildConstants.maxDepth, + PKIX_TRUE, /* PKIX_Boolean canBeCached */ + NULL, /* PKIX_Date *validityDate */ + targetCert, /* PKIX_PL_Cert *prevCert */ + targetSubjNames, /* PKIX_List *traversedSubjNames */ + tentativeChain, /* PKIX_List *trustChain */ + NULL, /* PKIX_ForwardBuilderState *parent */ + &state, /* PKIX_ForwardBuilderState **pState */ + plContext), + PKIX_BUILDSTATECREATEFAILED); + + state->buildConstants.numAnchors = buildConstants.numAnchors; + state->buildConstants.numCertStores = buildConstants.numCertStores; + state->buildConstants.numHintCerts = buildConstants.numHintCerts; + state->buildConstants.maxFanout = buildConstants.maxFanout; + state->buildConstants.maxDepth = buildConstants.maxDepth; + state->buildConstants.maxTime = buildConstants.maxTime; + state->buildConstants.procParams = buildConstants.procParams; + PKIX_INCREF(buildConstants.testDate); + state->buildConstants.testDate = buildConstants.testDate; + state->buildConstants.timeLimit = buildConstants.timeLimit; + PKIX_INCREF(buildConstants.targetCert); + state->buildConstants.targetCert = buildConstants.targetCert; + PKIX_INCREF(buildConstants.targetPubKey); + state->buildConstants.targetPubKey = + buildConstants.targetPubKey; + PKIX_INCREF(buildConstants.certStores); + state->buildConstants.certStores = buildConstants.certStores; + PKIX_INCREF(buildConstants.anchors); + state->buildConstants.anchors = buildConstants.anchors; + PKIX_INCREF(buildConstants.userCheckers); + state->buildConstants.userCheckers = + buildConstants.userCheckers; + PKIX_INCREF(buildConstants.hintCerts); + state->buildConstants.hintCerts = buildConstants.hintCerts; + PKIX_INCREF(buildConstants.revChecker); + state->buildConstants.revChecker = buildConstants.revChecker; + state->buildConstants.aiaMgr = buildConstants.aiaMgr; + aiaMgr = NULL; + state->buildConstants.trustOnlyUserAnchors = + buildConstants.trustOnlyUserAnchors; + + if (buildConstants.maxTime != 0) { + PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds + (buildConstants.maxTime, + &state->buildConstants.timeLimit, + plContext), + PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); + } + + if (pVerifyNode != NULL) { + PKIX_Error *tempResult = + pkix_VerifyNode_Create(targetCert, 0, NULL, + &(state->verifyNode), + plContext); + if (tempResult) { + pkixErrorResult = tempResult; + pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; + } + } + + PKIX_CHECK_ONLY_FATAL( + pkix_Build_CheckInCache(state, &buildResult, + &nbioContext, plContext), + PKIX_UNABLETOBUILDCHAIN); + if (nbioContext) { + *pNBIOContext = nbioContext; + *pState = state; + state = NULL; + goto cleanup; + } + if (buildResult) { + *pBuildResult = buildResult; + if (pVerifyNode != NULL) { + *pVerifyNode = state->verifyNode; + state->verifyNode = NULL; + } + goto cleanup; + } + } + + /* If we're resuming after non-blocking I/O we need to get SubjNames */ + if (targetSubjNames == NULL) { + PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames + (state->buildConstants.targetCert, + &targetSubjNames, + plContext), + PKIX_CERTGETALLSUBJECTNAMESFAILED); + } + + state->status = BUILD_INITIAL; + + pkixErrorResult = + pkix_BuildForwardDepthFirstSearch(&nbioContext, state, + &valResult, plContext); + + /* non-null nbioContext means the build would block */ + if (pkixErrorResult == NULL && nbioContext != NULL) { + + *pNBIOContext = nbioContext; + *pBuildResult = NULL; + + /* no valResult means the build has failed */ + } else { + if (pVerifyNode != NULL) { + PKIX_INCREF(state->verifyNode); + *pVerifyNode = state->verifyNode; + } + + if (valResult == NULL || pkixErrorResult) + PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); + PKIX_CHECK( + pkix_BuildResult_Create(valResult, state->trustChain, + &buildResult, plContext), + PKIX_BUILDRESULTCREATEFAILED); + *pBuildResult = buildResult; + } + + *pState = state; + state = NULL; + +cleanup: + + PKIX_DECREF(targetConstraints); + PKIX_DECREF(targetParams); + PKIX_DECREF(anchors); + PKIX_DECREF(targetSubjNames); + PKIX_DECREF(targetCert); + PKIX_DECREF(revChecker); + PKIX_DECREF(certStores); + PKIX_DECREF(certStore); + PKIX_DECREF(userCheckers); + PKIX_DECREF(hintCerts); + PKIX_DECREF(firstHintCert); + PKIX_DECREF(testDate); + PKIX_DECREF(targetPubKey); + PKIX_DECREF(tentativeChain); + PKIX_DECREF(valResult); + PKIX_DECREF(certList); + PKIX_DECREF(trustedCert); + PKIX_DECREF(state); + PKIX_DECREF(aiaMgr); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_Build_ResumeBuildChain + * DESCRIPTION: + * + * This function continues the search for a BuildChain, using the parameters + * provided in "procParams" and the ForwardBuilderState pointed to by "state". + * + * If a successful chain is built, this function stores the BuildResult at + * "pBuildResult". Alternatively, if an operation using non-blocking I/O + * is in progress and the operation has not been completed, this function + * stores the FowardBuilderState at "pState" and NULL at "pBuildResult". + * Finally, if chain building was unsuccessful, this function stores NULL + * at both "pState" and at "pBuildResult". + * + * PARAMETERS: + * "pNBIOContext" + * Address at which the NBIOContext is stored indicating whether the + * validation is complete. Must be non-NULL. + * "pState" + * Address at which the ForwardBuilderState is provided for resumption of + * the chain building attempt; also, the address at which the + * ForwardBuilderStateis stored, if the chain building is suspended for + * waiting I/O. Must be non-NULL. + * "pBuildResult" + * Address at which the BuildResult is stored, after a successful build. + * 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 Build 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_Build_ResumeBuildChain( + void **pNBIOContext, + PKIX_ForwardBuilderState *state, + PKIX_BuildResult **pBuildResult, + PKIX_VerifyNode **pVerifyNode, + void *plContext) +{ + PKIX_ValidateResult *valResult = NULL; + PKIX_BuildResult *buildResult = NULL; + void *nbioContext = NULL; + + PKIX_ENTER(BUILD, "pkix_Build_ResumeBuildChain"); + PKIX_NULLCHECK_TWO(state, pBuildResult); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + pkixErrorResult = + pkix_BuildForwardDepthFirstSearch(&nbioContext, state, + &valResult, plContext); + + /* non-null nbioContext means the build would block */ + if (pkixErrorResult == NULL && nbioContext != NULL) { + + *pNBIOContext = nbioContext; + *pBuildResult = NULL; + + /* no valResult means the build has failed */ + } else { + if (pVerifyNode != NULL) { + PKIX_INCREF(state->verifyNode); + *pVerifyNode = state->verifyNode; + } + + if (valResult == NULL || pkixErrorResult) + PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); + + PKIX_CHECK( + pkix_BuildResult_Create(valResult, state->trustChain, + &buildResult, plContext), + PKIX_BUILDRESULTCREATEFAILED); + *pBuildResult = buildResult; + } + +cleanup: + + PKIX_DECREF(valResult); + + PKIX_RETURN(BUILD); +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_BuildChain (see comments in pkix.h) + */ +PKIX_Error * +PKIX_BuildChain( + PKIX_ProcessingParams *procParams, + void **pNBIOContext, + void **pState, + PKIX_BuildResult **pBuildResult, + PKIX_VerifyNode **pVerifyNode, + void *plContext) +{ + PKIX_ForwardBuilderState *state = NULL; + PKIX_BuildResult *buildResult = NULL; + void *nbioContext = NULL; + + PKIX_ENTER(BUILD, "PKIX_BuildChain"); + PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + if (*pState == NULL) { + PKIX_CHECK(pkix_Build_InitiateBuildChain + (procParams, + &nbioContext, + &state, + &buildResult, + pVerifyNode, + plContext), + PKIX_BUILDINITIATEBUILDCHAINFAILED); + } else { + state = (PKIX_ForwardBuilderState *)(*pState); + *pState = NULL; /* no net change in reference count */ + if (state->status == BUILD_SHORTCUTPENDING) { + PKIX_CHECK(pkix_Build_InitiateBuildChain + (procParams, + &nbioContext, + &state, + &buildResult, + pVerifyNode, + plContext), + PKIX_BUILDINITIATEBUILDCHAINFAILED); + } else { + PKIX_CHECK(pkix_Build_ResumeBuildChain + (&nbioContext, + state, + &buildResult, + pVerifyNode, + plContext), + PKIX_BUILDINITIATEBUILDCHAINFAILED); + } + } + + /* non-null nbioContext means the build would block */ + if (nbioContext != NULL) { + + *pNBIOContext = nbioContext; + *pState = state; + state = NULL; + *pBuildResult = NULL; + + /* no buildResult means the build has failed */ + } else if (buildResult == NULL) { + PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); + } else { + /* + * If we made a successful chain by combining the target Cert + * with one of the Trust Anchors, we may have never created a + * validityDate. We treat this situation as + * canBeCached = PKIX_FALSE. + */ + if ((state != NULL) && + ((state->validityDate) != NULL) && + (state->canBeCached)) { + PKIX_CHECK(pkix_CacheCertChain_Add + (state->buildConstants.targetCert, + state->buildConstants.anchors, + state->validityDate, + buildResult, + plContext), + PKIX_CACHECERTCHAINADDFAILED); + } + + *pState = NULL; + *pBuildResult = buildResult; + buildResult = NULL; + } + +cleanup: + PKIX_DECREF(buildResult); + PKIX_DECREF(state); + + PKIX_RETURN(BUILD); +} diff --git a/security/nss/lib/libpkix/pkix/top/pkix_build.h b/security/nss/lib/libpkix/pkix/top/pkix_build.h new file mode 100644 index 0000000000..eeba9239d8 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/pkix_build.h @@ -0,0 +1,120 @@ +/* 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_build.h + * + * Header file for buildChain function + * + */ + +#ifndef _PKIX_BUILD_H +#define _PKIX_BUILD_H +#include "pkix_tools.h" +#ifndef NSS_PKIX_NO_LDAP +#include "pkix_pl_ldapt.h" +#endif +#include "pkix_ekuchecker.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BUILD_SHORTCUTPENDING, + BUILD_INITIAL, + BUILD_TRYAIA, + BUILD_AIAPENDING, + BUILD_COLLECTINGCERTS, + BUILD_GATHERPENDING, + BUILD_CERTVALIDATING, + BUILD_ABANDONNODE, + BUILD_DATEPREP, + BUILD_CHECKTRUSTED, + BUILD_CHECKTRUSTED2, + BUILD_ADDTOCHAIN, + BUILD_VALCHAIN, + BUILD_VALCHAIN2, + BUILD_EXTENDCHAIN, + BUILD_GETNEXTCERT +} BuildStatus; + +typedef struct BuildConstantsStruct BuildConstants; + +/* + * These fields (the ones that are objects) are not reference-counted + * in *each* state, but only in the root, the state that has no parent. + * That saves time in creation and destruction of child states, but is + * safe enough since they are constants. + */ +struct BuildConstantsStruct { + PKIX_UInt32 numAnchors; + PKIX_UInt32 numCertStores; + PKIX_UInt32 numHintCerts; + PKIX_UInt32 maxDepth; + PKIX_UInt32 maxFanout; + PKIX_UInt32 maxTime; + PKIX_ProcessingParams *procParams; + PKIX_PL_Date *testDate; + PKIX_PL_Date *timeLimit; + PKIX_PL_Cert *targetCert; + PKIX_PL_PublicKey *targetPubKey; + PKIX_List *certStores; + PKIX_List *anchors; + PKIX_List *userCheckers; + PKIX_List *hintCerts; + PKIX_RevocationChecker *revChecker; + PKIX_PL_AIAMgr *aiaMgr; + PKIX_Boolean useAIAForCertFetching; + PKIX_Boolean trustOnlyUserAnchors; +}; + +struct PKIX_ForwardBuilderStateStruct{ + BuildStatus status; + PKIX_Int32 traversedCACerts; + PKIX_UInt32 certStoreIndex; + PKIX_UInt32 numCerts; + PKIX_UInt32 numAias; + PKIX_UInt32 certIndex; + PKIX_UInt32 aiaIndex; + PKIX_UInt32 certCheckedIndex; + PKIX_UInt32 checkerIndex; + PKIX_UInt32 hintCertIndex; + PKIX_UInt32 numFanout; + PKIX_UInt32 numDepth; + PKIX_UInt32 reasonCode; + PKIX_Boolean canBeCached; + PKIX_Boolean useOnlyLocal; + PKIX_Boolean revChecking; + PKIX_Boolean usingHintCerts; + PKIX_Boolean certLoopingDetected; + PKIX_PL_Date *validityDate; + PKIX_PL_Cert *prevCert; + PKIX_PL_Cert *candidateCert; + PKIX_List *traversedSubjNames; + PKIX_List *trustChain; + PKIX_List *aia; + PKIX_List *candidateCerts; + PKIX_List *reversedCertChain; + PKIX_List *checkedCritExtOIDs; + PKIX_List *checkerChain; + PKIX_CertSelector *certSel; + PKIX_VerifyNode *verifyNode; + void *client; /* messageHandler, such as LDAPClient */ + PKIX_ForwardBuilderState *parentState; + BuildConstants buildConstants; +}; + +/* --Private-Functions-------------------------------------------- */ + +PKIX_Error * +pkix_ForwardBuilderState_RegisterSelf(void *plContext); + +PKIX_Error * +PKIX_Build_GetNBIOContext(void *state, void **pNBIOContext, void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_BUILD_H */ diff --git a/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c new file mode 100644 index 0000000000..aad0e1aaf3 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c @@ -0,0 +1,210 @@ +/* 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_lifecycle.c + * + * Top level initialize and shutdown functions + * + */ + +#include "pkix_lifecycle.h" + +static PKIX_Boolean pkixIsInitialized; + +/* Lock used by Logger - is reentrant by the same thread */ +extern PKIX_PL_MonitorLock *pkixLoggerLock; + +/* + * Following pkix_* variables are for debugging purpose. They should be taken + * out eventually. The purpose is to verify cache tables usage (via debugger). + */ +int pkix_ccAddCount = 0; +int pkix_ccLookupCount = 0; +int pkix_ccRemoveCount = 0; +int pkix_cAddCount = 0; +int pkix_cLookupCount = 0; +int pkix_cRemoveCount = 0; +int pkix_ceAddCount = 0; +int pkix_ceLookupCount = 0; + +PKIX_PL_HashTable *cachedCrlSigTable = NULL; +PKIX_PL_HashTable *cachedCertSigTable = NULL; +PKIX_PL_HashTable *cachedCertChainTable = NULL; +PKIX_PL_HashTable *cachedCertTable = NULL; +PKIX_PL_HashTable *cachedCrlEntryTable = NULL; +PKIX_PL_HashTable *aiaConnectionCache = NULL; +PKIX_PL_HashTable *httpSocketCache = NULL; + +extern PKIX_List *pkixLoggers; +extern PKIX_List *pkixLoggersErrors; +extern PKIX_List *pkixLoggersDebugTrace; + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_Initialize (see comments in pkix.h) + */ +PKIX_Error * +PKIX_Initialize( + PKIX_Boolean platformInitNeeded, + PKIX_UInt32 desiredMajorVersion, + PKIX_UInt32 minDesiredMinorVersion, + PKIX_UInt32 maxDesiredMinorVersion, + PKIX_UInt32 *pActualMinorVersion, + void **pPlContext) +{ + void *plContext = NULL; + + PKIX_ENTER(LIFECYCLE, "PKIX_Initialize"); + PKIX_NULLCHECK_ONE(pPlContext); + + /* + * If we are called a second time other than in the situation handled + * above, we return a positive status. + */ + if (pkixIsInitialized){ + /* Already initialized */ + PKIX_RETURN(LIFECYCLE); + } + + PKIX_CHECK(PKIX_PL_Initialize + (platformInitNeeded, PKIX_FALSE, &plContext), + PKIX_INITIALIZEFAILED); + + *pPlContext = plContext; + + if (desiredMajorVersion != PKIX_MAJOR_VERSION){ + PKIX_ERROR(PKIX_MAJORVERSIONSDONTMATCH); + } + + if ((minDesiredMinorVersion > PKIX_MINOR_VERSION) || + (maxDesiredMinorVersion < PKIX_MINOR_VERSION)){ + PKIX_ERROR(PKIX_MINORVERSIONNOTBETWEENDESIREDMINANDMAX); + } + + *pActualMinorVersion = PKIX_MINOR_VERSION; + + /* Create Cache Tables + * Do not initialize hash tables for object leak test */ +#if !defined(PKIX_OBJECT_LEAK_TEST) + PKIX_CHECK(PKIX_PL_HashTable_Create + (32, 0, &cachedCertSigTable, plContext), + PKIX_HASHTABLECREATEFAILED); + + PKIX_CHECK(PKIX_PL_HashTable_Create + (32, 0, &cachedCrlSigTable, plContext), + PKIX_HASHTABLECREATEFAILED); + + PKIX_CHECK(PKIX_PL_HashTable_Create + (32, 10, &cachedCertChainTable, plContext), + PKIX_HASHTABLECREATEFAILED); + + PKIX_CHECK(PKIX_PL_HashTable_Create + (32, 10, &cachedCertTable, plContext), + PKIX_HASHTABLECREATEFAILED); + + PKIX_CHECK(PKIX_PL_HashTable_Create + (32, 10, &cachedCrlEntryTable, plContext), + PKIX_HASHTABLECREATEFAILED); + + PKIX_CHECK(PKIX_PL_HashTable_Create + (5, 5, &aiaConnectionCache, plContext), + PKIX_HASHTABLECREATEFAILED); + +#ifdef PKIX_SOCKETCACHE + PKIX_CHECK(PKIX_PL_HashTable_Create + (5, 5, &httpSocketCache, plContext), + PKIX_HASHTABLECREATEFAILED); +#endif + if (pkixLoggerLock == NULL) { + PKIX_CHECK(PKIX_PL_MonitorLock_Create + (&pkixLoggerLock, plContext), + PKIX_MONITORLOCKCREATEFAILED); + } +#else + fnInvTable = PL_NewHashTable(0, pkix_ErrorGen_Hash, + PL_CompareValues, + PL_CompareValues, NULL, NULL); + if (!fnInvTable) { + PKIX_ERROR(PKIX_HASHTABLECREATEFAILED); + } + + fnStackNameArr = PORT_ZNewArray(char*, MAX_STACK_DEPTH); + if (!fnStackNameArr) { + PKIX_ERROR(PKIX_HASHTABLECREATEFAILED); + } + + fnStackInvCountArr = PORT_ZNewArray(PKIX_UInt32, MAX_STACK_DEPTH); + if (!fnStackInvCountArr) { + PKIX_ERROR(PKIX_HASHTABLECREATEFAILED); + } +#endif /* PKIX_OBJECT_LEAK_TEST */ + + pkixIsInitialized = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(LIFECYCLE); +} + +/* + * FUNCTION: PKIX_Shutdown (see comments in pkix.h) + */ +PKIX_Error * +PKIX_Shutdown(void *plContext) +{ + PKIX_List *savedPkixLoggers = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + + PKIX_ENTER(LIFECYCLE, "PKIX_Shutdown"); + + if (!pkixIsInitialized){ + /* The library was not initialized */ + PKIX_RETURN(LIFECYCLE); + } + + pkixIsInitialized = PKIX_FALSE; + + if (pkixLoggers) { + savedPkixLoggers = pkixLoggers; + savedPkixLoggersErrors = pkixLoggersErrors; + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggers = NULL; + pkixLoggersErrors = NULL; + pkixLoggersDebugTrace = NULL; + PKIX_DECREF(savedPkixLoggers); + PKIX_DECREF(savedPkixLoggersErrors); + PKIX_DECREF(savedPkixLoggersDebugTrace); + } + PKIX_DECREF(pkixLoggerLock); + + /* Destroy Cache Tables */ + PKIX_DECREF(cachedCertSigTable); + PKIX_DECREF(cachedCrlSigTable); + PKIX_DECREF(cachedCertChainTable); + PKIX_DECREF(cachedCertTable); + PKIX_DECREF(cachedCrlEntryTable); + PKIX_DECREF(aiaConnectionCache); + PKIX_DECREF(httpSocketCache); + + /* Clean up any temporary errors that happened during shutdown */ + if (pkixErrorList) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorList, plContext); + pkixErrorList = NULL; + } + + PKIX_CHECK(PKIX_PL_Shutdown(plContext), + PKIX_SHUTDOWNFAILED); + +#ifdef PKIX_OBJECT_LEAK_TEST + PORT_Free(fnStackInvCountArr); + PORT_Free(fnStackNameArr); + PL_HashTableDestroy(fnInvTable); +#endif + +cleanup: + + PKIX_RETURN(LIFECYCLE); +} diff --git a/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h new file mode 100644 index 0000000000..02631229cb --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h @@ -0,0 +1,23 @@ +/* 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_lifecycle.h + * + * Header file for initialize and shutdown functions. + * + */ + +#ifndef _PKIX_LIFECYCLE_H +#define _PKIX_LIFECYCLE_H +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_LIFECYCLE_H */ diff --git a/security/nss/lib/libpkix/pkix/top/pkix_validate.c b/security/nss/lib/libpkix/pkix/top/pkix_validate.c new file mode 100644 index 0000000000..1e5dec795a --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.c @@ -0,0 +1,1451 @@ +/* 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_validate.c + * + * Top level validateChain function + * + */ + +#include "pkix_validate.h" +#include "pkix_pl_common.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_AddToVerifyLog + * DESCRIPTION: + * + * This function returns immediately if the address for the VerifyNode tree + * pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode + * from the Cert pointed to by "cert" and the Error pointed to by "error", + * and inserts it at the depth in the VerifyNode tree determined by "depth". A + * depth of zero means that this function creates the root node of a new tree. + * + * Note: this function does not include the means of choosing among branches + * of a tree. It is intended for non-branching trees, that is, where each + * parent node has only a single child node. + * + * PARAMETERS: + * "cert" + * The address of the Cert to be included in the new VerifyNode. Must be + * non-NULL. + * "depth" + * The UInt32 value of the depth. + * "error" + * The address of the Error to be included in the new VerifyNode. + * "pVerifyTree" + * The address of the VerifyNode tree into which the created VerifyNode + * is to be inserted. The node is not created if VerifyTree is 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 Validate 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_AddToVerifyLog( + PKIX_PL_Cert *cert, + PKIX_UInt32 depth, + PKIX_Error *error, + PKIX_VerifyNode **pVerifyTree, + void *plContext) +{ + + PKIX_VerifyNode *verifyNode = NULL; + + PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog"); + PKIX_NULLCHECK_ONE(cert); + + if (pVerifyTree) { /* nothing to do if no address given for log */ + + PKIX_CHECK(pkix_VerifyNode_Create + (cert, depth, error, &verifyNode, plContext), + PKIX_VERIFYNODECREATEFAILED); + + if (depth == 0) { + /* We just created the root node */ + *pVerifyTree = verifyNode; + } else { + PKIX_CHECK(pkix_VerifyNode_AddToChain + (*pVerifyTree, verifyNode, plContext), + PKIX_VERIFYNODEADDTOCHAINFAILED); + } + } + +cleanup: + + PKIX_RETURN(VALIDATE); + +} + +/* + * FUNCTION: pkix_CheckCert + * DESCRIPTION: + * + * Checks whether the Cert pointed to by "cert" successfully validates + * using the List of CertChainCheckers pointed to by "checkers". If the + * certificate does not validate, an Error pointer is returned. + * + * This function should be called initially with the UInt32 pointed to by + * "pCheckerIndex" containing zero, and the pointer at "pNBIOContext" + * containing NULL. If a checker does non-blocking I/O, this function will + * return with the index of that checker stored at "pCheckerIndex" and a + * platform-dependent non-blocking I/O context stored at "pNBIOContext". + * A subsequent call to this function with those values intact will allow the + * checking to resume where it left off. This should be repeated until the + * function returns with NULL stored at "pNBIOContext". + * + * PARAMETERS: + * "cert" + * Address of Cert to validate. Must be non-NULL. + * "checkers" + * List of CertChainCheckers which must each validate the certificate. + * Must be non-NULL. + * "checkedExtOIDs" + * List of PKIX_PL_OID that has been processed. If called from building + * chain, it is the list of critical extension OIDs that has been + * processed prior to validation. May be NULL. + * "pCheckerIndex" + * Address at which is stored the the index, within the List "checkers", + * of a checker whose processing was interrupted by non-blocking I/O. + * Must be non-NULL. + * "pNBIOContext" + * Address at which is stored platform-specific non-blocking I/O context. + * 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 Validate 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_CheckCert( + PKIX_PL_Cert *cert, + PKIX_List *checkers, + PKIX_List *checkedExtOIDsList, + PKIX_UInt32 *pCheckerIndex, + void **pNBIOContext, + void *plContext) +{ + PKIX_CertChainChecker_CheckCallback checkerCheck = NULL; + PKIX_CertChainChecker *checker = NULL; + PKIX_List *unresCritExtOIDs = NULL; + PKIX_UInt32 numCheckers; + PKIX_UInt32 numUnresCritExtOIDs = 0; + PKIX_UInt32 checkerIndex = 0; + void *nbioContext = NULL; + + PKIX_ENTER(VALIDATE, "pkix_CheckCert"); + PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; /* prepare for case of error exit */ + + PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs + (cert, &unresCritExtOIDs, plContext), + PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); + + PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (checkerIndex = *pCheckerIndex; + checkerIndex < numCheckers; + checkerIndex++) { + + PKIX_CHECK(PKIX_List_GetItem + (checkers, + checkerIndex, + (PKIX_PL_Object **)&checker, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback + (checker, &checkerCheck, plContext), + PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED); + + PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs, + &nbioContext, plContext), + PKIX_CERTCHAINCHECKERCHECKFAILED); + + if (nbioContext != NULL) { + *pCheckerIndex = checkerIndex; + *pNBIOContext = nbioContext; + goto cleanup; + } + + PKIX_DECREF(checker); + } + + if (unresCritExtOIDs){ + +#ifdef PKIX_VALIDATEDEBUG + { + PKIX_PL_String *oidString = NULL; + PKIX_UInt32 length; + char *oidAscii = NULL; + PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext, + PKIX_LISTTOSTRINGFAILED); + PKIX_CHECK(PKIX_PL_String_GetEncoded + (oidString, + PKIX_ESCASCII, + (void **) &oidAscii, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + PKIX_VALIDATE_DEBUG_ARG + ("unrecognized critical extension OIDs:" + " %s\n", oidAscii); + PKIX_DECREF(oidString); + PKIX_PL_Free(oidAscii, plContext); + } +#endif + + if (checkedExtOIDsList != NULL) { + /* Take out OID's that had been processed, if any */ + PKIX_CHECK(pkix_List_RemoveItems + (unresCritExtOIDs, + checkedExtOIDsList, + plContext), + PKIX_LISTREMOVEITEMSFAILED); + } + + PKIX_CHECK(PKIX_List_GetLength + (unresCritExtOIDs, &numUnresCritExtOIDs, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numUnresCritExtOIDs != 0){ + PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION); + } + + } + +cleanup: + + PKIX_DECREF(checker); + PKIX_DECREF(unresCritExtOIDs); + + PKIX_RETURN(VALIDATE); + +} + +/* + * FUNCTION: pkix_InitializeCheckers + * DESCRIPTION: + * + * Creates several checkers and initializes them with values derived from the + * TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by + * "procParams", and the number of Certs in the Chain, represented by + * "numCerts". The List of checkers is stored at "pCheckers". + * + * PARAMETERS: + * "anchor" + * Address of TrustAnchor used to initialize the SignatureChecker and + * NameChainingChecker. Must be non-NULL. + * "procParams" + * Address of ProcessingParams used to initialize the ExpirationChecker + * and TargetCertChecker. Must be non-NULL. + * "numCerts" + * Number of certificates in the CertChain. + * "pCheckers" + * 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 Validate 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_InitializeCheckers( + PKIX_TrustAnchor *anchor, + PKIX_ProcessingParams *procParams, + PKIX_UInt32 numCerts, + PKIX_List **pCheckers, + void *plContext) +{ + PKIX_CertChainChecker *targetCertChecker = NULL; + PKIX_CertChainChecker *expirationChecker = NULL; + PKIX_CertChainChecker *nameChainingChecker = NULL; + PKIX_CertChainChecker *nameConstraintsChecker = NULL; + PKIX_CertChainChecker *basicConstraintsChecker = NULL; + PKIX_CertChainChecker *policyChecker = NULL; + PKIX_CertChainChecker *sigChecker = NULL; + PKIX_CertChainChecker *defaultCrlChecker = NULL; + PKIX_CertChainChecker *userChecker = NULL; + PKIX_PL_X500Name *trustedCAName = NULL; + PKIX_PL_PublicKey *trustedPubKey = NULL; + PKIX_List *checkers = NULL; + PKIX_PL_Date *testDate = NULL; + PKIX_CertSelector *certSelector = NULL; + PKIX_PL_Cert *trustedCert = NULL; + PKIX_PL_CertNameConstraints *trustedNC = NULL; + PKIX_List *initialPolicies = NULL; + PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; + PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; + PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; + PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; + PKIX_List *userCheckersList = NULL; + PKIX_List *certStores = NULL; + PKIX_UInt32 numCertCheckers = 0; + PKIX_UInt32 i; + + PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers"); + PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers); + PKIX_CHECK(PKIX_List_Create(&checkers, plContext), + PKIX_LISTCREATEFAILED); + + /* + * The TrustAnchor may have been created using CreateWithCert + * (in which case GetCAPublicKey and GetCAName will return NULL) + * or may have been created using CreateWithNameKeyPair (in which + * case GetTrustedCert will return NULL. So we call GetTrustedCert + * and populate trustedPubKey and trustedCAName accordingly. + */ + + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert + (anchor, &trustedCert, plContext), + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); + + if (trustedCert){ + PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey + (trustedCert, &trustedPubKey, plContext), + PKIX_CERTGETSUBJECTPUBLICKEYFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetSubject + (trustedCert, &trustedCAName, plContext), + PKIX_CERTGETSUBJECTFAILED); + } else { + PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey + (anchor, &trustedPubKey, plContext), + PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED); + + PKIX_CHECK(PKIX_TrustAnchor_GetCAName + (anchor, &trustedCAName, plContext), + PKIX_TRUSTANCHORGETCANAMEFAILED); + } + + PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName); + + PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints + (anchor, &trustedNC, plContext), + PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints + (procParams, &certSelector, plContext), + PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetDate + (procParams, &testDate, plContext), + PKIX_PROCESSINGPARAMSGETDATEFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies + (procParams, &initialPolicies, plContext), + PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected + (procParams, &policyQualifiersRejected, plContext), + PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited + (procParams, &initialPolicyMappingInhibit, plContext), + PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited + (procParams, &initialAnyPolicyInhibit, plContext), + PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired + (procParams, &initialExplicitPolicy, plContext), + PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetCertStores + (procParams, &certStores, plContext), + PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers + (procParams, &userCheckersList, plContext), + PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); + + /* now, initialize all the checkers */ + PKIX_CHECK(pkix_TargetCertChecker_Initialize + (certSelector, numCerts, &targetCertChecker, plContext), + PKIX_TARGETCERTCHECKERINITIALIZEFAILED); + + PKIX_CHECK(pkix_ExpirationChecker_Initialize + (testDate, &expirationChecker, plContext), + PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); + + PKIX_CHECK(pkix_NameChainingChecker_Initialize + (trustedCAName, &nameChainingChecker, plContext), + PKIX_NAMECHAININGCHECKERINITIALIZEFAILED); + + PKIX_CHECK(pkix_NameConstraintsChecker_Initialize + (trustedNC, numCerts, &nameConstraintsChecker, plContext), + PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED); + + PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize + (numCerts, &basicConstraintsChecker, plContext), + PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED); + + PKIX_CHECK(pkix_PolicyChecker_Initialize + (initialPolicies, + policyQualifiersRejected, + initialPolicyMappingInhibit, + initialExplicitPolicy, + initialAnyPolicyInhibit, + numCerts, + &policyChecker, + plContext), + PKIX_POLICYCHECKERINITIALIZEFAILED); + + PKIX_CHECK(pkix_SignatureChecker_Initialize + (trustedPubKey, numCerts, &sigChecker, plContext), + PKIX_SIGNATURECHECKERINITIALIZEFAILED); + + if (userCheckersList != NULL) { + + PKIX_CHECK(PKIX_List_GetLength + (userCheckersList, &numCertCheckers, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numCertCheckers; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (userCheckersList, + i, + (PKIX_PL_Object **) &userChecker, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, + (PKIX_PL_Object *)userChecker, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(userChecker); + } + } + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)targetCertChecker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)expirationChecker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)policyChecker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, (PKIX_PL_Object *)sigChecker, plContext), + PKIX_LISTAPPENDITEMFAILED); + + *pCheckers = checkers; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(checkers); + } + + PKIX_DECREF(certSelector); + PKIX_DECREF(testDate); + PKIX_DECREF(initialPolicies); + PKIX_DECREF(targetCertChecker); + PKIX_DECREF(expirationChecker); + PKIX_DECREF(nameChainingChecker); + PKIX_DECREF(nameConstraintsChecker); + PKIX_DECREF(basicConstraintsChecker); + PKIX_DECREF(policyChecker); + PKIX_DECREF(sigChecker); + PKIX_DECREF(trustedCAName); + PKIX_DECREF(trustedPubKey); + PKIX_DECREF(trustedNC); + PKIX_DECREF(trustedCert); + PKIX_DECREF(defaultCrlChecker); + PKIX_DECREF(userCheckersList); + PKIX_DECREF(certStores); + PKIX_DECREF(userChecker); + + PKIX_RETURN(VALIDATE); +} + +/* + * FUNCTION: pkix_RetrieveOutputs + * DESCRIPTION: + * + * This function queries the respective states of the List of checkers in + * "checkers" to to obtain the final public key from the SignatureChecker + * and the policy tree from the PolicyChecker, storing those values at + * "pFinalSubjPubKey" and "pPolicyTree", respectively. + * + * PARAMETERS: + * "checkers" + * Address of List of checkers to be queried. Must be non-NULL. + * "pFinalSubjPubKey" + * Address where final public key will be stored. Must be non-NULL. + * "pPolicyTree" + * Address where policy tree 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 Validate 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_RetrieveOutputs( + PKIX_List *checkers, + PKIX_PL_PublicKey **pFinalSubjPubKey, + PKIX_PolicyNode **pPolicyTree, + void *plContext) +{ + PKIX_PL_PublicKey *finalSubjPubKey = NULL; + PKIX_PolicyNode *validPolicyTree = NULL; + PKIX_CertChainChecker *checker = NULL; + PKIX_PL_Object *state = NULL; + PKIX_UInt32 numCheckers = 0; + PKIX_UInt32 type; + PKIX_Int32 j; + + PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs"); + + PKIX_NULLCHECK_TWO(checkers, pPolicyTree); + + /* + * To optimize the search, we guess that the sigChecker is + * last in the tree and is preceded by the policyChecker. We + * search toward the front of the chain. Remember that List + * items are indexed 0..(numItems - 1). + */ + + PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (j = numCheckers - 1; j >= 0; j--){ + PKIX_CHECK(PKIX_List_GetItem + (checkers, j, (PKIX_PL_Object **)&checker, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState + (checker, &state, plContext), + PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); + + /* user defined checker may have no state */ + if (state != NULL) { + + PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext), + PKIX_OBJECTGETTYPEFAILED); + + if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){ + /* final pubKey will include any inherited DSA params */ + finalSubjPubKey = + ((pkix_SignatureCheckerState *)state)-> + prevPublicKey; + PKIX_INCREF(finalSubjPubKey); + *pFinalSubjPubKey = finalSubjPubKey; + } + + if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) { + validPolicyTree = + ((PKIX_PolicyCheckerState *)state)->validPolicyTree; + break; + } + } + + PKIX_DECREF(checker); + PKIX_DECREF(state); + } + + PKIX_INCREF(validPolicyTree); + *pPolicyTree = validPolicyTree; + +cleanup: + + PKIX_DECREF(checker); + PKIX_DECREF(state); + + PKIX_RETURN(VALIDATE); + +} + +/* + * FUNCTION: pkix_CheckChain + * DESCRIPTION: + * + * Checks whether the List of Certs pointed to by "certs", containing + * "numCerts" entries, successfully validates using each CertChainChecker in + * the List pointed to by "checkers" and has not been revoked, according to any + * of the Revocation Checkers in the List pointed to by "revChecker". Checkers + * are expected to remove from "removeCheckedExtOIDs" and extensions that they + * process. Indices to the certChain and the checkerChain are obtained and + * returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These + * should be set to zero prior to the initial call, but may be changed (and + * must be supplied on subsequent calls) if processing is suspended for non- + * blocking I/O. Each time a Cert passes from being validated by one of the + * CertChainCheckers to being checked by a Revocation Checker, the Boolean + * stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is + * rejected by a Revocation Checker, its reason code is returned at + * "pReasonCode. If the List of Certs successfully validates, the public key i + * the final certificate is obtained and stored at "pFinalSubjPubKey" and the + * validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List + * of Certs fails to validate, an Error pointer is returned. + * + * If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which + * tracks the results of the validation. That is, either each node in the + * chain has a NULL Error component, or the last node contains an Error + * which indicates why the validation failed. + * + * The number of Certs in the List, represented by "numCerts", is used to + * determine which Cert is the final Cert. + * + * PARAMETERS: + * "certs" + * Address of List of Certs to validate. Must be non-NULL. + * "numCerts" + * Number of certificates in the List of certificates. + * "checkers" + * List of CertChainCheckers which must each validate the List of + * certificates. Must be non-NULL. + * "revChecker" + * List of RevocationCheckers which must each not reject the List of + * certificates. May be empty, but must be non-NULL. + * "removeCheckedExtOIDs" + * List of PKIX_PL_OID that has been processed. If called from building + * chain, it is the list of critical extension OIDs that has been + * processed prior to validation. Extension OIDs that may be processed by + * user defined checker processes are also in the list. May be NULL. + * "procParams" + * Address of ProcessingParams used to initialize various checkers. Must + * be non-NULL. + * "pCertCheckedIndex" + * Address where Int32 index to the Cert chain is obtained and + * returned. Must be non-NULL. + * "pCheckerIndex" + * Address where Int32 index to the CheckerChain is obtained and + * returned. Must be non-NULL. + * "pRevChecking" + * Address where Boolean is obtained and returned, indicating, if FALSE, + * that CertChainCheckers are being called; or, if TRUE, that RevChecker + * are being called. Must be non-NULL. + * "pReasonCode" + * Address where UInt32 results of revocation checking are stored. Must be + * non-NULL. + * "pNBIOContext" + * Address where platform-dependent context is stored if checking is + * suspended for non-blocking I/O. Must be non-NULL. + * "pFinalSubjPubKey" + * Address where the final public key will be stored. Must be non-NULL. + * "pPolicyTree" + * Address where the final validPolicyTree is stored. Must be non-NULL. + * "pVerifyTree" + * Address where a VerifyTree is stored, if 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 Validate 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_CheckChain( + PKIX_List *certs, + PKIX_UInt32 numCerts, + PKIX_TrustAnchor *anchor, + PKIX_List *checkers, + PKIX_RevocationChecker *revChecker, + PKIX_List *removeCheckedExtOIDs, + PKIX_ProcessingParams *procParams, + PKIX_UInt32 *pCertCheckedIndex, + PKIX_UInt32 *pCheckerIndex, + PKIX_Boolean *pRevChecking, + PKIX_UInt32 *pReasonCode, + void **pNBIOContext, + PKIX_PL_PublicKey **pFinalSubjPubKey, + PKIX_PolicyNode **pPolicyTree, + PKIX_VerifyNode **pVerifyTree, + void *plContext) +{ + PKIX_UInt32 j = 0; + PKIX_Boolean revChecking = PKIX_FALSE; + PKIX_Error *checkCertError = NULL; + void *nbioContext = NULL; + PKIX_PL_Cert *cert = NULL; + PKIX_PL_Cert *issuer = NULL; + PKIX_PL_NssContext *nssContext = NULL; + CERTCertList *certList = NULL; + const CERTChainVerifyCallback *chainVerifyCallback = NULL; + CERTCertificate *nssCert = NULL; + + PKIX_ENTER(VALIDATE, "pkix_CheckChain"); + PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex); + PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor); + PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + revChecking = *pRevChecking; + nssContext = (PKIX_PL_NssContext *)plContext; + chainVerifyCallback = &nssContext->chainVerifyCallback; + + if (chainVerifyCallback->isChainValid != NULL) { + PRBool chainOK = PR_FALSE; /*assume failure*/ + SECStatus rv; + + certList = CERT_NewCertList(); + if (certList == NULL) { + PKIX_ERROR_ALLOC_ERROR(); + } + + /* Add the trust anchor to the list */ + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert + (anchor, &cert, plContext), + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); + + PKIX_CHECK( + PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext), + PKIX_CERTGETCERTCERTIFICATEFAILED); + + rv = CERT_AddCertToListHead(certList, nssCert); + if (rv != SECSuccess) { + PKIX_ERROR_ALLOC_ERROR(); + } + /* the certList takes ownership of nssCert on success */ + nssCert = NULL; + PKIX_DECREF(cert); + + /* Add the rest of the chain to the list */ + for (j = *pCertCheckedIndex; j < numCerts; j++) { + PKIX_CHECK(PKIX_List_GetItem( + certs, j, (PKIX_PL_Object **)&cert, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK( + PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext), + PKIX_CERTGETCERTCERTIFICATEFAILED); + + rv = CERT_AddCertToListHead(certList, nssCert); + if (rv != SECSuccess) { + PKIX_ERROR_ALLOC_ERROR(); + } + /* the certList takes ownership of nssCert on success */ + nssCert = NULL; + PKIX_DECREF(cert); + } + + rv = (*chainVerifyCallback->isChainValid) + (chainVerifyCallback->isChainValidArg, certList, &chainOK); + if (rv != SECSuccess) { + PKIX_ERROR_FATAL(PKIX_CHAINVERIFYCALLBACKFAILED); + } + + if (!chainOK) { + PKIX_ERROR(PKIX_CHAINVERIFYCALLBACKFAILED); + } + + } + + PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert + (anchor, &cert, plContext), + PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); + + for (j = *pCertCheckedIndex; j < numCerts; j++) { + + PORT_Assert(cert); + PKIX_DECREF(issuer); + issuer = cert; + cert = NULL; + + PKIX_CHECK(PKIX_List_GetItem( + certs, j, (PKIX_PL_Object **)&cert, plContext), + PKIX_LISTGETITEMFAILED); + + /* check if cert pointer is valid */ + PORT_Assert(cert); + if (cert == NULL) { + continue; + } + + if (revChecking == PKIX_FALSE) { + + PKIX_CHECK(pkix_CheckCert + (cert, + checkers, + removeCheckedExtOIDs, + pCheckerIndex, + &nbioContext, + plContext), + PKIX_CHECKCERTFAILED); + + if (nbioContext != NULL) { + *pCertCheckedIndex = j; + *pRevChecking = revChecking; + *pNBIOContext = nbioContext; + goto cleanup; + } + + revChecking = PKIX_TRUE; + *pCheckerIndex = 0; + } + + if (revChecking == PKIX_TRUE) { + PKIX_RevocationStatus revStatus; + pkixErrorResult = + PKIX_RevocationChecker_Check( + cert, issuer, revChecker, + procParams, PKIX_TRUE, + (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE, + &revStatus, pReasonCode, + &nbioContext, plContext); + if (nbioContext != NULL) { + *pCertCheckedIndex = j; + *pRevChecking = revChecking; + *pNBIOContext = nbioContext; + goto cleanup; + } + if (revStatus == PKIX_RevStatus_Revoked || + pkixErrorResult) { + if (!pkixErrorResult) { + /* if pkixErrorResult is returned then + * use it as it has a detailed revocation + * error code. Otherwise create a new error */ + PKIX_ERROR_CREATE(VALIDATE, + PKIX_CERTIFICATEREVOKED, + pkixErrorResult); + } + goto cleanup; + } + revChecking = PKIX_FALSE; + *pCheckerIndex = 0; + } + + PKIX_CHECK(pkix_AddToVerifyLog + (cert, j, NULL, pVerifyTree, plContext), + PKIX_ADDTOVERIFYLOGFAILED); + } + + PKIX_CHECK(pkix_RetrieveOutputs + (checkers, pFinalSubjPubKey, pPolicyTree, plContext), + PKIX_RETRIEVEOUTPUTSFAILED); + + *pNBIOContext = NULL; + +cleanup: + if (PKIX_ERROR_RECEIVED && cert) { + checkCertError = pkixErrorResult; + + PKIX_CHECK_FATAL( + pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree, + plContext), + PKIX_ADDTOVERIFYLOGFAILED); + pkixErrorResult = checkCertError; + pkixErrorCode = pkixErrorResult->errCode; + checkCertError = NULL; + } + +fatal: + if (nssCert) { + CERT_DestroyCertificate(nssCert); + } + + if (certList) { + CERT_DestroyCertList(certList); + } + + PKIX_DECREF(checkCertError); + PKIX_DECREF(cert); + PKIX_DECREF(issuer); + + PKIX_RETURN(VALIDATE); +} + +/* + * FUNCTION: pkix_ExtractParameters + * DESCRIPTION: + * + * Extracts several parameters from the ValidateParams object pointed to by + * "valParams" and stores the CertChain at "pChain", the List of Certs at + * "pCerts", the number of Certs in the chain at "pNumCerts", the + * ProcessingParams object at "pProcParams", the List of TrustAnchors at + * "pAnchors", and the number of TrustAnchors at "pNumAnchors". + * + * PARAMETERS: + * "valParams" + * Address of ValidateParams from which the parameters are extracted. + * Must be non-NULL. + * "pCerts" + * Address where object pointer for List of Certs will be stored. + * Must be non-NULL. + * "pNumCerts" + * Address where number of Certs will be stored. Must be non-NULL. + * "pProcParams" + * Address where object pointer for ProcessingParams will be stored. + * Must be non-NULL. + * "pAnchors" + * Address where object pointer for List of Anchors will be stored. + * Must be non-NULL. + * "pNumAnchors" + * Address where number of Anchors 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 Validate 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_ExtractParameters( + PKIX_ValidateParams *valParams, + PKIX_List **pCerts, + PKIX_UInt32 *pNumCerts, + PKIX_ProcessingParams **pProcParams, + PKIX_List **pAnchors, + PKIX_UInt32 *pNumAnchors, + void *plContext) +{ + PKIX_ENTER(VALIDATE, "pkix_ExtractParameters"); + PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts); + PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors); + + /* extract relevant parameters from chain */ + PKIX_CHECK(PKIX_ValidateParams_GetCertChain + (valParams, pCerts, plContext), + PKIX_VALIDATEPARAMSGETCERTCHAINFAILED); + + PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext), + PKIX_LISTGETLENGTHFAILED); + + /* extract relevant parameters from procParams */ + PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams + (valParams, pProcParams, plContext), + PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors + (*pProcParams, pAnchors, plContext), + PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED); + + PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext), + PKIX_LISTGETLENGTHFAILED); + +cleanup: + + PKIX_RETURN(VALIDATE); +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_ValidateChain (see comments in pkix.h) + */ +PKIX_Error * +PKIX_ValidateChain( + PKIX_ValidateParams *valParams, + PKIX_ValidateResult **pResult, + PKIX_VerifyNode **pVerifyTree, + void *plContext) +{ + PKIX_Error *chainFailed = NULL; + + PKIX_ProcessingParams *procParams = NULL; + PKIX_CertChainChecker *userChecker = NULL; + PKIX_RevocationChecker *revChecker = NULL; + PKIX_List *certs = NULL; + PKIX_List *checkers = NULL; + PKIX_List *anchors = NULL; + PKIX_List *userCheckers = NULL; + PKIX_List *userCheckerExtOIDs = NULL; + PKIX_List *validateCheckedCritExtOIDsList = NULL; + PKIX_TrustAnchor *anchor = NULL; + PKIX_ValidateResult *valResult = NULL; + PKIX_PL_PublicKey *finalPubKey = NULL; + PKIX_PolicyNode *validPolicyTree = NULL; + PKIX_Boolean supportForwarding = PKIX_FALSE; + PKIX_Boolean revChecking = PKIX_FALSE; + PKIX_UInt32 i, numCerts, numAnchors; + PKIX_UInt32 numUserCheckers = 0; + PKIX_UInt32 certCheckedIndex = 0; + PKIX_UInt32 checkerIndex = 0; + PKIX_UInt32 reasonCode = 0; + void *nbioContext = NULL; + + PKIX_ENTER(VALIDATE, "PKIX_ValidateChain"); + PKIX_NULLCHECK_TWO(valParams, pResult); + + /* extract various parameters from valParams */ + PKIX_CHECK(pkix_ExtractParameters + (valParams, + &certs, + &numCerts, + &procParams, + &anchors, + &numAnchors, + plContext), + PKIX_EXTRACTPARAMETERSFAILED); + + /* + * setup an extension OID list that user had defined for his checker + * processing. User checker is not responsible for taking out OIDs + * from unresolved critical extension list as the libpkix checker + * is doing. Here we add those user checkers' OIDs to the removal + * list to be taken out by CheckChain + */ + PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers + (procParams, &userCheckers, plContext), + PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); + + if (userCheckers != NULL) { + + PKIX_CHECK(PKIX_List_Create + (&validateCheckedCritExtOIDsList, + plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength + (userCheckers, &numUserCheckers, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numUserCheckers; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (userCheckers, + i, + (PKIX_PL_Object **) &userChecker, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK + (PKIX_CertChainChecker_IsForwardCheckingSupported + (userChecker, &supportForwarding, plContext), + PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); + + if (supportForwarding == PKIX_FALSE) { + + PKIX_CHECK + (PKIX_CertChainChecker_GetSupportedExtensions + (userChecker, &userCheckerExtOIDs, plContext), + PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); + + if (userCheckerExtOIDs != NULL) { + PKIX_CHECK(pkix_List_AppendList + (validateCheckedCritExtOIDsList, + userCheckerExtOIDs, + plContext), + PKIX_LISTAPPENDLISTFAILED); + } + } + + PKIX_DECREF(userCheckerExtOIDs); + PKIX_DECREF(userChecker); + } + } + + PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker + (procParams, &revChecker, plContext), + PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); + + /* try to validate the chain with each anchor */ + for (i = 0; i < numAnchors; i++){ + + /* get trust anchor */ + PKIX_CHECK(PKIX_List_GetItem + (anchors, i, (PKIX_PL_Object **)&anchor, plContext), + PKIX_LISTGETITEMFAILED); + + /* initialize checkers using information from trust anchor */ + PKIX_CHECK(pkix_InitializeCheckers + (anchor, procParams, numCerts, &checkers, plContext), + PKIX_INITIALIZECHECKERSFAILED); + + /* + * Validate the chain using this trust anchor and these + * checkers. (WARNING: checkers that use non-blocking I/O + * are not currently supported.) + */ + certCheckedIndex = 0; + checkerIndex = 0; + revChecking = PKIX_FALSE; + chainFailed = pkix_CheckChain + (certs, + numCerts, + anchor, + checkers, + revChecker, + validateCheckedCritExtOIDsList, + procParams, + &certCheckedIndex, + &checkerIndex, + &revChecking, + &reasonCode, + &nbioContext, + &finalPubKey, + &validPolicyTree, + pVerifyTree, + plContext); + + if (chainFailed) { + + /* cert chain failed to validate */ + + PKIX_DECREF(chainFailed); + PKIX_DECREF(anchor); + PKIX_DECREF(checkers); + PKIX_DECREF(validPolicyTree); + + /* if last anchor, we fail; else, we try next anchor */ + if (i == (numAnchors - 1)) { /* last anchor */ + PKIX_ERROR(PKIX_VALIDATECHAINFAILED); + } + + } else { + + /* XXX Remove this assertion after 2014-12-31. + * See bug 946984. */ + PORT_Assert(reasonCode == 0); + + /* cert chain successfully validated! */ + PKIX_CHECK(pkix_ValidateResult_Create + (finalPubKey, + anchor, + validPolicyTree, + &valResult, + plContext), + PKIX_VALIDATERESULTCREATEFAILED); + + *pResult = valResult; + + /* no need to try any more anchors in the loop */ + goto cleanup; + } + } + +cleanup: + + PKIX_DECREF(finalPubKey); + PKIX_DECREF(certs); + PKIX_DECREF(anchors); + PKIX_DECREF(anchor); + PKIX_DECREF(checkers); + PKIX_DECREF(revChecker); + PKIX_DECREF(validPolicyTree); + PKIX_DECREF(chainFailed); + PKIX_DECREF(procParams); + PKIX_DECREF(userCheckers); + PKIX_DECREF(validateCheckedCritExtOIDsList); + + PKIX_RETURN(VALIDATE); +} + +/* + * FUNCTION: pkix_Validate_BuildUserOIDs + * DESCRIPTION: + * + * This function creates a List of the OIDs that are processed by the user + * checkers in the List pointed to by "userCheckers", storing the resulting + * List at "pUserCritOIDs". If the List of userCheckers is NULL, the output + * List will be NULL. Otherwise the output List will be non-NULL, but may be + * empty. + * + * PARAMETERS: + * "userCheckers" + * The address of the List of userCheckers. + * "pUserCritOIDs" + * The address at which the List is 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 VALIDATE 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_Validate_BuildUserOIDs( + PKIX_List *userCheckers, + PKIX_List **pUserCritOIDs, + void *plContext) +{ + PKIX_UInt32 numUserCheckers = 0; + PKIX_UInt32 i = 0; + PKIX_List *userCritOIDs = NULL; + PKIX_List *userCheckerExtOIDs = NULL; + PKIX_Boolean supportForwarding = PKIX_FALSE; + PKIX_CertChainChecker *userChecker = NULL; + + PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs"); + PKIX_NULLCHECK_ONE(pUserCritOIDs); + + if (userCheckers != NULL) { + PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength + (userCheckers, &numUserCheckers, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numUserCheckers; i++) { + PKIX_CHECK(PKIX_List_GetItem + (userCheckers, + i, + (PKIX_PL_Object **) &userChecker, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported + (userChecker, &supportForwarding, plContext), + PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); + + if (supportForwarding == PKIX_FALSE) { + + PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions + (userChecker, &userCheckerExtOIDs, plContext), + PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); + + if (userCheckerExtOIDs != NULL) { + PKIX_CHECK(pkix_List_AppendList + (userCritOIDs, userCheckerExtOIDs, plContext), + PKIX_LISTAPPENDLISTFAILED); + } + } + + PKIX_DECREF(userCheckerExtOIDs); + PKIX_DECREF(userChecker); + } + } + + *pUserCritOIDs = userCritOIDs; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(userCritOIDs); + } + + PKIX_DECREF(userCheckerExtOIDs); + PKIX_DECREF(userChecker); + + PKIX_RETURN(VALIDATE); +} + +/* + * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h) + */ +PKIX_Error * +PKIX_ValidateChain_NB( + PKIX_ValidateParams *valParams, + PKIX_UInt32 *pCertIndex, + PKIX_UInt32 *pAnchorIndex, + PKIX_UInt32 *pCheckerIndex, + PKIX_Boolean *pRevChecking, + PKIX_List **pCheckers, + void **pNBIOContext, + PKIX_ValidateResult **pResult, + PKIX_VerifyNode **pVerifyTree, + void *plContext) +{ + PKIX_UInt32 numCerts = 0; + PKIX_UInt32 numAnchors = 0; + PKIX_UInt32 i = 0; + PKIX_UInt32 certIndex = 0; + PKIX_UInt32 anchorIndex = 0; + PKIX_UInt32 checkerIndex = 0; + PKIX_UInt32 reasonCode = 0; + PKIX_Boolean revChecking = PKIX_FALSE; + PKIX_List *certs = NULL; + PKIX_List *anchors = NULL; + PKIX_List *checkers = NULL; + PKIX_List *userCheckers = NULL; + PKIX_List *validateCheckedCritExtOIDsList = NULL; + PKIX_TrustAnchor *anchor = NULL; + PKIX_ValidateResult *valResult = NULL; + PKIX_PL_PublicKey *finalPubKey = NULL; + PKIX_PolicyNode *validPolicyTree = NULL; + PKIX_ProcessingParams *procParams = NULL; + PKIX_RevocationChecker *revChecker = NULL; + PKIX_Error *chainFailed = NULL; + void *nbioContext = NULL; + + PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB"); + PKIX_NULLCHECK_FOUR + (valParams, pCertIndex, pAnchorIndex, pCheckerIndex); + PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + /* extract various parameters from valParams */ + PKIX_CHECK(pkix_ExtractParameters + (valParams, + &certs, + &numCerts, + &procParams, + &anchors, + &numAnchors, + plContext), + PKIX_EXTRACTPARAMETERSFAILED); + + /* + * Create a List of the OIDs that will be processed by the user + * checkers. User checkers are not responsible for removing OIDs from + * the List of unresolved critical extensions, as libpkix checkers are. + * So we add those user checkers' OIDs to the removal list to be taken + * out by CheckChain. + */ + PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers + (procParams, &userCheckers, plContext), + PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); + + PKIX_CHECK(pkix_Validate_BuildUserOIDs + (userCheckers, &validateCheckedCritExtOIDsList, plContext), + PKIX_VALIDATEBUILDUSEROIDSFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker + (procParams, &revChecker, plContext), + PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); + + /* Are we resuming after a WOULDBLOCK return, or starting anew ? */ + if (nbioContext != NULL) { + /* Resuming */ + certIndex = *pCertIndex; + anchorIndex = *pAnchorIndex; + checkerIndex = *pCheckerIndex; + revChecking = *pRevChecking; + checkers = *pCheckers; + *pCheckers = NULL; + } + + /* try to validate the chain with each anchor */ + for (i = anchorIndex; i < numAnchors; i++) { + + /* get trust anchor */ + PKIX_CHECK(PKIX_List_GetItem + (anchors, i, (PKIX_PL_Object **)&anchor, plContext), + PKIX_LISTGETITEMFAILED); + + /* initialize checkers using information from trust anchor */ + if (nbioContext == NULL) { + PKIX_CHECK(pkix_InitializeCheckers + (anchor, + procParams, + numCerts, + &checkers, + plContext), + PKIX_INITIALIZECHECKERSFAILED); + } + + /* + * Validate the chain using this trust anchor and these + * checkers. + */ + chainFailed = pkix_CheckChain + (certs, + numCerts, + anchor, + checkers, + revChecker, + validateCheckedCritExtOIDsList, + procParams, + &certIndex, + &checkerIndex, + &revChecking, + &reasonCode, + &nbioContext, + &finalPubKey, + &validPolicyTree, + pVerifyTree, + plContext); + + if (nbioContext != NULL) { + *pCertIndex = certIndex; + *pAnchorIndex = anchorIndex; + *pCheckerIndex = checkerIndex; + *pRevChecking = revChecking; + PKIX_INCREF(checkers); + *pCheckers = checkers; + *pNBIOContext = nbioContext; + goto cleanup; + } + + if (chainFailed) { + + /* cert chain failed to validate */ + + PKIX_DECREF(chainFailed); + PKIX_DECREF(anchor); + PKIX_DECREF(checkers); + PKIX_DECREF(validPolicyTree); + + /* if last anchor, we fail; else, we try next anchor */ + if (i == (numAnchors - 1)) { /* last anchor */ + PKIX_ERROR(PKIX_VALIDATECHAINFAILED); + } + + } else { + + /* XXX Remove this assertion after 2014-12-31. + * See bug 946984. */ + PORT_Assert(reasonCode == 0); + + /* cert chain successfully validated! */ + PKIX_CHECK(pkix_ValidateResult_Create + (finalPubKey, + anchor, + validPolicyTree, + &valResult, + plContext), + PKIX_VALIDATERESULTCREATEFAILED); + + *pResult = valResult; + + /* no need to try any more anchors in the loop */ + goto cleanup; + } + } + +cleanup: + + PKIX_DECREF(finalPubKey); + PKIX_DECREF(certs); + PKIX_DECREF(anchors); + PKIX_DECREF(anchor); + PKIX_DECREF(checkers); + PKIX_DECREF(revChecker); + PKIX_DECREF(validPolicyTree); + PKIX_DECREF(chainFailed); + PKIX_DECREF(procParams); + PKIX_DECREF(userCheckers); + PKIX_DECREF(validateCheckedCritExtOIDsList); + + PKIX_RETURN(VALIDATE); +} diff --git a/security/nss/lib/libpkix/pkix/top/pkix_validate.h b/security/nss/lib/libpkix/pkix/top/pkix_validate.h new file mode 100644 index 0000000000..7692e3babf --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.h @@ -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_validate.h + * + * Header file for validateChain function + * + */ + +#ifndef _PKIX_VALIDATE_H +#define _PKIX_VALIDATE_H +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +PKIX_Error * +pkix_CheckChain( + PKIX_List *certs, + PKIX_UInt32 numCerts, + PKIX_TrustAnchor *anchor, + PKIX_List *checkers, + PKIX_RevocationChecker *revChecker, + PKIX_List *buildCheckedExtOIDs, + PKIX_ProcessingParams *procParams, + PKIX_UInt32 *pCertCheckedIndex, + PKIX_UInt32 *pCheckerIndex, + PKIX_Boolean *pRevChecking, + PKIX_UInt32 *pReasonCode, + void **pNBIOContext, + PKIX_PL_PublicKey **pFinalSubjPubKey, + PKIX_PolicyNode **pPolicyTree, + PKIX_VerifyNode **pVerifyTree, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_VALIDATE_H */ diff --git a/security/nss/lib/libpkix/pkix/top/top.gyp b/security/nss/lib/libpkix/pkix/top/top.gyp new file mode 100644 index 0000000000..fb1b08ecbd --- /dev/null +++ b/security/nss/lib/libpkix/pkix/top/top.gyp @@ -0,0 +1,25 @@ +# 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': 'pkixtop', + 'type': 'static_library', + 'sources': [ + 'pkix_build.c', + 'pkix_lifecycle.c', + 'pkix_validate.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix/util/Makefile b/security/nss/lib/libpkix/pkix/util/Makefile new file mode 100644 index 0000000000..2b5492506c --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/Makefile @@ -0,0 +1,44 @@ +#! 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). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### diff --git a/security/nss/lib/libpkix/pkix/util/exports.gyp b/security/nss/lib/libpkix/pkix/util/exports.gyp new file mode 100644 index 0000000000..8318c6c347 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/exports.gyp @@ -0,0 +1,28 @@ +# 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_util_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_error.h', + 'pkix_list.h', + 'pkix_logger.h', + 'pkix_tools.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/util/manifest.mn b/security/nss/lib/libpkix/pkix/util/manifest.mn new file mode 100644 index 0000000000..e7d9f973c7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/manifest.mn @@ -0,0 +1,25 @@ +# +# 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 = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_tools.h \ + pkix_error.h \ + pkix_logger.h \ + pkix_list.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_tools.c \ + pkix_error.c \ + pkix_logger.c \ + pkix_list.c \ + pkix_errpaths.c \ + $(NULL) + +LIBRARY_NAME = pkixutil +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.c b/security/nss/lib/libpkix/pkix/util/pkix_error.c new file mode 100644 index 0000000000..9d730ca161 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_error.c @@ -0,0 +1,565 @@ +/* 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_error.c + * + * Error Object Functions + * + */ + +#include "pkix_error.h" + +#undef PKIX_ERRORENTRY + +#define PKIX_ERRORENTRY(name,desc,nsserr) #desc + +#if defined PKIX_ERROR_DESCRIPTION + +const char * const PKIX_ErrorText[] = +{ +#include "pkix_errorstrings.h" +}; + +#else + +#include "prprf.h" + +#endif /* PKIX_ERROR_DESCRIPTION */ + +extern const PKIX_Int32 PKIX_PLErrorIndex[]; + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_Error_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Error_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_Error *firstError = NULL; + PKIX_Error *secondError = NULL; + PKIX_Error *firstCause = NULL; + PKIX_Error *secondCause = NULL; + PKIX_PL_Object *firstInfo = NULL; + PKIX_PL_Object *secondInfo = NULL; + PKIX_ERRORCLASS firstClass, secondClass; + PKIX_UInt32 secondType; + PKIX_Boolean boolResult, unequalFlag; + + PKIX_ENTER(ERROR, "pkix_Error_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + unequalFlag = PKIX_FALSE; + + /* First just compare pointer values to save time */ + if (firstObject == secondObject) { + *pResult = PKIX_TRUE; + goto cleanup; + } else { + /* Result will only be set to true if all tests pass */ + *pResult = PKIX_FALSE; + } + + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_ERROR_TYPE, plContext), + PKIX_FIRSTOBJECTNOTANERROROBJECT); + + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_ERRORGETTINGSECONDOBJECTTYPE); + + /* If types differ, then return false. Result is already set */ + if (secondType != PKIX_ERROR_TYPE) goto cleanup; + + /* It is safe to cast to PKIX_Error */ + firstError = (PKIX_Error *) firstObject; + secondError = (PKIX_Error *) secondObject; + + /* Compare error codes */ + firstClass = firstError->errClass; + secondClass = secondError->errClass; + + /* If codes differ, return false. Result is already set */ + if (firstClass != secondClass) goto cleanup; + + /* Compare causes */ + firstCause = firstError->cause; + secondCause = secondError->cause; + + /* Ensure that either both or none of the causes are NULL */ + if (((firstCause != NULL) && (secondCause == NULL))|| + ((firstCause == NULL) && (secondCause != NULL))) + unequalFlag = PKIX_TRUE; + + if ((firstCause != NULL) && (secondCause != NULL)) { + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object*)firstCause, + (PKIX_PL_Object*)secondCause, + &boolResult, + plContext), + PKIX_ERRORINRECURSIVEEQUALSCALL); + + /* Set the unequalFlag so that we return after dec refing */ + if (boolResult == 0) unequalFlag = PKIX_TRUE; + } + + /* If the cause errors are not equal, return null */ + if (unequalFlag) goto cleanup; + + /* Compare info fields */ + firstInfo = firstError->info; + secondInfo = secondError->info; + + if (firstInfo != secondInfo) goto cleanup; + + /* Ensure that either both or none of the infos are NULL */ + if (((firstInfo != NULL) && (secondInfo == NULL))|| + ((firstInfo == NULL) && (secondInfo != NULL))) + unequalFlag = PKIX_TRUE; + + if ((firstInfo != NULL) && (secondInfo != NULL)) { + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object*)firstInfo, + (PKIX_PL_Object*)secondInfo, + &boolResult, + plContext), + PKIX_ERRORINRECURSIVEEQUALSCALL); + + /* Set the unequalFlag so that we return after dec refing */ + if (boolResult == 0) unequalFlag = PKIX_TRUE; + } + + /* If the infos are not equal, return null */ + if (unequalFlag) goto cleanup; + + + /* Compare descs */ + if (firstError->errCode != secondError->errCode) { + unequalFlag = PKIX_TRUE; + } + + if (firstError->plErr != secondError->plErr) { + unequalFlag = PKIX_TRUE; + } + + /* If the unequalFlag was set, return false */ + if (unequalFlag) goto cleanup; + + /* Errors are equal in all fields at this point */ + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: pkix_Error_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Error_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_Error *error = NULL; + + PKIX_ENTER(ERROR, "pkix_Error_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext), + PKIX_OBJECTNOTANERROR); + + error = (PKIX_Error *)object; + + PKIX_DECREF(error->cause); + + PKIX_DECREF(error->info); + +cleanup: + + PKIX_RETURN(ERROR); +} + + +/* XXX This is not thread safe */ +static PKIX_UInt32 pkix_error_cause_depth = 1; + +/* + * FUNCTION: pkix_Error_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Error_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_Error *error = NULL; + PKIX_Error *cause = NULL; + PKIX_PL_String *desc = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *causeString = NULL; + PKIX_PL_String *optCauseString = NULL; + PKIX_PL_String *errorNameString = NULL; + char *format = NULL; + PKIX_ERRORCLASS errClass; + + PKIX_ENTER(ERROR, "pkix_Error_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext), + PKIX_OBJECTNOTANERROR); + + error = (PKIX_Error *)object; + + /* Get this error's errClass, description and the string of its cause */ + errClass = error->errClass; + + /* Get the description string */ + PKIX_Error_GetDescription(error, &desc, plContext); + + /* Get the cause */ + cause = error->cause; + + /* Get the causes's description string */ + if (cause != NULL) { + pkix_error_cause_depth++; + + /* Get the cause string */ + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)cause, &causeString, plContext), + PKIX_ERRORGETTINGCAUSESTRING); + + format = "\n*** Cause (%d): %s"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + format, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + /* Create the optional Cause String */ + PKIX_CHECK(PKIX_PL_Sprintf + (&optCauseString, + plContext, + formatString, + pkix_error_cause_depth, + causeString), + PKIX_SPRINTFFAILED); + + PKIX_DECREF(formatString); + + pkix_error_cause_depth--; + } + + /* Create the Format String */ + if (optCauseString != NULL) { + format = "*** %s Error- %s%s"; + } else { + format = "*** %s Error- %s"; + } + + /* Ensure that error errClass is known, otherwise default to Object */ + if (errClass >= PKIX_NUMERRORCLASSES) { + errClass = 0; + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (void *)PKIX_ERRORCLASSNAMES[errClass], + 0, + &errorNameString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + format, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + /* Create the output String */ + PKIX_CHECK(PKIX_PL_Sprintf + (pString, + plContext, + formatString, + errorNameString, + desc, + optCauseString), + PKIX_SPRINTFFAILED); + +cleanup: + + PKIX_DECREF(desc); + PKIX_DECREF(causeString); + PKIX_DECREF(formatString); + PKIX_DECREF(optCauseString); + PKIX_DECREF(errorNameString); + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: pkix_Error_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Error_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pResult, + void *plContext) +{ + PKIX_ENTER(ERROR, "pkix_Error_Hashcode"); + PKIX_NULLCHECK_TWO(object, pResult); + + /* XXX Unimplemented */ + /* XXX Need to make hashcodes equal when two errors are equal */ + *pResult = (PKIX_UInt32)((char *)object - (char *)NULL); + + PKIX_RETURN(ERROR); +} + +/* --Initializers------------------------------------------------- */ + +/* + * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a + * descriptive name for an error errClass. This is used by the default + * PKIX_PL_Error_ToString function. + * + * Note: PKIX_ERRORCLASSES is defined in pkixt.h as a list of error types. + * (More precisely, as a list of invocations of ERRMACRO(type).) The + * macro is expanded in pkixt.h to define error numbers, and here to + * provide corresponding strings. For example, since the fifth ERRMACRO + * entry is MUTEX, then PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and + * PKIX_ERRORCLASSNAMES[4] is initialized here with the value "MUTEX". + */ +#undef ERRMACRO +#define ERRMACRO(type) #type + +const char * +PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES] = +{ + PKIX_ERRORCLASSES +}; + +/* + * FUNCTION: pkix_Error_RegisterSelf + * DESCRIPTION: + * Registers PKIX_ERROR_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_Error_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(ERROR, "pkix_Error_RegisterSelf"); + + entry.description = "Error"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_Error); + entry.destructor = pkix_Error_Destroy; + entry.equalsFunction = pkix_Error_Equals; + entry.hashcodeFunction = pkix_Error_Hashcode; + entry.toStringFunction = pkix_Error_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_ERROR_TYPE] = entry; + + PKIX_RETURN(ERROR); +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_Error_Create (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_Create( + PKIX_ERRORCLASS errClass, + PKIX_Error *cause, + PKIX_PL_Object *info, + PKIX_ERRORCODE errCode, + PKIX_Error **pError, + void *plContext) +{ + PKIX_Error *tempCause = NULL; + PKIX_Error *error = NULL; + + PKIX_ENTER(ERROR, "PKIX_Error_Create"); + + PKIX_NULLCHECK_ONE(pError); + + /* + * when called here, if PKIX_PL_Object_Alloc returns an error, + * it must be a PKIX_ALLOC_ERROR + */ + pkixErrorResult = PKIX_PL_Object_Alloc + (PKIX_ERROR_TYPE, + ((PKIX_UInt32)(sizeof (PKIX_Error))), + (PKIX_PL_Object **)&error, + plContext); + + if (pkixErrorResult) return (pkixErrorResult); + + error->errClass = errClass; + + /* Ensure we don't have a loop. Follow causes until NULL */ + for (tempCause = cause; + tempCause != NULL; + tempCause = tempCause->cause) { + /* If we detect a loop, throw a new error */ + if (tempCause == error) { + PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED); + } + } + + PKIX_INCREF(cause); + error->cause = cause; + + PKIX_INCREF(info); + error->info = info; + + error->errCode = errCode; + + error->plErr = PKIX_PLErrorIndex[error->errCode]; + + *pError = error; + error = NULL; + +cleanup: + /* PKIX-XXX Fix for leak during error creation */ + PKIX_DECREF(error); + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetErrorClass (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetErrorClass( + PKIX_Error *error, + PKIX_ERRORCLASS *pClass, + void *plContext) +{ + PKIX_ENTER(ERROR, "PKIX_Error_GetErrorClass"); + PKIX_NULLCHECK_TWO(error, pClass); + + *pClass = error->errClass; + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetErrorCode (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetErrorCode( + PKIX_Error *error, + PKIX_ERRORCODE *pCode, + void *plContext) +{ + PKIX_ENTER(ERROR, "PKIX_Error_GetErrorCode"); + PKIX_NULLCHECK_TWO(error, pCode); + + *pCode = error->errCode; + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetCause (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetCause( + PKIX_Error *error, + PKIX_Error **pCause, + void *plContext) +{ + PKIX_ENTER(ERROR, "PKIX_Error_GetCause"); + PKIX_NULLCHECK_TWO(error, pCause); + + if (error->cause != PKIX_ALLOC_ERROR()){ + PKIX_INCREF(error->cause); + } + + *pCause = error->cause; + +cleanup: + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetSupplementaryInfo (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetSupplementaryInfo( + PKIX_Error *error, + PKIX_PL_Object **pInfo, + void *plContext) +{ + PKIX_ENTER(ERROR, "PKIX_Error_GetSupplementaryInfo"); + PKIX_NULLCHECK_TWO(error, pInfo); + + PKIX_INCREF(error->info); + + *pInfo = error->info; + +cleanup: + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetDescription (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetDescription( + PKIX_Error *error, + PKIX_PL_String **pDesc, + void *plContext) +{ + PKIX_PL_String *descString = NULL; +#ifndef PKIX_ERROR_DESCRIPTION + char errorStr[32]; +#endif + + PKIX_ENTER(ERROR, "PKIX_Error_GetDescription"); + PKIX_NULLCHECK_TWO(error, pDesc); + +#ifndef PKIX_ERROR_DESCRIPTION + PR_snprintf(errorStr, 32, "Error code: %d", error->errCode); +#endif + + PKIX_PL_String_Create(PKIX_ESCASCII, +#if defined PKIX_ERROR_DESCRIPTION + (void *)PKIX_ErrorText[error->errCode], +#else + errorStr, +#endif + 0, + &descString, + plContext); + + *pDesc = descString; + + PKIX_RETURN(ERROR); +} diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.h b/security/nss/lib/libpkix/pkix/util/pkix_error.h new file mode 100644 index 0000000000..ca4171ab17 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_error.h @@ -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_error.h + * + * Error Object Type Definition + * + */ + +#ifndef _PKIX_ERROR_H +#define _PKIX_ERROR_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_ErrorStruct { + PKIX_ERRORCODE errCode; + PKIX_ERRORCLASS errClass; /* was formerly "code" */ + PKIX_Int32 plErr; + PKIX_Error *cause; + PKIX_PL_Object *info; +}; + +/* see source file for function documentation */ + +extern PKIX_Error * pkix_Error_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_ERROR_H */ diff --git a/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c new file mode 100644 index 0000000000..a33ccf7ddb --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c @@ -0,0 +1,103 @@ +/* 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_errpaths.c + * + * Error Handling Helper Functions + * + */ + +#define PKIX_STDVARS_POINTER +#include "pkix_error.h" + +const PKIX_StdVars zeroStdVars; + +PKIX_Error* +PKIX_DoThrow(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass, + PKIX_ERRORCODE errCode, PKIX_ERRORCLASS overrideClass, + void *plContext) +{ + if (!pkixErrorReceived && !pkixErrorResult && pkixErrorList) { + pkixTempResult = PKIX_List_GetItem(pkixErrorList, 0, + (PKIX_PL_Object**)&pkixReturnResult, + plContext); + } else { + pkixTempResult = (PKIX_Error*)pkix_Throw(errClass, myFuncName, errCode, + overrideClass, pkixErrorResult, + &pkixReturnResult, plContext); + } + if (pkixReturnResult) { + if (pkixErrorResult != PKIX_ALLOC_ERROR()) { + PKIX_DECREF(pkixErrorResult); + } + pkixTempResult = pkixReturnResult; + } else if (pkixErrorResult) { + if (pkixTempResult != PKIX_ALLOC_ERROR()) { + PKIX_DECREF(pkixTempResult); + } + pkixTempResult = pkixErrorResult; + } + if (pkixErrorList) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorList, plContext); + pkixErrorList = NULL; + } + return pkixTempResult; +} + +PKIX_Error * +PKIX_DoReturn(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass, + PKIX_Boolean doLogger, void *plContext) +{ + PKIX_OBJECT_UNLOCK(lockedObject); + if (pkixErrorReceived || pkixErrorResult || pkixErrorList) + return PKIX_DoThrow(stdVars, errClass, pkixErrorCode, pkixErrorClass, + plContext); + /* PKIX_DEBUG_EXIT(type); */ + if (doLogger) + _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, "<<<", PKIX_LOGGER_LEVEL_TRACE); + return NULL; +} + +/* PKIX_DoAddError - creates the list of received error if it does not exist + * yet and adds newly received error into the list. */ +void +PKIX_DoAddError(PKIX_StdVars *stdVars, PKIX_Error *error, void * plContext) +{ + PKIX_List *localList = NULL; + PKIX_Error *localError = NULL; + PKIX_Boolean listCreated = PKIX_FALSE; + + if (!pkixErrorList) { + localError = PKIX_List_Create(&localList, plContext); + if (localError) + goto cleanup; + listCreated = PKIX_TRUE; + } else { + localList = pkixErrorList; + } + + localError = PKIX_List_AppendItem(localList, (PKIX_PL_Object*)error, + plContext); + PORT_Assert (localError == NULL); + if (localError != NULL) { + if (listCreated) { + /* ignore the error code of DecRef function */ + PKIX_PL_Object_DecRef((PKIX_PL_Object*)localList, plContext); + localList = NULL; + } + } else { + pkixErrorList = localList; + } + +cleanup: + + if (localError && localError != PKIX_ALLOC_ERROR()) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)localError, plContext); + } + + if (error && error != PKIX_ALLOC_ERROR()) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext); + } +} + diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.c b/security/nss/lib/libpkix/pkix/util/pkix_list.c new file mode 100644 index 0000000000..d02b66e6d6 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_list.c @@ -0,0 +1,1701 @@ +/* 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_list.c + * + * List Object Functions + * + */ + +#include "pkix_list.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_List_Create_Internal + * DESCRIPTION: + * + * Creates a new List, using the Boolean value of "isHeader" to determine + * whether the new List should be a header, and stores it at "pList". The + * List is initially empty and holds no items. To initially add items to + * the List, use PKIX_List_AppendItem. + * + * PARAMETERS: + * "isHeader" + * Boolean value indicating whether new List should be a header. + * "pList" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_List_Create_Internal( + PKIX_Boolean isHeader, + PKIX_List **pList, + void *plContext) +{ + PKIX_List *list = NULL; + + PKIX_ENTER(LIST, "pkix_List_Create_Internal"); + PKIX_NULLCHECK_ONE(pList); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LIST_TYPE, + ((PKIX_UInt32)(sizeof (PKIX_List))), + (PKIX_PL_Object **)&list, plContext), + PKIX_ERRORCREATINGLISTITEM); + + list->item = NULL; + list->next = NULL; + list->immutable = PKIX_FALSE; + list->length = 0; + list->isHeader = isHeader; + + *pList = list; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_List *nextItem = NULL; + + PKIX_ENTER(LIST, "pkix_List_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a list */ + PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), + PKIX_OBJECTNOTLIST); + + list = (PKIX_List *)object; + + /* We have a valid list. DecRef its item and recurse on next */ + PKIX_DECREF(list->item); + while ((nextItem = list->next) != NULL) { + list->next = nextItem->next; + nextItem->next = NULL; + PKIX_DECREF(nextItem); + } + list->immutable = PKIX_FALSE; + list->length = 0; + list->isHeader = PKIX_FALSE; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the List pointed + * to by "list" and stores its address in the object pointed to by "pString". + * + * PARAMETERS + * "list" + * Address of List whose string representation is desired. + * Must be non-NULL. + * "pString" + * Address of object pointer's destination. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a List 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_List_ToString_Helper( + PKIX_List *list, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *itemString = NULL; + PKIX_PL_String *nextString = NULL; + PKIX_PL_String *format = NULL; + PKIX_Boolean empty; + + PKIX_ENTER(LIST, "pkix_List_ToString_Helper"); + PKIX_NULLCHECK_TWO(list, pString); + + /* special case when list is the header */ + if (list->isHeader){ + + PKIX_CHECK(PKIX_List_IsEmpty(list, &empty, plContext), + PKIX_LISTISEMPTYFAILED); + + if (empty){ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "EMPTY", + 0, + &itemString, + plContext), + PKIX_ERRORCREATINGITEMSTRING); + (*pString) = itemString; + PKIX_DEBUG_EXIT(LIST); + return (NULL); + } else { + PKIX_CHECK(pkix_List_ToString_Helper + (list->next, &itemString, plContext), + PKIX_LISTTOSTRINGHELPERFAILED); + } + + /* Create a string object from the format */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "%s", 0, &format, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (pString, plContext, format, itemString), + PKIX_SPRINTFFAILED); + } else { + /* Get a string for this list's item */ + if (list->item == NULL) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "(null)", + 0, + &itemString, + plContext), + PKIX_STRINGCREATEFAILED); + } else { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)list->item, + &itemString, + plContext), + PKIX_OBJECTTOSTRINGFAILED); + } + if (list->next == NULL) { + /* Just return the itemstring */ + (*pString) = itemString; + PKIX_DEBUG_EXIT(LIST); + return (NULL); + } + + /* Recursive call to get string for this list's next pointer */ + PKIX_CHECK(pkix_List_ToString_Helper + (list->next, &nextString, plContext), + PKIX_LISTTOSTRINGHELPERFAILED); + + /* Create a string object from the format */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s, %s", + 0, + &format, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (pString, + plContext, + format, + itemString, + nextString), + PKIX_SPRINTFFAILED); + } + +cleanup: + + PKIX_DECREF(itemString); + PKIX_DECREF(nextString); + PKIX_DECREF(format); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_PL_String *listString = NULL; + PKIX_PL_String *format = NULL; + + PKIX_ENTER(LIST, "pkix_List_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), + PKIX_OBJECTNOTLIST); + + list = (PKIX_List *)object; + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + PKIX_CHECK(pkix_List_ToString_Helper(list, &listString, plContext), + PKIX_LISTTOSTRINGHELPERFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "(%s)", 0, &format, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf(pString, plContext, format, listString), + PKIX_SPRINTFFAILED); + +cleanup: + + PKIX_DECREF(listString); + PKIX_DECREF(format); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_List *firstList = NULL; + PKIX_List *secondList = NULL; + PKIX_UInt32 firstLength = 0; + PKIX_UInt32 secondLength = 0; + PKIX_PL_Object *firstItem = NULL; + PKIX_PL_Object *secondItem = NULL; + PKIX_UInt32 i = 0; + + PKIX_ENTER(LIST, "pkix_List_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + /* test that first is a List */ + PKIX_CHECK(pkix_CheckType(first, PKIX_LIST_TYPE, plContext), + PKIX_FIRSTOBJECTNOTLIST); + + /* + * Since we know first is a List, if both references are + * identical, they must be equal + */ + if (first == second){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If second isn't a List, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_LIST_TYPE) goto cleanup; + + firstList = (PKIX_List *)first; + secondList = (PKIX_List *)second; + + if ((!firstList->isHeader) && (!secondList->isHeader)){ + PKIX_ERROR(PKIX_INPUTLISTSMUSTBELISTHEADERS); + } + + firstLength = firstList->length; + secondLength = secondList->length; + + cmpResult = PKIX_FALSE; + if (firstLength == secondLength){ + for (i = 0, cmpResult = PKIX_TRUE; + ((i < firstLength) && cmpResult); + i++){ + PKIX_CHECK(PKIX_List_GetItem + (firstList, i, &firstItem, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_GetItem + (secondList, i, &secondItem, plContext), + PKIX_LISTGETITEMFAILED); + + if ((!firstItem && secondItem) || + (firstItem && !secondItem)){ + cmpResult = PKIX_FALSE; + } else if (!firstItem && !secondItem){ + continue; + } else { + PKIX_CHECK(PKIX_PL_Object_Equals + (firstItem, + secondItem, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(firstItem); + PKIX_DECREF(secondItem); + } + } + } + + *pResult = cmpResult; + +cleanup: + + PKIX_DECREF(firstItem); + PKIX_DECREF(secondItem); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_PL_Object *element = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 tempHash = 0; + PKIX_UInt32 length, i; + + PKIX_ENTER(LIST, "pkix_List_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), + PKIX_OBJECTNOTLIST); + + list = (PKIX_List *)object; + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + for (i = 0; i < length; i++){ + PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext), + PKIX_LISTGETITEMFAILED); + + if (!element){ + tempHash = 100; + } else { + PKIX_CHECK(PKIX_PL_Object_Hashcode + (element, &tempHash, plContext), + PKIX_LISTHASHCODEFAILED); + } + + hash = 31 * hash + tempHash; + + PKIX_DECREF(element); + } + + *pHashcode = hash; + +cleanup: + + PKIX_DECREF(element); + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Duplicate + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_List *listDuplicate = NULL; + + PKIX_ENTER(LIST, "pkix_List_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), + PKIX_OBJECTNOTLIST); + + list = (PKIX_List *)object; + + if (list->immutable){ + PKIX_CHECK(pkix_duplicateImmutable + (object, pNewObject, plContext), + PKIX_DUPLICATEIMMUTABLEFAILED); + } else { + + PKIX_CHECK(pkix_List_Create_Internal + (list->isHeader, &listDuplicate, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + listDuplicate->length = list->length; + + PKIX_INCREF(list->item); + listDuplicate->item = list->item; + + if (list->next == NULL){ + listDuplicate->next = NULL; + } else { + /* Recursively Duplicate list */ + PKIX_CHECK(pkix_List_Duplicate + ((PKIX_PL_Object *)list->next, + (PKIX_PL_Object **)&listDuplicate->next, + plContext), + PKIX_LISTDUPLICATEFAILED); + } + + *pNewObject = (PKIX_PL_Object *)listDuplicate; + } + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(listDuplicate); + } + + PKIX_RETURN(LIST); +} + + +/* + * FUNCTION: pkix_List_GetElement + * DESCRIPTION: + * + * Copies the "list"'s element at "index" into "element". The input List must + * be the header of the List (as opposed to being an element of the List). The + * index counts from zero and must be less than the List's length. This + * function does NOT increment the reference count of the List element since + * the returned element's reference will not be stored by the calling + * function. + * + * PARAMETERS: + * "list" + * Address of List (must be header) to get element from. Must be non-NULL. + * "index" + * Index of list to get element from. Must be less than List's length. + * "pElement" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_List_GetElement( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_List **pElement, + void *plContext) +{ + PKIX_List *iterator = NULL; + PKIX_UInt32 length; + PKIX_UInt32 position = 0; + + PKIX_ENTER(LIST, "pkix_List_GetElement"); + PKIX_NULLCHECK_TWO(list, pElement); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + if (index >= length) { + PKIX_ERROR(PKIX_INDEXOUTOFBOUNDS); + } + + for (iterator = list; position++ <= index; iterator = iterator->next) + ; + + (*pElement) = iterator; + +cleanup: + + PKIX_RETURN(LIST); +} + + +/* + * FUNCTION: pkix_List_RegisterSelf + * DESCRIPTION: + * Registers PKIX_LIST_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_List_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(LIST, "pkix_List_RegisterSelf"); + + entry.description = "List"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_List); + entry.destructor = pkix_List_Destroy; + entry.equalsFunction = pkix_List_Equals; + entry.hashcodeFunction = pkix_List_Hashcode; + entry.toStringFunction = pkix_List_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_List_Duplicate; + + systemClasses[PKIX_LIST_TYPE] = entry; + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Contains + * DESCRIPTION: + * + * Checks a List pointed to by "list", to determine whether it includes + * an entry that is equal to the Object pointed to by "object", and stores + * the result in "pFound". + * + * PARAMETERS: + * "list" + * List to be searched; may be empty; must be non-NULL + * "object" + * Object to be checked for; must be non-NULL + * "pFound" + * Address where the result of the search 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 Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_Contains( + PKIX_List *list, + PKIX_PL_Object *object, + PKIX_Boolean *pFound, + void *plContext) +{ + PKIX_PL_Object *current = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + PKIX_Boolean match = PKIX_FALSE; + + PKIX_ENTER(LIST, "pkix_List_Contains"); + PKIX_NULLCHECK_THREE(list, object, pFound); + + PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (index = 0; index < numEntries; index++) { + PKIX_CHECK(PKIX_List_GetItem + (list, index, ¤t, plContext), + PKIX_LISTGETITEMFAILED); + + if (current) { + PKIX_CHECK(PKIX_PL_Object_Equals + (object, current, &match, plContext), + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(current); + } + + if (match) { + break; + } + } + + *pFound = match; + +cleanup: + + PKIX_DECREF(current); + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Remove + * DESCRIPTION: + * + * Traverses the List pointed to by "list", to find and delete an entry + * that is equal to the Object pointed to by "object". If no such entry + * is found the function does not return an error. + * + * PARAMETERS: + * "list" + * List to be searched; may be empty; must be non-NULL + * "object" + * Object to be checked for and deleted, if found; 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 Validate Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_Remove( + PKIX_List *list, + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Object *current = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + PKIX_Boolean match = PKIX_FALSE; + + PKIX_ENTER(LIST, "pkix_List_Remove"); + PKIX_NULLCHECK_TWO(list, object); + + PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (index = 0; index < numEntries; index++) { + PKIX_CHECK(PKIX_List_GetItem + (list, index, ¤t, plContext), + PKIX_LISTGETITEMFAILED); + + if (current) { + PKIX_CHECK(PKIX_PL_Object_Equals + (object, current, &match, plContext), + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(current); + } + + if (match) { + PKIX_CHECK(PKIX_List_DeleteItem + (list, index, plContext), + PKIX_LISTDELETEITEMFAILED); + break; + } + } + +cleanup: + + PKIX_DECREF(current); + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_RemoveItems + * DESCRIPTION: + * + * Traverses the List pointed to by "list", to find and delete an entry + * that is equal to the Object in the "deleteList". If no such entry + * is found the function does not return an error. + * + * PARAMETERS: + * "list" + * Object in "list" is checked for object in "deleteList" and deleted if + * found; may be empty; must be non-NULL + * "deleteList" + * List of objects to be searched ; may be empty; 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 Validate Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_RemoveItems( + PKIX_List *list, + PKIX_List *deleteList, + void *plContext) +{ + PKIX_PL_Object *current = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + + PKIX_ENTER(LIST, "pkix_List_RemoveItems"); + PKIX_NULLCHECK_TWO(list, deleteList); + + PKIX_CHECK(PKIX_List_GetLength(deleteList, &numEntries, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (index = 0; index < numEntries; index++) { + PKIX_CHECK(PKIX_List_GetItem + (deleteList, index, ¤t, plContext), + PKIX_LISTGETITEMFAILED); + + if (current) { + PKIX_CHECK(pkix_List_Remove + (list, current, plContext), + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(current); + } + } + +cleanup: + + PKIX_DECREF(current); + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_MergeLists + * DESCRIPTION: + * + * Creates a new list consisting of the items from "firstList", followed by + * the items on "secondList", returns the new list at "pMergedList". If + * both input lists are NULL or empty, the result is an empty list. If an error + * occurs, the result is NULL. + * + * PARAMETERS: + * "firstList" + * Address of list to be merged from. May be NULL or empty. + * "secondList" + * Address of list to be merged from. May be NULL or empty. + * "pMergedList" + * Address where returned object is stored. + * "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 List Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_MergeLists( + PKIX_List *firstList, + PKIX_List *secondList, + PKIX_List **pMergedList, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_PL_Object *item = NULL; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(LIST, "pkix_List_MergeLists"); + PKIX_NULLCHECK_ONE(pMergedList); + + *pMergedList = NULL; + + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + + if (firstList != NULL) { + + PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + for (i = 0; i < numItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(item); + } + + numItems = 0; + if (secondList != NULL) { + + PKIX_CHECK(PKIX_List_GetLength + (secondList, + &numItems, + plContext), + PKIX_LISTGETLENGTHFAILED); + + } + + for (i = 0; i < numItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (secondList, i, &item, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (list, item, plContext), PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(item); + } + + *pMergedList = list; + list = NULL; + +cleanup: + PKIX_DECREF(list); + PKIX_DECREF(item); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_AppendList + * DESCRIPTION: + * + * Append items on "fromList" to the "toList". Item reference count on + * "toList" is not incremented, but items appended from "fromList" are + * incremented. + * + * PARAMETERS: + * "toList" + * Address of list to be appended to. Must be non-NULL. + * "fromList" + * Address of list to be appended from. May be NULL or empty. + * "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 List Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_AppendList( + PKIX_List *toList, + PKIX_List *fromList, + void *plContext) +{ + PKIX_PL_Object *item = NULL; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(LIST, "pkix_List_AppendList"); + PKIX_NULLCHECK_ONE(toList); + + /* if fromList is NULL or is an empty list, no action */ + + if (fromList == NULL) { + goto cleanup; + } + + PKIX_CHECK(PKIX_List_GetLength(fromList, &numItems, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numItems == 0) { + goto cleanup; + } + + for (i = 0; i < numItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (fromList, i, &item, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem(toList, item, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(item); + } + +cleanup: + + PKIX_DECREF(item); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_AppendUnique + * DESCRIPTION: + * + * Adds each Object in the List pointed to by "fromList" to the List pointed + * to by "toList", if it is not already a member of that List. In other words, + * "toList" becomes the union of the two sets. + * + * PARAMETERS: + * "toList" + * Address of a List of Objects to be augmented by "fromList". Must be + * non-NULL, but may be empty. + * "fromList" + * Address of a List of Objects to be added, if not already present, to + * "toList". Must be non-NULL, but may be empty. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "toList" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_AppendUnique( + PKIX_List *toList, + PKIX_List *fromList, + void *plContext) +{ + PKIX_Boolean isContained = PKIX_FALSE; + PKIX_UInt32 listLen = 0; + PKIX_UInt32 listIx = 0; + PKIX_PL_Object *object = NULL; + + PKIX_ENTER(BUILD, "pkix_List_AppendUnique"); + PKIX_NULLCHECK_TWO(fromList, toList); + + PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (listIx = 0; listIx < listLen; listIx++) { + + PKIX_CHECK(PKIX_List_GetItem + (fromList, listIx, &object, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_List_Contains + (toList, object, &isContained, plContext), + PKIX_LISTCONTAINSFAILED); + + if (isContained == PKIX_FALSE) { + PKIX_CHECK(PKIX_List_AppendItem + (toList, object, plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + PKIX_DECREF(object); + } + +cleanup: + + PKIX_DECREF(object); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_QuickSort + * DESCRIPTION: + * + * Sorts List of Objects "fromList" using "comparatorCallback"'s result as + * comasrison key and returns the sorted List at "pSortedList". The sorting + * algorithm used is quick sort (n*logn). + * + * PARAMETERS: + * "fromList" + * Address of a List of Objects to be sorted. Must be non-NULL, but may be + * empty. + * "comparatorCallback" + * Address of callback function that will compare two Objects on the List. + * It should return -1 for less, 0 for equal and 1 for greater. The + * callback implementation chooses what in Objects to be compared. Must be + * non-NULL. + * "pSortedList" + * Address of a List of Objects that shall be sorted and returned. Must be + * non-NULL, but may be empty. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "toList" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_QuickSort( + PKIX_List *fromList, + PKIX_List_SortComparatorCallback comparator, + PKIX_List **pSortedList, + void *plContext) +{ + PKIX_List *sortedList = NULL; + PKIX_List *lessList = NULL; + PKIX_List *greaterList = NULL; + PKIX_List *sortedLessList = NULL; + PKIX_List *sortedGreaterList = NULL; + PKIX_PL_Object *object = NULL; + PKIX_PL_Object *cmpObj = NULL; + PKIX_Int32 cmpResult = 0; + PKIX_UInt32 size = 0; + PKIX_UInt32 i; + + PKIX_ENTER(BUILD, "pkix_List_QuickSort"); + PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList); + + PKIX_CHECK(PKIX_List_GetLength(fromList, &size, plContext), + PKIX_LISTGETLENGTHFAILED); + + PKIX_CHECK(PKIX_List_Create(&lessList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_Create(&greaterList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetItem + (fromList, 0, &object, plContext), + PKIX_LISTGETITEMFAILED); + + /* + * Pick the first item on the list as the one to be compared. + * Separate rest of the itmes into two lists: less-than or greater- + * than lists. Sort those two lists recursively. Insert sorted + * less-than list before the picked item and append the greater- + * than list after the picked item. + */ + for (i = 1; i < size; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (fromList, i, &cmpObj, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(comparator(object, cmpObj, &cmpResult, plContext), + PKIX_COMPARATORCALLBACKFAILED); + + if (cmpResult >= 0) { + PKIX_CHECK(PKIX_List_AppendItem + (lessList, cmpObj, plContext), + PKIX_LISTAPPENDITEMFAILED); + } else { + PKIX_CHECK(PKIX_List_AppendItem + (greaterList, cmpObj, plContext), + PKIX_LISTAPPENDITEMFAILED); + } + PKIX_DECREF(cmpObj); + } + + PKIX_CHECK(PKIX_List_Create(&sortedList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(lessList, &size, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (size > 1) { + + PKIX_CHECK(pkix_List_QuickSort + (lessList, comparator, &sortedLessList, plContext), + PKIX_LISTQUICKSORTFAILED); + + PKIX_CHECK(pkix_List_AppendList + (sortedList, sortedLessList, plContext), + PKIX_LISTAPPENDLISTFAILED); + } else { + PKIX_CHECK(pkix_List_AppendList + (sortedList, lessList, plContext), + PKIX_LISTAPPENDLISTFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem(sortedList, object, plContext), + PKIX_LISTAPPENDFAILED); + + PKIX_CHECK(PKIX_List_GetLength(greaterList, &size, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (size > 1) { + + PKIX_CHECK(pkix_List_QuickSort + (greaterList, comparator, &sortedGreaterList, plContext), + PKIX_LISTQUICKSORTFAILED); + + PKIX_CHECK(pkix_List_AppendList + (sortedList, sortedGreaterList, plContext), + PKIX_LISTAPPENDLISTFAILED); + } else { + PKIX_CHECK(pkix_List_AppendList + (sortedList, greaterList, plContext), + PKIX_LISTAPPENDLISTFAILED); + } + + *pSortedList = sortedList; + +cleanup: + + PKIX_DECREF(cmpObj); + PKIX_DECREF(object); + PKIX_DECREF(sortedGreaterList); + PKIX_DECREF(sortedLessList); + PKIX_DECREF(greaterList); + PKIX_DECREF(lessList); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_BubbleSort + * DESCRIPTION: + * + * Sorts List of Objects "fromList" using "comparatorCallback"'s result as + * comasrison key and returns the sorted List at "pSortedList". The sorting + * algorithm used is bubble sort (n*n). + * + * PARAMETERS: + * "fromList" + * Address of a List of Objects to be sorted. Must be non-NULL, but may be + * empty. + * "comparatorCallback" + * Address of callback function that will compare two Objects on the List. + * It should return -1 for less, 0 for equal and 1 for greater. The + * callback implementation chooses what in Objects to be compared. Must be + * non-NULL. + * "pSortedList" + * Address of a List of Objects that shall be sorted and returned. Must be + * non-NULL, but may be empty. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "toList" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_BubbleSort( + PKIX_List *fromList, + PKIX_List_SortComparatorCallback comparator, + PKIX_List **pSortedList, + void *plContext) +{ + PKIX_List *sortedList = NULL; + PKIX_PL_Object *cmpObj = NULL; + PKIX_PL_Object *leastObj = NULL; + PKIX_Int32 cmpResult = 0; + PKIX_UInt32 size = 0; + PKIX_UInt32 i, j; + + PKIX_ENTER(BUILD, "pkix_List_BubbleSort"); + PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList); + + if (fromList->immutable) { + PKIX_ERROR(PKIX_CANNOTSORTIMMUTABLELIST); + } + PKIX_CHECK(pkix_List_Duplicate + ((PKIX_PL_Object *) fromList, + (PKIX_PL_Object **) &sortedList, + plContext), + PKIX_LISTDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(sortedList, &size, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (size > 1) { + + /* + * Move from the first of the item on the list, For each iteration, + * compare and swap the least value to the head of the comparisoning + * sub-list. + */ + for (i = 0; i < size - 1; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (sortedList, i, &leastObj, plContext), + PKIX_LISTGETITEMFAILED); + + for (j = i + 1; j < size; j++) { + PKIX_CHECK(PKIX_List_GetItem + (sortedList, j, &cmpObj, plContext), + PKIX_LISTGETITEMFAILED); + PKIX_CHECK(comparator + (leastObj, cmpObj, &cmpResult, plContext), + PKIX_COMPARATORCALLBACKFAILED); + if (cmpResult > 0) { + PKIX_CHECK(PKIX_List_SetItem + (sortedList, j, leastObj, plContext), + PKIX_LISTSETITEMFAILED); + + PKIX_DECREF(leastObj); + leastObj = cmpObj; + cmpObj = NULL; + } else { + PKIX_DECREF(cmpObj); + } + } + PKIX_CHECK(PKIX_List_SetItem + (sortedList, i, leastObj, plContext), + PKIX_LISTSETITEMFAILED); + + PKIX_DECREF(leastObj); + } + + } + + *pSortedList = sortedList; + sortedList = NULL; +cleanup: + + PKIX_DECREF(sortedList); + PKIX_DECREF(leastObj); + PKIX_DECREF(cmpObj); + + PKIX_RETURN(LIST); +} + +/* --Public-List-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_List_Create (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_Create( + PKIX_List **pList, + void *plContext) +{ + PKIX_List *list = NULL; + + PKIX_ENTER(LIST, "PKIX_List_Create"); + PKIX_NULLCHECK_ONE(pList); + + PKIX_CHECK(pkix_List_Create_Internal(PKIX_TRUE, &list, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + *pList = list; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_SetImmutable (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_SetImmutable( + PKIX_List *list, + void *plContext) +{ + PKIX_ENTER(LIST, "PKIX_List_SetImmutable"); + PKIX_NULLCHECK_ONE(list); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + list->immutable = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_IsImmutable (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_IsImmutable( + PKIX_List *list, + PKIX_Boolean *pImmutable, + void *plContext) +{ + PKIX_ENTER(LIST, "PKIX_List_IsImmutable"); + PKIX_NULLCHECK_TWO(list, pImmutable); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + *pImmutable = list->immutable; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_GetLength (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_GetLength( + PKIX_List *list, + PKIX_UInt32 *pLength, + void *plContext) +{ + PKIX_ENTER(LIST, "PKIX_List_GetLength"); + PKIX_NULLCHECK_TWO(list, pLength); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + *pLength = list->length; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_IsEmpty (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_IsEmpty( + PKIX_List *list, + PKIX_Boolean *pEmpty, + void *plContext) +{ + PKIX_UInt32 length; + + PKIX_ENTER(LIST, "PKIX_List_IsEmpty"); + PKIX_NULLCHECK_TWO(list, pEmpty); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + if (length == 0){ + *pEmpty = PKIX_TRUE; + } else { + *pEmpty = PKIX_FALSE; + } + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_AppendItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_AppendItem( + PKIX_List *list, + PKIX_PL_Object *item, + void *plContext) +{ + PKIX_List *lastElement = NULL; + PKIX_List *newElement = NULL; + PKIX_UInt32 length, i; + + PKIX_ENTER(LIST, "PKIX_List_AppendItem"); + PKIX_NULLCHECK_ONE(list); + + if (list->immutable){ + PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); + } + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + /* find last element of list and create new element there */ + + lastElement = list; + for (i = 0; i < length; i++){ + lastElement = lastElement->next; + } + + PKIX_CHECK(pkix_List_Create_Internal + (PKIX_FALSE, &newElement, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + PKIX_INCREF(item); + newElement->item = item; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)list, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + lastElement->next = newElement; + newElement = NULL; + list->length += 1; + +cleanup: + + PKIX_DECREF(newElement); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_InsertItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_InsertItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object *item, + void *plContext) +{ + PKIX_List *element = NULL; + PKIX_List *newElem = NULL; + + PKIX_ENTER(LIST, "PKIX_List_InsertItem"); + PKIX_NULLCHECK_ONE(list); + + + if (list->immutable){ + PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); + } + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + /* Create a new list object */ + PKIX_CHECK(pkix_List_Create_Internal(PKIX_FALSE, &newElem, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + if (list->length) { + PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), + PKIX_LISTGETELEMENTFAILED); + /* Copy the old element's contents into the new element */ + newElem->item = element->item; + /* Add new item to the list */ + PKIX_INCREF(item); + element->item = item; + /* Set the new element's next pointer to the old element's next */ + newElem->next = element->next; + /* Set the old element's next pointer to the new element */ + element->next = newElem; + newElem = NULL; + } else { + PKIX_INCREF(item); + newElem->item = item; + newElem->next = NULL; + list->next = newElem; + newElem = NULL; + } + list->length++; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)list, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); +cleanup: + PKIX_DECREF(newElem); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_GetItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_GetItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object **pItem, + void *plContext) +{ + PKIX_List *element = NULL; + + PKIX_ENTER(LIST, "PKIX_List_GetItem"); + PKIX_NULLCHECK_TWO(list, pItem); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), + PKIX_LISTGETELEMENTFAILED); + + PKIX_INCREF(element->item); + *pItem = element->item; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_SetItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_SetItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object *item, + void *plContext) +{ + PKIX_List *element; + + PKIX_ENTER(LIST, "PKIX_List_SetItem"); + PKIX_NULLCHECK_ONE(list); + + if (list->immutable){ + PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); + } + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), + PKIX_LISTGETELEMENTFAILED); + + /* DecRef old contents */ + PKIX_DECREF(element->item); + + /* Set New Contents */ + PKIX_INCREF(item); + element->item = item; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)list, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_DeleteItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_DeleteItem( + PKIX_List *list, + PKIX_UInt32 index, + void *plContext) +{ + PKIX_List *element = NULL; + PKIX_List *prevElement = NULL; + PKIX_List *nextElement = NULL; + + PKIX_ENTER(LIST, "PKIX_List_DeleteItem"); + PKIX_NULLCHECK_ONE(list); + + if (list->immutable){ + PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); + } + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), + PKIX_LISTGETELEMENTFAILED); + + /* DecRef old contents */ + PKIX_DECREF(element->item); + + nextElement = element->next; + + if (nextElement != NULL) { + /* If the next element exists, splice it out. */ + + /* Don't need to change ref counts for targets of next */ + element->item = nextElement->item; + nextElement->item = NULL; + + /* Don't need to change ref counts for targets of next */ + element->next = nextElement->next; + nextElement->next = NULL; + + PKIX_DECREF(nextElement); + + } else { /* The element is at the tail of the list */ + if (index != 0) { + PKIX_CHECK(pkix_List_GetElement + (list, index-1, &prevElement, plContext), + PKIX_LISTGETELEMENTFAILED); + } else if (index == 0){ /* prevElement must be header */ + prevElement = list; + } + prevElement->next = NULL; + + /* Delete the element */ + PKIX_DECREF(element); + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)list, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + list->length = list->length - 1; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_ReverseList (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_ReverseList( + PKIX_List *list, + PKIX_List **pReversedList, + void *plContext) +{ + PKIX_List *reversedList = NULL; + PKIX_PL_Object *item = NULL; + PKIX_PL_Object *duplicateItem = NULL; + PKIX_UInt32 length, i; + + PKIX_ENTER(LIST, "pkix_List_ReverseList"); + PKIX_NULLCHECK_TWO(list, pReversedList); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + /* Create a new list object */ + PKIX_CHECK(PKIX_List_Create(&reversedList, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + /* + * Starting with the last item and traversing backwards (from + * the original list), append each item to the reversed list + */ + + for (i = 1; i <= length; i++){ + PKIX_CHECK(PKIX_List_GetItem + (list, (length - i), &item, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_PL_Object_Duplicate + (item, &duplicateItem, plContext), + PKIX_LISTDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (reversedList, duplicateItem, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(item); + PKIX_DECREF(duplicateItem); + } + + *pReversedList = reversedList; + +cleanup: + + PKIX_DECREF(item); + PKIX_DECREF(duplicateItem); + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(reversedList); + } + + PKIX_RETURN(LIST); +} diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.h b/security/nss/lib/libpkix/pkix/util/pkix_list.h new file mode 100644 index 0000000000..13e104f21a --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_list.h @@ -0,0 +1,95 @@ +/* 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_list.h + * + * List Object Type Definition + * + */ + +#ifndef _PKIX_LIST_H +#define _PKIX_LIST_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef PKIX_Error * +(*PKIX_List_SortComparatorCallback)( + PKIX_PL_Object *obj1, + PKIX_PL_Object *obj2, + PKIX_Int32 *pResult, + void *plContext); + +struct PKIX_ListStruct { + PKIX_PL_Object *item; + PKIX_List *next; + PKIX_Boolean immutable; + PKIX_UInt32 length; + PKIX_Boolean isHeader; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_List_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_List_Contains( + PKIX_List *list, + PKIX_PL_Object *object, + PKIX_Boolean *pFound, + void *plContext); + +PKIX_Error * +pkix_List_Remove( + PKIX_List *list, + PKIX_PL_Object *target, + void *plContext); + +PKIX_Error * +pkix_List_MergeLists( + PKIX_List *firstList, + PKIX_List *secondList, + PKIX_List **pMergedList, + void *plContext); + +PKIX_Error * +pkix_List_AppendList( + PKIX_List *toList, + PKIX_List *fromList, + void *plContext); + +PKIX_Error * +pkix_List_AppendUnique( + PKIX_List *toList, + PKIX_List *fromList, + void *plContext); + +PKIX_Error * +pkix_List_RemoveItems( + PKIX_List *list, + PKIX_List *deleteList, + void *plContext); + +PKIX_Error * +pkix_List_QuickSort( + PKIX_List *fromList, + PKIX_List_SortComparatorCallback comparator, + PKIX_List **pSortedList, + void *plContext); + +PKIX_Error * +pkix_List_BubbleSort( + PKIX_List *fromList, + PKIX_List_SortComparatorCallback comparator, + PKIX_List **pSortedList, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_LIST_H */ diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.c b/security/nss/lib/libpkix/pkix/util/pkix_logger.c new file mode 100644 index 0000000000..10f537a319 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.c @@ -0,0 +1,1088 @@ +/* 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_logger.c + * + * Logger Object Functions + * + */ + +#include "pkix_logger.h" +#ifndef PKIX_ERROR_DESCRIPTION +#include "prprf.h" +#endif + +/* Global variable to keep PKIX_Logger List */ +PKIX_List *pkixLoggers = NULL; + +/* + * Once the Logger has been set, for any logging related operations, we have + * to go through the List to find a match, and if found, issue the + * corresponding callback. The overhead to check for DEBUG and TRACE in each + * PKIX function entering and exiting is very expensive (400X), and redundant + * if they are not the interest of the Logger. Therefore, the PKIX_Logger List + * pkixLoggers is separated into two lists based on its Loggers' trace level. + * + * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or + * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors + * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and + * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to + * pkixLoggersDebugTrace. + * + * Currently we provide five logging levels and the default setting are by: + * + * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level + * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level + * WARNING is not invoked as default + * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs + * compilation -DPKIX_<component>DEBUG flag to turn on + * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE + * level. TRACE provides duplicate information of DEBUG, but needs no + * recompilation and cannot choose component. To allow application + * to use DEBUG level, TRACE is put as last. + * + */ +PKIX_List *pkixLoggersErrors = NULL; +PKIX_List *pkixLoggersDebugTrace = NULL; + +/* To ensure atomic update on pkixLoggers lists */ +PKIX_PL_MonitorLock *pkixLoggerLock = NULL; + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_Logger_CheckErrors + * DESCRIPTION: + * + * This function goes through each PKIX_Logger at "pkixLoggersList" and + * checks if "maxLevel" and "logComponent" satisfies what is specified in the + * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and + * passes a PKIX_PL_String that is the concatenation of "message" and + * "message2" to the application for processing. + * Since this call is inserted into a handful of PKIX macros, no macros are + * applied in this function, to avoid infinite recursion. + * If an error occurs, this call is aborted. + * + * PARAMETERS: + * "pkixLoggersList" + * A list of PKIX_Loggers to be examined for invoking callback. Must be + * non-NULL. + * "message" + * Address of "message" to be logged. Must be non-NULL. + * "message2" + * Address of "message2" to be concatenated and logged. May be NULL. + * "logComponent" + * A PKIX_UInt32 that indicates the component the message is from. + * "maxLevel" + * A PKIX_UInt32 that represents the level of severity of the message. + * "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 Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_Logger_Check( + PKIX_List *pkixLoggersList, + const char *message, + const char *message2, + PKIX_ERRORCLASS logComponent, + PKIX_UInt32 currentLevel, + void *plContext) +{ + PKIX_Logger *logger = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *messageString = NULL; + PKIX_PL_String *message2String = NULL; + PKIX_PL_String *msgString = NULL; + PKIX_Error *error = NULL; + PKIX_Boolean needLogging = PKIX_FALSE; + PKIX_UInt32 i, length; + + /* + * We cannot use any the PKIX_ macros here, since this function is + * called from some of these macros. It can create infinite recursion. + */ + + if ((pkixLoggersList == NULL) || (message == NULL)) { + return(NULL); + } + + /* + * Disable all subsequent loggings to avoid recursion. The result is + * if other thread is calling this function at the same time, there + * won't be any logging because the pkixLoggersErrors and + * pkixLoggersDebugTrace are set to null. + * It would be nice if we provide control per thread (e.g. make + * plContext threadable) then we can avoid the recursion by setting + * flag at plContext. Then other thread's logging won't be affected. + * + * Also we need to use a reentrant Lock. Although we avoid recursion + * for TRACE. When there is an ERROR occurs in subsequent call, this + * function will be called. + */ + + error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext); + if (error) { return(NULL); } + + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggersDebugTrace = NULL; + savedPkixLoggersErrors = pkixLoggersErrors; + pkixLoggersErrors = NULL; + + /* Convert message and message2 to String */ + error = PKIX_PL_String_Create + (PKIX_ESCASCII, message, 0, &messageString, plContext); + if (error) { goto cleanup; } + + if (message2) { + error = PKIX_PL_String_Create + (PKIX_ESCASCII, message2, 0, &message2String, plContext); + if (error) { goto cleanup; } + error = PKIX_PL_String_Create + (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext); + if (error) { goto cleanup; } + + } else { + error = PKIX_PL_String_Create + (PKIX_ESCASCII, "%s", 0, &formatString, plContext); + if (error) { goto cleanup; } + + } + + error = PKIX_PL_Sprintf + (&msgString, + plContext, + formatString, + messageString, + message2String); + if (error) { goto cleanup; } + + /* Go through the Logger list */ + + error = PKIX_List_GetLength(pkixLoggersList, &length, plContext); + if (error) { goto cleanup; } + + for (i = 0; i < length; i++) { + + error = PKIX_List_GetItem + (pkixLoggersList, + i, + (PKIX_PL_Object **) &logger, + plContext); + if (error) { goto cleanup; } + + /* Intended logging level less or equal than the max */ + needLogging = (currentLevel <= logger->maxLevel); + + if (needLogging && (logger->callback)) { + + /* + * We separate Logger into two lists based on log level + * but log level is not modified. We need to check here to + * avoid logging the higher log level (lower value) twice. + */ + if (pkixLoggersList == pkixLoggersErrors) { + needLogging = needLogging && + (currentLevel <= PKIX_LOGGER_LEVEL_WARNING); + } else if (pkixLoggersList == pkixLoggersDebugTrace) { + needLogging = needLogging && + (currentLevel > PKIX_LOGGER_LEVEL_WARNING); + } + + if (needLogging) { + if (logComponent == logger->logComponent) { + needLogging = PKIX_TRUE; + } else { + needLogging = PKIX_FALSE; + } + } + + if (needLogging) { + error = logger->callback + (logger, + msgString, + currentLevel, + logComponent, + plContext); + if (error) { goto cleanup; } + } + } + + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)logger, plContext); + logger = NULL; + if (error) { goto cleanup; } + + } + +cleanup: + + if (formatString) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)formatString, plContext); + } + + if (messageString) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)messageString, plContext); + } + + if (message2String) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)message2String, plContext); + } + + if (msgString) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)msgString, plContext); + } + + if (logger) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)logger, plContext); + } + + if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) { + pkixLoggersErrors = savedPkixLoggersErrors; + } + + if (pkixLoggersDebugTrace == NULL && + savedPkixLoggersDebugTrace != NULL) { + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; + } + + error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext); + if (error) { return(NULL); } + + return(NULL); +} + +PKIX_Error * +pkix_Logger_CheckWithCode( + PKIX_List *pkixLoggersList, + PKIX_UInt32 errorCode, + const char *message2, + PKIX_ERRORCLASS logComponent, + PKIX_UInt32 currentLevel, + void *plContext) +{ + char error[32]; + char *errorString = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode"); +#if defined PKIX_ERROR_DESCRIPTION + errorString = PKIX_ErrorText[errorCode]; +#else + PR_snprintf(error, 32, "Error code: %d", errorCode); + errorString = error; +#endif /* PKIX_ERROR_DESCRIPTION */ + + pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString, + message2, logComponent, + currentLevel, plContext); + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_Logger *logger = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a logger */ + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), + PKIX_OBJECTNOTLOGGER); + + logger = (PKIX_Logger *)object; + + /* We have a valid logger. DecRef its item and recurse on next */ + + logger->callback = NULL; + PKIX_DECREF(logger->context); + logger->logComponent = (PKIX_ERRORCLASS)0; + +cleanup: + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_Logger *logger = NULL; + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *contextString = NULL; + PKIX_PL_String *componentString = NULL; + PKIX_PL_String *loggerString = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper"); + PKIX_NULLCHECK_TWO(object, pString); + + /* Check that this object is a logger */ + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), + PKIX_OBJECTNOTLOGGER); + + logger = (PKIX_Logger *)object; + + asciiFormat = + "[\n" + "\tLogger: \n" + "\tContext: %s\n" + "\tMaximum Level: %d\n" + "\tComponent Name: %s\n" + "]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_TOSTRING(logger->context, &contextString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (void *)PKIX_ERRORCLASSNAMES[logger->logComponent], + 0, + &componentString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&loggerString, + plContext, + formatString, + contextString, + logger->maxLevel, + componentString), + PKIX_SPRINTFFAILED); + + *pString = loggerString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(contextString); + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_Logger *firstLogger = NULL; + PKIX_Logger *secondLogger = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + /* test that first is a Logger */ + PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext), + PKIX_FIRSTOBJECTNOTLOGGER); + + /* + * Since we know first is a Logger, if both references are + * identical, they must be equal + */ + if (first == second){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If second isn't a Logger, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_LOGGER_TYPE) goto cleanup; + + firstLogger = (PKIX_Logger *)first; + secondLogger = (PKIX_Logger *)second; + + cmpResult = PKIX_FALSE; + + if (firstLogger->callback != secondLogger->callback) { + goto cleanup; + } + + if (firstLogger->logComponent != secondLogger->logComponent) { + goto cleanup; + } + + PKIX_EQUALS + (firstLogger->context, + secondLogger->context, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (cmpResult == PKIX_FALSE) { + goto cleanup; + } + + if (firstLogger->maxLevel != secondLogger->maxLevel) { + goto cleanup; + } + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_Logger *logger = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 tempHash = 0; + + PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), + PKIX_OBJECTNOTLOGGER); + + logger = (PKIX_Logger *)object; + + PKIX_HASHCODE(logger->context, &tempHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + hash = (((((PKIX_UInt32)((char *)logger->callback - (char *)NULL) + tempHash) << 7) + + logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent; + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(LOGGER); +} + + +/* + * FUNCTION: pkix_Logger_Duplicate + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_Logger *logger = NULL; + PKIX_Logger *dupLogger = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext), + PKIX_OBJECTNOTLOGGER); + + logger = (PKIX_Logger *) object; + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LOGGER_TYPE, + sizeof (PKIX_Logger), + (PKIX_PL_Object **)&dupLogger, + plContext), + PKIX_COULDNOTCREATELOGGEROBJECT); + + dupLogger->callback = logger->callback; + dupLogger->maxLevel = logger->maxLevel; + + PKIX_DUPLICATE + (logger->context, + &dupLogger->context, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + dupLogger->logComponent = logger->logComponent; + + *pNewObject = (PKIX_PL_Object *) dupLogger; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(dupLogger); + } + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_RegisterSelf + * DESCRIPTION: + * Registers PKIX_LOGGER_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_Logger_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf"); + + entry.description = "Logger"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_Logger); + entry.destructor = pkix_Logger_Destroy; + entry.equalsFunction = pkix_Logger_Equals; + entry.hashcodeFunction = pkix_Logger_Hashcode; + entry.toStringFunction = pkix_Logger_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_Logger_Duplicate; + + systemClasses[PKIX_LOGGER_TYPE] = entry; + + PKIX_RETURN(LOGGER); +} + +/* --Public-Logger-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_Create( + PKIX_Logger_LogCallback callback, + PKIX_PL_Object *loggerContext, + PKIX_Logger **pLogger, + void *plContext) +{ + PKIX_Logger *logger = NULL; + + PKIX_ENTER(LOGGER, "PKIX_Logger_Create"); + PKIX_NULLCHECK_ONE(pLogger); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LOGGER_TYPE, + sizeof (PKIX_Logger), + (PKIX_PL_Object **)&logger, + plContext), + PKIX_COULDNOTCREATELOGGEROBJECT); + + logger->callback = callback; + logger->maxLevel = 0; + logger->logComponent = (PKIX_ERRORCLASS)0; + + PKIX_INCREF(loggerContext); + logger->context = loggerContext; + + *pLogger = logger; + logger = NULL; + +cleanup: + + PKIX_DECREF(logger); + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_GetLogCallback( + PKIX_Logger *logger, + PKIX_Logger_LogCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback"); + PKIX_NULLCHECK_TWO(logger, pCallback); + + *pCallback = logger->callback; + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_GetLoggerContext( + PKIX_Logger *logger, + PKIX_PL_Object **pLoggerContext, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex"); + PKIX_NULLCHECK_TWO(logger, pLoggerContext); + + PKIX_INCREF(logger->context); + *pLoggerContext = logger->context; + +cleanup: + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_GetMaxLoggingLevel( + PKIX_Logger *logger, + PKIX_UInt32 *pLevel, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel"); + PKIX_NULLCHECK_TWO(logger, pLevel); + + *pLevel = logger->maxLevel; + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_SetMaxLoggingLevel( + PKIX_Logger *logger, + PKIX_UInt32 level, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel"); + PKIX_NULLCHECK_ONE(logger); + + if (level > PKIX_LOGGER_LEVEL_MAX) { + PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM); + } else { + logger->maxLevel = level; + } + +cleanup: + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_GetLoggingComponent( + PKIX_Logger *logger, + PKIX_ERRORCLASS *pComponent, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent"); + PKIX_NULLCHECK_TWO(logger, pComponent); + + *pComponent = logger->logComponent; + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_SetLoggingComponent( + PKIX_Logger *logger, + PKIX_ERRORCLASS component, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent"); + PKIX_NULLCHECK_ONE(logger); + + logger->logComponent = component; + + PKIX_RETURN(LOGGER); +} + + +/* + * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are + * documented as not thread-safe. However they are thread-safe now. We need + * the lock when accessing the logger lists. + */ + +/* + * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_GetLoggers( + PKIX_List **pLoggers, /* list of PKIX_Logger */ + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_Logger *logger = NULL; + PKIX_Logger *dupLogger = NULL; + PKIX_UInt32 i, length; + PKIX_Boolean locked = PKIX_FALSE; + + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers"); + PKIX_NULLCHECK_ONE(pLoggers); + + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), + PKIX_MONITORLOCKENTERFAILED); + locked = PKIX_TRUE; + + /* + * Temporarily disable DEBUG/TRACE Logging to avoid possible + * deadlock: + * When the Logger List is being accessed, e.g. by PKIX_ENTER or + * PKIX_DECREF, pkix_Logger_Check may check whether logging + * is requested, creating a deadlock situation. + */ + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggersDebugTrace = NULL; + savedPkixLoggersErrors = pkixLoggersErrors; + pkixLoggersErrors = NULL; + + if (pkixLoggers == NULL) { + length = 0; + } else { + PKIX_CHECK(PKIX_List_GetLength + (pkixLoggers, &length, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + /* Create a list and copy the pkixLoggers item to the list */ + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + + for (i = 0; i < length; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (pkixLoggers, + i, + (PKIX_PL_Object **) &logger, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_Logger_Duplicate + ((PKIX_PL_Object *)logger, + (PKIX_PL_Object **)&dupLogger, + plContext), + PKIX_LOGGERDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (list, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(logger); + PKIX_DECREF(dupLogger); + } + + /* Set the list to be immutable */ + PKIX_CHECK(PKIX_List_SetImmutable(list, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pLoggers = list; + +cleanup: + + PKIX_DECREF(logger); + + /* Restore logging capability */ + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; + pkixLoggersErrors = savedPkixLoggersErrors; + + if (locked) { + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), + PKIX_MONITORLOCKEXITFAILED); + } + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_SetLoggers( + PKIX_List *loggers, /* list of PKIX_Logger */ + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + PKIX_Logger *logger = NULL; + PKIX_Logger *dupLogger = NULL; + PKIX_Boolean locked = PKIX_FALSE; + PKIX_UInt32 i, length; + + PKIX_ENTER(LOGGER, "PKIX_SetLoggers"); + + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), + PKIX_MONITORLOCKENTERFAILED); + locked = PKIX_TRUE; + + /* Disable tracing, etc. to avoid recursion and deadlock */ + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggersDebugTrace = NULL; + savedPkixLoggersErrors = pkixLoggersErrors; + pkixLoggersErrors = NULL; + + /* discard any prior loggers */ + PKIX_DECREF(pkixLoggers); + PKIX_DECREF(savedPkixLoggersErrors); + PKIX_DECREF(savedPkixLoggersDebugTrace); + + if (loggers != NULL) { + + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < length; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (loggers, + i, + (PKIX_PL_Object **) &logger, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_Logger_Duplicate + ((PKIX_PL_Object *)logger, + (PKIX_PL_Object **)&dupLogger, + plContext), + PKIX_LOGGERDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (list, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + /* Make two lists */ + + /* Put in pkixLoggersErrors in any case*/ + + if (savedPkixLoggersErrors == NULL) { + + PKIX_CHECK(PKIX_List_Create + (&savedPkixLoggersErrors, + plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (savedPkixLoggersErrors, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { + + /* Put in pkixLoggersDebugTrace */ + + if (savedPkixLoggersDebugTrace == NULL) { + + PKIX_CHECK(PKIX_List_Create + (&savedPkixLoggersDebugTrace, + plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (savedPkixLoggersDebugTrace, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + PKIX_DECREF(logger); + PKIX_DECREF(dupLogger); + + } + + pkixLoggers = list; + } + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(list); + PKIX_DECREF(savedPkixLoggersErrors); + PKIX_DECREF(savedPkixLoggersDebugTrace); + pkixLoggers = NULL; + } + + PKIX_DECREF(logger); + + /* Reenable logging capability with new lists */ + pkixLoggersErrors = savedPkixLoggersErrors; + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; + + if (locked) { + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), + PKIX_MONITORLOCKEXITFAILED); + } + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_AddLogger( + PKIX_Logger *logger, + void *plContext) +{ + PKIX_Logger *dupLogger = NULL; + PKIX_Logger *addLogger = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + PKIX_Boolean locked = PKIX_FALSE; + PKIX_UInt32 i, length; + + PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger"); + PKIX_NULLCHECK_ONE(logger); + + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), + PKIX_MONITORLOCKENTERFAILED); + locked = PKIX_TRUE; + + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggersDebugTrace = NULL; + savedPkixLoggersErrors = pkixLoggersErrors; + pkixLoggersErrors = NULL; + + PKIX_DECREF(savedPkixLoggersErrors); + PKIX_DECREF(savedPkixLoggersDebugTrace); + + if (pkixLoggers == NULL) { + + PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(pkix_Logger_Duplicate + ((PKIX_PL_Object *)logger, + (PKIX_PL_Object **)&dupLogger, + plContext), + PKIX_LOGGERDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (pkixLoggers, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext), + PKIX_LISTGETLENGTHFAILED); + + /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */ + for (i = 0; i < length; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (pkixLoggers, + i, + (PKIX_PL_Object **) &addLogger, + plContext), + PKIX_LISTGETITEMFAILED); + + + /* Put in pkixLoggersErrors */ + + if (savedPkixLoggersErrors == NULL) { + + PKIX_CHECK(PKIX_List_Create + (&savedPkixLoggersErrors, + plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (savedPkixLoggersErrors, + (PKIX_PL_Object *) addLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { + + /* Put in pkixLoggersDebugTrace */ + + if (savedPkixLoggersDebugTrace == NULL) { + + PKIX_CHECK(PKIX_List_Create + (&savedPkixLoggersDebugTrace, + plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (savedPkixLoggersDebugTrace, + (PKIX_PL_Object *) addLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + PKIX_DECREF(addLogger); + + } + +cleanup: + + PKIX_DECREF(dupLogger); + PKIX_DECREF(addLogger); + + /* Restore logging capability */ + pkixLoggersErrors = savedPkixLoggersErrors; + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; + + if (locked) { + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), + PKIX_MONITORLOCKEXITFAILED); + } + + PKIX_RETURN(LOGGER); +} diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.h b/security/nss/lib/libpkix/pkix/util/pkix_logger.h new file mode 100644 index 0000000000..9411aed2e2 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.h @@ -0,0 +1,57 @@ +/* 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_logger.h + * + * Logger Object Type Definition + * + */ + +#ifndef _PKIX_LOGGER_H +#define _PKIX_LOGGER_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern PKIX_List *pkixLoggers; +extern PKIX_List *pkixLoggersErrors; +extern PKIX_List *pkixLoggersDebugTrace; + +struct PKIX_LoggerStruct { + PKIX_Logger_LogCallback callback; + PKIX_PL_Object *context; + PKIX_UInt32 maxLevel; + PKIX_ERRORCLASS logComponent; +}; + +PKIX_Error * +pkix_Logger_Check( + PKIX_List *pkixLoggersList, + const char *message, + const char *message2, + PKIX_ERRORCLASS logComponent, + PKIX_UInt32 maxLevel, + void *plContext); + +PKIX_Error * +pkix_Logger_CheckWithCode( + PKIX_List *pkixLoggersList, + PKIX_UInt32 errorCode, + const char *message2, + PKIX_ERRORCLASS logComponent, + PKIX_UInt32 maxLevel, + void *plContext); + +/* see source file for function documentation */ + +PKIX_Error *pkix_Logger_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_LOGGER_H */ diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.c b/security/nss/lib/libpkix/pkix/util/pkix_tools.c new file mode 100644 index 0000000000..4c01f8da14 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.c @@ -0,0 +1,1525 @@ +/* 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_tools.c + * + * Private Utility Functions + * + */ + +#include "pkix_tools.h" + +#define CACHE_ITEM_PERIOD_SECONDS (3600) /* one hour */ + +/* + * This cahce period is only for CertCache. A Cert from a trusted CertStore + * should be checked more frequently for update new arrival, etc. + */ +#define CACHE_TRUST_ITEM_PERIOD_SECONDS (CACHE_ITEM_PERIOD_SECONDS/10) + +extern PKIX_PL_HashTable *cachedCertChainTable; +extern PKIX_PL_HashTable *cachedCertTable; +extern PKIX_PL_HashTable *cachedCrlEntryTable; + +/* Following variables are used to checked cache hits - can be taken out */ +extern int pkix_ccAddCount; +extern int pkix_ccLookupCount; +extern int pkix_ccRemoveCount; +extern int pkix_cAddCount; +extern int pkix_cLookupCount; +extern int pkix_cRemoveCount; +extern int pkix_ceAddCount; +extern int pkix_ceLookupCount; + +#ifdef PKIX_OBJECT_LEAK_TEST +/* Following variables are used for object leak test */ +char *nonNullValue = "Non Empty Value"; +PKIX_Boolean noErrorState = PKIX_TRUE; +PKIX_Boolean runningLeakTest; +PKIX_Boolean errorGenerated; +PKIX_UInt32 stackPosition; +PKIX_UInt32 *fnStackInvCountArr; +char **fnStackNameArr; +PLHashTable *fnInvTable; +PKIX_UInt32 testStartFnStackPosition; +char *errorFnStackString; +#endif /* PKIX_OBJECT_LEAK_TEST */ + +/* --Private-Functions-------------------------------------------- */ + +#ifdef PKIX_OBJECT_LEAK_TEST +/* + * FUNCTION: pkix_ErrorGen_Hash + * DESCRIPTION: + * + * Hash function to be used in object leak test hash table. + * + */ +PLHashNumber PR_CALLBACK +pkix_ErrorGen_Hash (const void *key) +{ + char *str = NULL; + PLHashNumber rv = (*(PRUint8*)key) << 5; + PRUint32 i, counter = 0; + PRUint8 *rvc = (PRUint8 *)&rv; + + while ((str = fnStackNameArr[counter++]) != NULL) { + PRUint32 len = strlen(str); + for( i = 0; i < len; i++ ) { + rvc[ i % sizeof(rv) ] ^= *str; + str++; + } + } + + return rv; +} + +#endif /* PKIX_OBJECT_LEAK_TEST */ + +/* + * FUNCTION: pkix_IsCertSelfIssued + * DESCRIPTION: + * + * Checks whether the Cert pointed to by "cert" is self-issued and stores the + * Boolean result at "pSelfIssued". A Cert is considered self-issued if the + * Cert's issuer matches the Cert's subject. If the subject or issuer is + * not specified, a PKIX_FALSE is returned. + * + * PARAMETERS: + * "cert" + * Address of Cert used to determine whether Cert is self-issued. + * Must be non-NULL. + * "pSelfIssued" + * Address where Boolean 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 Cert 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_IsCertSelfIssued( + PKIX_PL_Cert *cert, + PKIX_Boolean *pSelfIssued, + void *plContext) +{ + PKIX_PL_X500Name *subject = NULL; + PKIX_PL_X500Name *issuer = NULL; + + PKIX_ENTER(CERT, "pkix_IsCertSelfIssued"); + PKIX_NULLCHECK_TWO(cert, pSelfIssued); + + PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext), + PKIX_CERTGETSUBJECTFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext), + PKIX_CERTGETISSUERFAILED); + + if (subject == NULL || issuer == NULL) { + *pSelfIssued = PKIX_FALSE; + } else { + + PKIX_CHECK(PKIX_PL_X500Name_Match + (subject, issuer, pSelfIssued, plContext), + PKIX_X500NAMEMATCHFAILED); + } + +cleanup: + PKIX_DECREF(subject); + PKIX_DECREF(issuer); + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_Throw + * DESCRIPTION: + * + * Creates an Error using the value of "errorCode", the character array + * pointed to by "funcName", the character array pointed to by "errorText", + * and the Error pointed to by "cause" (if any), and stores it at "pError". + * + * If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR", + * then there is no point creating a new Error object. Rather, we simply + * store "cause" at "pError". + * + * PARAMETERS: + * "errorCode" + * Value of error code. + * "funcName" + * Address of EscASCII array representing name of function throwing error. + * Must be non-NULL. + * "errnum" + * PKIX_ERRMSGNUM of error description for new error. + * "cause" + * Address of Error representing error's cause. + * "pError" + * 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 an Error 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_Throw( + PKIX_ERRORCLASS errorClass, + const char *funcName, + PKIX_ERRORCODE errorCode, + PKIX_ERRORCLASS overrideClass, + PKIX_Error *cause, + PKIX_Error **pError, + void *plContext) +{ + PKIX_Error *error = NULL; + + PKIX_ENTER(ERROR, "pkix_Throw"); + PKIX_NULLCHECK_TWO(funcName, pError); + + *pError = NULL; + +#ifdef PKIX_OBJECT_LEAK_TEST + noErrorState = PKIX_TRUE; + if (pkixLog) { +#ifdef PKIX_ERROR_DESCRIPTION + PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n", + funcName, PKIX_ErrorText[errorCode], + (cause ? PKIX_ErrorText[cause->errCode] : "null"))); +#else + PR_LOG(pkixLog, 4, ("Error in function \"%s\": error code \"%d\"\n", + funcName, errorCode)); +#endif /* PKIX_ERROR_DESCRIPTION */ + PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef")); + } +#endif /* PKIX_OBJECT_LEAK_TEST */ + + /* if cause has error class of PKIX_FATAL_ERROR, return immediately */ + if (cause) { + if (cause->errClass == PKIX_FATAL_ERROR){ + PKIX_INCREF(cause); + *pError = cause; + goto cleanup; + } + } + + if (overrideClass == PKIX_FATAL_ERROR){ + errorClass = overrideClass; + } + + pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL, + errorCode, &error, plContext); + + if (!pkixTempResult) { + /* Setting plErr error code: + * get it from PORT_GetError if it is a leaf error and + * default error code does not exist(eq 0) */ + if (!cause && !error->plErr) { + error->plErr = PKIX_PL_GetPLErrorCode(); + } + } + + *pError = error; + +cleanup: + + PKIX_DEBUG_EXIT(ERROR); + pkixErrorClass = 0; +#ifdef PKIX_OBJECT_LEAK_TEST + noErrorState = PKIX_FALSE; + + if (runningLeakTest && fnStackNameArr) { + PR_LOG(pkixLog, 5, + ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), + stackPosition, " ", fnStackNameArr[stackPosition], + stackPosition, myFuncName)); + fnStackNameArr[stackPosition--] = NULL; + } +#endif /* PKIX_OBJECT_LEAK_TEST */ + return (pkixTempResult); +} + +/* + * FUNCTION: pkix_CheckTypes + * DESCRIPTION: + * + * Checks that the types of the Object pointed to by "first" and the Object + * pointed to by "second" are both equal to the value of "type". If they + * are not equal, a PKIX_Error is returned. + * + * PARAMETERS: + * "first" + * Address of first Object. Must be non-NULL. + * "second" + * Address of second Object. Must be non-NULL. + * "type" + * Value of type to check against. + * "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 an Error 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_CheckTypes( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_UInt32 type, + void *plContext) +{ + PKIX_UInt32 firstType, secondType; + + PKIX_ENTER(OBJECT, "pkix_CheckTypes"); + PKIX_NULLCHECK_TWO(first, second); + + PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext), + PKIX_COULDNOTGETFIRSTOBJECTTYPE); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETSECONDOBJECTTYPE); + + if ((firstType != type)||(firstType != secondType)) { + PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH); + } + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_CheckType + * DESCRIPTION: + * + * Checks that the type of the Object pointed to by "object" is equal to the + * value of "type". If it is not equal, a PKIX_Error is returned. + * + * PARAMETERS: + * "object" + * Address of Object. Must be non-NULL. + * "type" + * Value of type to check against. + * "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 an Error 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_CheckType( + PKIX_PL_Object *object, + PKIX_UInt32 type, + void *plContext) +{ + return (pkix_CheckTypes(object, object, type, plContext)); +} + +/* + * FUNCTION: pkix_hash + * DESCRIPTION: + * + * Computes a hash value for "length" bytes starting at the array of bytes + * pointed to by "bytes" and stores the result at "pHash". + * + * XXX To speed this up, we could probably read 32 bits at a time from + * bytes (maybe even 64 bits on some platforms) + * + * PARAMETERS: + * "bytes" + * Address of array of bytes to hash. Must be non-NULL. + * "length" + * Number of bytes to hash. + * "pHash" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_hash( + const unsigned char *bytes, + PKIX_UInt32 length, + PKIX_UInt32 *pHash, + void *plContext) +{ + PKIX_UInt32 i; + PKIX_UInt32 hash; + + PKIX_ENTER(OBJECT, "pkix_hash"); + if (length != 0) { + PKIX_NULLCHECK_ONE(bytes); + } + PKIX_NULLCHECK_ONE(pHash); + + hash = 0; + for (i = 0; i < length; i++) { + /* hash = 31 * hash + bytes[i]; */ + hash = (hash << 5) - hash + bytes[i]; + } + + *pHash = hash; + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_countArray + * DESCRIPTION: + * + * Counts the number of elements in the null-terminated array of pointers + * pointed to by "array" and returns the result. + * + * PARAMETERS + * "array" + * Address of null-terminated array of pointers. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns the number of elements in the array. + */ +PKIX_UInt32 +pkix_countArray(void **array) +{ + PKIX_UInt32 count = 0; + + if (array) { + while (*array++) { + count++; + } + } + return (count); +} + +/* + * FUNCTION: pkix_duplicateImmutable + * DESCRIPTION: + * + * Convenience callback function used for duplicating immutable objects. + * Since the objects can not be modified, this function simply increments the + * reference count on the object, and returns a reference to that object. + * + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +PKIX_Error * +pkix_duplicateImmutable( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_ENTER(OBJECT, "pkix_duplicateImmutable"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_INCREF(object); + + *pNewObject = object; + +cleanup: + PKIX_RETURN(OBJECT); +} + +/* --String-Encoding-Conversion-Functions------------------------ */ + +/* + * FUNCTION: pkix_hex2i + * DESCRIPTION: + * + * Converts hexadecimal character "c" to its integer value and returns result. + * + * PARAMETERS + * "c" + * Character to convert to a hex value. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF). + */ +PKIX_UInt32 +pkix_hex2i(char c) +{ + if ((c >= '0')&&(c <= '9')) + return (c-'0'); + else if ((c >= 'a')&&(c <= 'f')) + return (c-'a'+10); + else if ((c >= 'A')&&(c <= 'F')) + return (c-'A'+10); + else + return ((PKIX_UInt32)(-1)); +} + +/* + * FUNCTION: pkix_i2hex + * DESCRIPTION: + * + * Converts integer value "digit" to its ASCII hex value + * + * PARAMETERS + * "digit" + * Value of integer to convert to ASCII hex value. Must be 0-15. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * The ASCII hexadecimal value of "digit". + */ +char +pkix_i2hex(char digit) +{ + if ((digit >= 0)&&(digit <= 9)) + return (digit+'0'); + else if ((digit >= 0xa)&&(digit <= 0xf)) + return (digit - 10 + 'a'); + else + return (-1); +} + +/* + * FUNCTION: pkix_isPlaintext + * DESCRIPTION: + * + * Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug + * depending on the value of "debug". + * + * In EscASCII, [01, 7E] except '&' are plaintext. + * In EscASCII_Debug [20, 7E] except '&' are plaintext. + * + * PARAMETERS: + * "c" + * Character to check. + * "debug" + * Value of debug flag. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * True if "c" is plaintext. + */ +PKIX_Boolean +pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) { + return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20))); +} + +/* --Cache-Functions------------------------ */ + +/* + * FUNCTION: pkix_CacheCertChain_Lookup + * DESCRIPTION: + * + * Look up CertChain Hash Table for a cached BuildResult based on "targetCert" + * and "anchors" as the hash keys. If there is no item to match the key, + * PKIX_FALSE is stored at "pFound". If an item is found, its cache time is + * compared to "testDate". If expired, the item is removed and PKIX_FALSE is + * stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the + * BuildResult is stored at "pBuildResult". + * The hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "targetCert" + * Address of Target Cert as key to retrieve this CertChain. Must be + * non-NULL. + * "anchors" + * Address of PKIX_List of "anchors" is used as key to retrive CertChain. + * Must be non-NULL. + * "testDate" + * Address of PKIX_PL_Date for verifying time validity and cache validity. + * May be NULL. If testDate is NULL, this cache item will not be out-dated. + * "pFound" + * Address of PKIX_Boolean indicating valid data is found. + * Must be non-NULL. + * "pBuildResult" + * Address where BuildResult 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 an Error 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_CacheCertChain_Lookup( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + PKIX_PL_Date *testDate, + PKIX_Boolean *pFound, + PKIX_BuildResult **pBuildResult, + void *plContext) +{ + PKIX_List *cachedValues = NULL; + PKIX_List *cachedKeys = NULL; + PKIX_Error *cachedCertChainError = NULL; + PKIX_PL_Date *cacheValidUntilDate = NULL; + PKIX_PL_Date *validityDate = NULL; + PKIX_Int32 cmpValidTimeResult = 0; + PKIX_Int32 cmpCacheTimeResult = 0; + + PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup"); + + PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult); + + *pFound = PKIX_FALSE; + + /* use trust anchors and target cert as hash key */ + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)targetCert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)anchors, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCertChainError = PKIX_PL_HashTable_Lookup + (cachedCertChainTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object **) &cachedValues, + plContext); + + pkix_ccLookupCount++; + + /* retrieve data from hashed value list */ + + if (cachedValues != NULL && cachedCertChainError == NULL) { + + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 0, + (PKIX_PL_Object **) &cacheValidUntilDate, + plContext), + PKIX_LISTGETITEMFAILED); + + /* check validity time and cache age time */ + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 1, + (PKIX_PL_Object **) &validityDate, + plContext), + PKIX_LISTGETITEMFAILED); + + /* if testDate is not set, this cache item is not out-dated */ + if (testDate) { + + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)testDate, + (PKIX_PL_Object *)cacheValidUntilDate, + &cmpCacheTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)testDate, + (PKIX_PL_Object *)validityDate, + &cmpValidTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + } + + /* certs' date are all valid and cache item is not old */ + if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) { + + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 2, + (PKIX_PL_Object **) pBuildResult, + plContext), + PKIX_LISTGETITEMFAILED); + + *pFound = PKIX_TRUE; + + } else { + + pkix_ccRemoveCount++; + *pFound = PKIX_FALSE; + + /* out-dated item, remove it from cache */ + PKIX_CHECK(PKIX_PL_HashTable_Remove + (cachedCertChainTable, + (PKIX_PL_Object *) cachedKeys, + plContext), + PKIX_HASHTABLEREMOVEFAILED); + } + } + +cleanup: + + PKIX_DECREF(cachedValues); + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedCertChainError); + PKIX_DECREF(cacheValidUntilDate); + PKIX_DECREF(validityDate); + + PKIX_RETURN(BUILD); + +} + +/* + * FUNCTION: pkix_CacheCertChain_Remove + * DESCRIPTION: + * + * Remove CertChain Hash Table entry based on "targetCert" and "anchors" + * as the hash keys. If there is no item to match the key, no action is + * taken. + * The hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "targetCert" + * Address of Target Cert as key to retrieve this CertChain. Must be + * non-NULL. + * "anchors" + * Address of PKIX_List of "anchors" is used as key to retrive CertChain. + * 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 an Error 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_CacheCertChain_Remove( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + void *plContext) +{ + PKIX_List *cachedKeys = NULL; + + PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove"); + PKIX_NULLCHECK_TWO(targetCert, anchors); + + /* use trust anchors and target cert as hash key */ + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)targetCert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)anchors, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove + (cachedCertChainTable, + (PKIX_PL_Object *) cachedKeys, + plContext), + PKIX_HASHTABLEREMOVEFAILED); + + pkix_ccRemoveCount++; + +cleanup: + + PKIX_DECREF(cachedKeys); + + PKIX_RETURN(BUILD); + +} + +/* + * FUNCTION: pkix_CacheCertChain_Add + * DESCRIPTION: + * + * Add a BuildResult to the CertChain Hash Table for a "buildResult" with + * "targetCert" and "anchors" as the hash keys. + * "validityDate" is the most restricted notAfter date of all Certs in + * this CertChain and is verified when this BuildChain is retrieved. + * The hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "targetCert" + * Address of Target Cert as key to retrieve this CertChain. Must be + * non-NULL. + * "anchors" + * Address of PKIX_List of "anchors" is used as key to retrive CertChain. + * Must be non-NULL. + * "validityDate" + * Address of PKIX_PL_Date contains the most restriced notAfter time of + * all "certs". Must be non-NULL. + * Address of PKIX_Boolean indicating valid data is found. + * Must be non-NULL. + * "buildResult" + * Address of BuildResult to be cached. 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 an Error 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_CacheCertChain_Add( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + PKIX_PL_Date *validityDate, + PKIX_BuildResult *buildResult, + void *plContext) +{ + PKIX_List *cachedValues = NULL; + PKIX_List *cachedKeys = NULL; + PKIX_Error *cachedCertChainError = NULL; + PKIX_PL_Date *cacheValidUntilDate = NULL; + + PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add"); + + PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult); + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)targetCert, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)anchors, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds + (CACHE_ITEM_PERIOD_SECONDS, + &cacheValidUntilDate, + plContext), + PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, + (PKIX_PL_Object *)cacheValidUntilDate, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, (PKIX_PL_Object *)validityDate, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, (PKIX_PL_Object *)buildResult, plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCertChainError = PKIX_PL_HashTable_Add + (cachedCertChainTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object *) cachedValues, + plContext); + + pkix_ccAddCount++; + + if (cachedCertChainError != NULL) { + PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: " + "entry existed\n"); + } + +cleanup: + + PKIX_DECREF(cachedValues); + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedCertChainError); + PKIX_DECREF(cacheValidUntilDate); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_CacheCert_Lookup + * DESCRIPTION: + * + * Look up Cert Hash Table for a cached item based on "store" and Subject in + * "certSelParams" as the hash keys and returns values Certs in "pCerts". + * If there isn't an item to match the key, a PKIX_FALSE is returned at + * "pFound". The item's cache time is verified with "testDate". If out-dated, + * this item is removed and PKIX_FALSE is returned at "pFound". + * This hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * If the CertStore this Cert is from is a trusted one, the cache period is + * shorter so cache can be updated more frequently. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "store" + * Address of CertStore as key to retrieve this CertChain. Must be + * non-NULL. + * "certSelParams" + * Address of ComCertSelParams that its subject is used as key to retrieve + * this CertChain. Must be non-NULL. + * "testDate" + * Address of PKIX_PL_Date for verifying time cache validity. + * Must be non-NULL. If testDate is NULL, this cache item won't be out + * dated. + * "pFound" + * Address of KPKIX_Boolean indicating valid data is found. + * Must be non-NULL. + * "pCerts" + * Address PKIX_List where the CertChain will be stored. Must be no-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 an Error 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_CacheCert_Lookup( + PKIX_CertStore *store, + PKIX_ComCertSelParams *certSelParams, + PKIX_PL_Date *testDate, + PKIX_Boolean *pFound, + PKIX_List** pCerts, + void *plContext) +{ + PKIX_PL_Cert *cert = NULL; + PKIX_List *cachedKeys = NULL; + PKIX_List *cachedValues = NULL; + PKIX_List *cachedCertList = NULL; + PKIX_List *selCertList = NULL; + PKIX_PL_X500Name *subject = NULL; + PKIX_PL_Date *invalidAfterDate = NULL; + PKIX_PL_Date *cacheValidUntilDate = NULL; + PKIX_CertSelector *certSel = NULL; + PKIX_Error *cachedCertError = NULL; + PKIX_Error *selectorError = NULL; + PKIX_CertSelector_MatchCallback selectorMatch = NULL; + PKIX_Int32 cmpValidTimeResult = PKIX_FALSE; + PKIX_Int32 cmpCacheTimeResult = 0; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup"); + PKIX_NULLCHECK_TWO(store, certSelParams); + PKIX_NULLCHECK_TWO(pFound, pCerts); + + *pFound = PKIX_FALSE; + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubject + (certSelParams, &subject, plContext), + PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); + + PKIX_NULLCHECK_ONE(subject); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)subject, plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCertError = PKIX_PL_HashTable_Lookup + (cachedCertTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object **) &cachedValues, + plContext); + pkix_cLookupCount++; + + if (cachedValues != NULL && cachedCertError == NULL) { + + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 0, + (PKIX_PL_Object **) &cacheValidUntilDate, + plContext), + PKIX_LISTGETITEMFAILED); + + if (testDate) { + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)testDate, + (PKIX_PL_Object *)cacheValidUntilDate, + &cmpCacheTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + } + + if (cmpCacheTimeResult <= 0) { + + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 1, + (PKIX_PL_Object **) &cachedCertList, + plContext), + PKIX_LISTGETITEMFAILED); + + /* + * Certs put on cache satifies only for Subject, + * user selector and ComCertSelParams to filter. + */ + PKIX_CHECK(PKIX_CertSelector_Create + (NULL, NULL, &certSel, plContext), + PKIX_CERTSELECTORCREATEFAILED); + + PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams + (certSel, certSelParams, plContext), + PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); + + PKIX_CHECK(PKIX_CertSelector_GetMatchCallback + (certSel, &selectorMatch, plContext), + PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); + + PKIX_CHECK(PKIX_List_Create(&selCertList, plContext), + PKIX_LISTCREATEFAILED); + + /* + * If any of the Cert on the list is out-dated, invalidate + * this cache item. + */ + PKIX_CHECK(PKIX_List_GetLength + (cachedCertList, &numItems, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numItems; i++){ + + PKIX_CHECK(PKIX_List_GetItem + (cachedCertList, + i, + (PKIX_PL_Object **)&cert, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter + (cert, &invalidAfterDate, plContext), + PKIX_CERTGETVALIDITYNOTAFTERFAILED); + + if (testDate) { + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)invalidAfterDate, + (PKIX_PL_Object *)testDate, + &cmpValidTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + } + + if (cmpValidTimeResult < 0) { + + pkix_cRemoveCount++; + *pFound = PKIX_FALSE; + + /* one cert is out-dated, remove item from cache */ + PKIX_CHECK(PKIX_PL_HashTable_Remove + (cachedCertTable, + (PKIX_PL_Object *) cachedKeys, + plContext), + PKIX_HASHTABLEREMOVEFAILED); + goto cleanup; + } + + selectorError = selectorMatch(certSel, cert, plContext); + if (!selectorError){ + /* put on the return list */ + PKIX_CHECK(PKIX_List_AppendItem + (selCertList, + (PKIX_PL_Object *)cert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + *pFound = PKIX_TRUE; + } else { + PKIX_DECREF(selectorError); + } + + PKIX_DECREF(cert); + PKIX_DECREF(invalidAfterDate); + + } + + if (*pFound) { + PKIX_INCREF(selCertList); + *pCerts = selCertList; + } + + } else { + + pkix_cRemoveCount++; + *pFound = PKIX_FALSE; + /* cache item is out-dated, remove it from cache */ + PKIX_CHECK(PKIX_PL_HashTable_Remove + (cachedCertTable, + (PKIX_PL_Object *) cachedKeys, + plContext), + PKIX_HASHTABLEREMOVEFAILED); + } + + } + +cleanup: + + PKIX_DECREF(subject); + PKIX_DECREF(certSel); + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedValues); + PKIX_DECREF(cacheValidUntilDate); + PKIX_DECREF(cert); + PKIX_DECREF(cachedCertList); + PKIX_DECREF(selCertList); + PKIX_DECREF(invalidAfterDate); + PKIX_DECREF(cachedCertError); + PKIX_DECREF(selectorError); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_CacheCert_Add + * DESCRIPTION: + * + * Add Cert Hash Table for a cached item based on "store" and Subject in + * "certSelParams" as the hash keys and have "certs" as the key value. + * This hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * If the CertStore this Cert is from is a trusted one, the cache period is + * shorter so cache can be updated more frequently. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "store" + * Address of CertStore as key to retrieve this CertChain. Must be + * non-NULL. + * "certSelParams" + * Address of ComCertSelParams that its subject is used as key to retrieve + * this CertChain. Must be non-NULL. + * "certs" + * Address PKIX_List of Certs will be stored. Must be no-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 an Error 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_CacheCert_Add( + PKIX_CertStore *store, + PKIX_ComCertSelParams *certSelParams, + PKIX_List* certs, + void *plContext) +{ + PKIX_List *cachedKeys = NULL; + PKIX_List *cachedValues = NULL; + PKIX_List *cachedCerts = NULL; + PKIX_PL_Date *cacheValidUntilDate = NULL; + PKIX_PL_X500Name *subject = NULL; + PKIX_Error *cachedCertError = NULL; + PKIX_CertStore_CheckTrustCallback trustCallback = NULL; + PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS; + PKIX_UInt32 numCerts = 0; + + PKIX_ENTER(BUILD, "pkix_CacheCert_Add"); + PKIX_NULLCHECK_THREE(store, certSelParams, certs); + + PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts, + plContext), + PKIX_LISTGETLENGTHFAILED); + if (numCerts == 0) { + /* Don't want to add an empty list. */ + goto cleanup; + } + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubject + (certSelParams, &subject, plContext), + PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); + + PKIX_NULLCHECK_ONE(subject); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)subject, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_CertStore_GetTrustCallback + (store, &trustCallback, plContext), + PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); + + if (trustCallback) { + cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS; + } + + PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds + (cachePeriod, &cacheValidUntilDate, plContext), + PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, + (PKIX_PL_Object *)cacheValidUntilDate, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DUPLICATE(certs, &cachedCerts, plContext, + PKIX_OBJECTDUPLICATELISTFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, + (PKIX_PL_Object *)cachedCerts, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCertError = PKIX_PL_HashTable_Add + (cachedCertTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object *) cachedValues, + plContext); + + pkix_cAddCount++; + + if (cachedCertError != NULL) { + PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: " + "entry existed\n"); + } + +cleanup: + + PKIX_DECREF(subject); + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedValues); + PKIX_DECREF(cachedCerts); + PKIX_DECREF(cacheValidUntilDate); + PKIX_DECREF(cachedCertError); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_CacheCrlEntry_Lookup + * DESCRIPTION: + * + * Look up CrlEntry Hash Table for a cached item based on "store", + * "certIssuer" and "certSerialNumber" as the hash keys and returns values + * "pCrls". If there isn't an item to match the key, a PKIX_FALSE is + * returned at "pFound". + * This hashtable is maintained in the following way: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * + * PARAMETERS: + * "store" + * Address of CertStore as key to retrieve this CertChain. Must be + * non-NULL. + * "certIssuer" + * Address of X500Name that is used as key to retrieve the CRLEntries. + * Must be non-NULL. + * "certSerialNumber" + * Address of BigInt that is used as key to retrieve the CRLEntries. + * Must be non-NULL. + * "pFound" + * Address of KPKIX_Boolean indicating valid data is found. + * Must be non-NULL. + * "pCrls" + * Address PKIX_List where the CRLEntry will be stored. Must be no-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 an Error 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_CacheCrlEntry_Lookup( + PKIX_CertStore *store, + PKIX_PL_X500Name *certIssuer, + PKIX_PL_BigInt *certSerialNumber, + PKIX_Boolean *pFound, + PKIX_List** pCrls, + void *plContext) +{ + PKIX_List *cachedKeys = NULL; + PKIX_List *cachedCrlEntryList = NULL; + PKIX_Error *cachedCrlEntryError = NULL; + + PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup"); + PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber); + PKIX_NULLCHECK_TWO(pFound, pCrls); + + *pFound = PKIX_FALSE; + + /* Find CrlEntry(s) by issuer and serial number */ + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)certSerialNumber, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCrlEntryError = PKIX_PL_HashTable_Lookup + (cachedCrlEntryTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object **) &cachedCrlEntryList, + plContext); + pkix_ceLookupCount++; + + /* + * We don't need check Date to invalidate this cache item, + * the item is uniquely defined and won't be reverted. Let + * the FIFO for cleaning up. + */ + + if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) { + + PKIX_INCREF(cachedCrlEntryList); + *pCrls = cachedCrlEntryList; + + *pFound = PKIX_TRUE; + + } else { + + *pFound = PKIX_FALSE; + } + +cleanup: + + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedCrlEntryList); + PKIX_DECREF(cachedCrlEntryError); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_CacheCrlEntry_Add + * DESCRIPTION: + * + * Look up CrlEntry Hash Table for a cached item based on "store", + * "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as + * the hash value. If there isn't an item to match the key, a PKIX_FALSE is + * returned at "pFound". + * This hashtable is maintained in the following way: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * + * PARAMETERS: + * "store" + * Address of CertStore as key to retrieve this CertChain. Must be + * non-NULL. + * "certIssuer" + * Address of X500Name that is used as key to retrieve the CRLEntries. + * Must be non-NULL. + * "certSerialNumber" + * Address of BigInt that is used as key to retrieve the CRLEntries. + * Must be non-NULL. + * "crls" + * Address PKIX_List where the CRLEntry is stored. Must be no-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 an Error 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_CacheCrlEntry_Add( + PKIX_CertStore *store, + PKIX_PL_X500Name *certIssuer, + PKIX_PL_BigInt *certSerialNumber, + PKIX_List* crls, + void *plContext) +{ + PKIX_List *cachedKeys = NULL; + PKIX_Error *cachedCrlEntryError = NULL; + + PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add"); + PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber); + PKIX_NULLCHECK_ONE(crls); + + /* Add CrlEntry(s) by issuer and serial number */ + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)certSerialNumber, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCrlEntryError = PKIX_PL_HashTable_Add + (cachedCrlEntryTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object *) crls, + plContext); + pkix_ceAddCount++; + +cleanup: + + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedCrlEntryError); + + PKIX_RETURN(BUILD); +} + +#ifdef PKIX_OBJECT_LEAK_TEST + +/* TEST_START_FN and testStartFnStackPosition define at what state + * of the stack the object leak testing should begin. The condition + * in pkix_CheckForGeneratedError works the following way: do leak + * testing if at position testStartFnStackPosition in stack array + * (fnStackNameArr) we have called function TEST_START_FN. + * Note, that stack array get filled only when executing libpkix + * functions. + * */ +#define TEST_START_FN "PKIX_BuildChain" + +PKIX_Error* +pkix_CheckForGeneratedError(PKIX_StdVars * stdVars, + PKIX_ERRORCLASS errClass, + char * fnName, + PKIX_Boolean *errSetFlag, + void * plContext) +{ + PKIX_Error *genErr = NULL; + PKIX_UInt32 pos = 0; + PKIX_UInt32 strLen = 0; + + if (fnName) { + if (fnStackNameArr[testStartFnStackPosition] == NULL || + strcmp(fnStackNameArr[testStartFnStackPosition], TEST_START_FN) + ) { + /* return with out error if not with in boundary */ + return NULL; + } + if (!strcmp(fnName, TEST_START_FN)) { + *errSetFlag = PKIX_TRUE; + noErrorState = PKIX_FALSE; + errorGenerated = PKIX_FALSE; + } + } + + if (noErrorState || errorGenerated) return NULL; + + if (fnName && ( + !strcmp(fnName, "PKIX_PL_Object_DecRef") || + !strcmp(fnName, "PKIX_PL_Object_Unlock") || + !strcmp(fnName, "pkix_UnlockObject") || + !strcmp(fnName, "pkix_Throw") || + !strcmp(fnName, "pkix_trace_dump_cert") || + !strcmp(fnName, "PKIX_PL_Free"))) { + /* do not generate error for this functions */ + noErrorState = PKIX_TRUE; + *errSetFlag = PKIX_TRUE; + return NULL; + } + + if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) { + return NULL; + } + + PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue); + errorGenerated = PKIX_TRUE; + noErrorState = PKIX_TRUE; + genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR, + errClass, plContext); + while(fnStackNameArr[pos]) { + strLen += PORT_Strlen(fnStackNameArr[pos++]) + 1; + } + strLen += 1; /* end of line. */ + pos = 0; + errorFnStackString = PORT_ZAlloc(strLen); + while(fnStackNameArr[pos]) { + strcat(errorFnStackString, "/"); + strcat(errorFnStackString, fnStackNameArr[pos++]); + } + noErrorState = PKIX_FALSE; + + return genErr; +} +#endif /* PKIX_OBJECT_LEAK_TEST */ diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.h b/security/nss/lib/libpkix/pkix/util/pkix_tools.h new file mode 100644 index 0000000000..5a8ef2741e --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.h @@ -0,0 +1,1588 @@ +/* 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_tools.h + * + * Header for Utility Functions and Macros + * + */ + +#ifndef _PKIX_TOOLS_H +#define _PKIX_TOOLS_H + +#include "pkix.h" +#include <stddef.h> +#include <stdio.h> +#include "secport.h" +#include "prlong.h" + +/* private PKIX system headers */ +#include "pkix_basicconstraintschecker.h" +#include "pkix_buildresult.h" +#include "pkix_certchainchecker.h" +#include "pkix_certselector.h" +#include "pkix_comcertselparams.h" +#include "pkix_comcrlselparams.h" +#include "pkix_crlselector.h" +#include "pkix_error.h" +#include "pkix_expirationchecker.h" +#include "pkix_list.h" +#include "pkix_logger.h" +#include "pkix_namechainingchecker.h" +#include "pkix_nameconstraintschecker.h" +#include "pkix_policychecker.h" +#include "pkix_policynode.h" +#include "pkix_procparams.h" +#include "pkix_resourcelimits.h" +#include "pkix_revocationmethod.h" +#include "pkix_revocationchecker.h" +#include "pkix_crlchecker.h" +#include "pkix_ocspchecker.h" +#include "pkix_signaturechecker.h" +#include "pkix_store.h" +#include "pkix_targetcertchecker.h" +#include "pkix_validate.h" +#include "pkix_valresult.h" +#include "pkix_verifynode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pkixStdVarsStr { + const char *aMyFuncName; + PKIX_Error *aPkixErrorResult; + PKIX_Error *aPkixTempResult; + PKIX_Error *aPkixReturnResult; + PKIX_ERRORCODE aPkixErrorCode; + PKIX_Boolean aPkixErrorReceived; + PKIX_Boolean aPkixTempErrorReceived; + PKIX_ERRORCLASS aPkixErrorClass; + PKIX_UInt32 aPkixType; + PKIX_PL_Object *aLockedObject; + PKIX_List *aPkixErrorList; +} PKIX_StdVars; + +#ifdef PKIX_STDVARS_POINTER +#define myFuncName stdVars->aMyFuncName +#define pkixErrorResult stdVars->aPkixErrorResult +#define pkixTempResult stdVars->aPkixTempResult +#define pkixReturnResult stdVars->aPkixReturnResult +#define pkixErrorCode stdVars->aPkixErrorCode +#define pkixErrorReceived stdVars->aPkixErrorReceived +#define pkixTempErrorReceived stdVars->aPkixTempErrorReceived +#define pkixErrorClass stdVars->aPkixErrorClass +#define pkixType stdVars->aPkixType +#define lockedObject stdVars->aLockedObject +#define pkixErrorList stdVars->aPkixErrorList +#define stdVarsPtr stdVars +#else +#define myFuncName stdVars.aMyFuncName +#define pkixErrorResult stdVars.aPkixErrorResult +#define pkixTempResult stdVars.aPkixTempResult +#define pkixReturnResult stdVars.aPkixReturnResult +#define pkixErrorCode stdVars.aPkixErrorCode +#define pkixErrorReceived stdVars.aPkixErrorReceived +#define pkixTempErrorReceived stdVars.aPkixTempErrorReceived +#define pkixErrorClass stdVars.aPkixErrorClass +#define pkixType stdVars.aPkixType +#define lockedObject stdVars.aLockedObject +#define pkixErrorList stdVars.aPkixErrorList +#define stdVarsPtr &stdVars +#endif + +extern PKIX_Error * PKIX_DoReturn(PKIX_StdVars * stdVars, + PKIX_ERRORCLASS errClass, + PKIX_Boolean doLogger, + void * plContext); + +extern PKIX_Error * PKIX_DoThrow(PKIX_StdVars * stdVars, + PKIX_ERRORCLASS errClass, + PKIX_ERRORCODE errCode, + PKIX_ERRORCLASS overrideClass, + void * plContext); + +extern void PKIX_DoAddError(PKIX_StdVars * stdVars, + PKIX_Error * error, + void * plContext); + +#ifdef PKIX_OBJECT_LEAK_TEST +extern PKIX_Error * pkix_CheckForGeneratedError(PKIX_StdVars * stdVars, + PKIX_ERRORCLASS errClass, + char * fnName, + PKIX_Boolean *errorStateSet, + void * plContext); +#endif /* PKIX_OBJECT_LEAK_TEST */ + +extern const PKIX_StdVars zeroStdVars; + +extern PRLogModuleInfo *pkixLog; + +/* + * UTILITY MACROS + * Documentation for these common utility macros can be found in the + * Implementation Guidelines document (Section 4.3) + * + * In general, macros with multiple statements (or a single "if" statement) + * use the "do {<body>} while (0)" technique in order to convert the multiple + * statements into one statement, thus avoiding the dangling else problem. + * For macros which ALWAYS exit with a "return" or "goto", there is no + * need to use this technique (and it yields compiler warnings of "statement + * not reached"), so we just use "{<body>}" to group the statements together. + */ + +#if !defined (PKIX_OBJECT_LEAK_TEST) + +#define PKIX_STD_VARS(funcName) \ + static const char cMyFuncName[] = {funcName}; \ + PKIX_StdVars stdVars = zeroStdVars; \ + myFuncName = cMyFuncName + + +#else /* PKIX_OBJECT_LEAK_TEST */ + +extern char **fnStackNameArr; +extern PKIX_UInt32 *fnStackInvCountArr; +extern PKIX_UInt32 stackPosition; +extern PKIX_Boolean noErrorState; +extern PKIX_Boolean errorGenerated; +extern PKIX_Boolean runningLeakTest; +extern PLHashTable *fnInvTable; +extern PKIX_UInt32 testStartFnStackPosition; +extern char *errorFnStackString; + +extern PLHashNumber PR_CALLBACK pkix_ErrorGen_Hash (const void *key); + +#define PKIX_STD_VARS(funcName) \ + static const char cMyFuncName[] = {funcName}; \ + PKIX_StdVars stdVars = zeroStdVars; \ + PKIX_Boolean errorSetFlag = PKIX_FALSE; \ + myFuncName = cMyFuncName; \ + if (runningLeakTest) { \ + if (fnStackNameArr) { \ + fnStackInvCountArr[stackPosition] += 1; \ + stackPosition += 1; \ + fnStackInvCountArr[stackPosition] = 0; \ + fnStackNameArr[stackPosition] = (char*)myFuncName; \ + fnStackNameArr[stackPosition + 1] = NULL; \ + PR_LOG(pkixLog, 5, \ + ("%s%*s+> %s(%d) - %s\n", (errorGenerated ? "*" : " "), \ + stackPosition, " ", fnStackNameArr[stackPosition], \ + stackPosition, myFuncName)); \ + } \ + do { \ + pkixErrorResult = pkix_CheckForGeneratedError(&stdVars, PKIX_MEM_ERROR, \ + funcName, &errorSetFlag, \ + plContext); \ + if (pkixErrorResult) { \ + PR_LOG(pkixLog, 5, \ + ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \ + stackPosition, " ", fnStackNameArr[stackPosition], \ + stackPosition, myFuncName)); \ + fnStackNameArr[stackPosition--] = NULL; \ + if (errorSetFlag) { \ + noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \ + } \ + return pkixErrorResult; \ + } \ + } while (0); \ + } +#endif /* PKIX_OBJECT_LEAK_TEST */ + +#ifdef DEBUG +#define _PKIX_DEBUG_TRACE(cond, prefix, level) \ + do { \ + if (cond) { \ + pkix_Logger_Check(pkixLoggersDebugTrace, myFuncName, \ + prefix, pkixType, level, plContext); \ + } \ + } while (0) +#else +#define _PKIX_DEBUG_TRACE(cond, prefix, level) +#endif + +#define _PKIX_LOG_ERROR(code, level) \ + { \ + if (pkixLoggersErrors) { \ + pkix_Logger_CheckWithCode(pkixLoggersErrors, code, \ + NULL, pkixType, level, plContext); \ + } \ + } + +#define PKIX_ENTER(type, funcName) \ + PKIX_STD_VARS(funcName); \ + pkixType = PKIX_ ## type ## _ERROR; \ + PKIX_DEBUG_ENTER(type); \ + _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, ">>>", PKIX_LOGGER_LEVEL_TRACE); + +#define PKIX_ENTER_NO_LOGGER(type, funcName) \ + PKIX_STD_VARS(funcName); \ + pkixType = PKIX_ ## type ## _ERROR; \ + PKIX_DEBUG_ENTER(type); + +#define PKIX_DEBUG_ENTER(type) \ + PKIX_ ## type ## _DEBUG_ARG("( Entering %s).\n", myFuncName) + +#define PKIX_DEBUG_EXIT(type) \ + PKIX_ ## type ## _DEBUG_ARG("( Exiting %s).\n", myFuncName) + +#define PKIX_OBJECT_UNLOCK(obj) \ + do { \ + if (obj && lockedObject == (PKIX_PL_Object *)(obj)){ \ + pkixTempResult = \ + PKIX_PL_Object_Unlock \ + ((PKIX_PL_Object *)(obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + } \ + lockedObject = NULL; \ + } else { \ + PORT_Assert(lockedObject == NULL); \ + } \ + } while (0) + +#define PKIX_DECREF(obj) \ + do { \ + if (obj){ \ + pkixTempResult = PKIX_PL_Object_DecRef \ + ((PKIX_PL_Object *)(obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + } \ + obj = NULL; \ + } \ + } while (0) + +#define PKIX_THROW(type, descNum) \ + return PKIX_DoThrow(&stdVars, (PKIX_ ## type ## _ERROR), descNum, \ + pkixErrorClass, plContext); + +#ifdef PKIX_OBJECT_LEAK_TEST +#define PKIX_RETURN(type) \ + if (runningLeakTest && fnStackNameArr) { \ + PR_LOG(pkixLog, 5, \ + ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \ + stackPosition, " ", fnStackNameArr[stackPosition], \ + stackPosition, myFuncName)); \ + fnStackNameArr[stackPosition--] = NULL; \ + if (errorSetFlag) noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \ + } \ + return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext); +#else +#define PKIX_RETURN(type) \ + return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext); +#endif /* PKIX_OBJECT_LEAK_TEST */ + + +#if defined(DEBUG) && !defined(DEBUG_nb95248) +#define PKIX_RETURN_NO_LOGGER(type) \ + { \ + PKIX_OBJECT_UNLOCK(lockedObject); \ + if ((pkixErrorReceived) || (pkixErrorResult) || pkixErrorList) \ + PKIX_THROW(type, pkixErrorCode); \ + PKIX_DEBUG_EXIT(type); \ + return NULL; \ + } +#else +#define PKIX_RETURN_NO_LOGGER(type) \ + return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_FALSE, plContext); +#endif + +/* disable to disable ;-) */ +/* #define WANT_TRACE_CHECK_FAILURES */ + +#ifdef WANT_TRACE_CHECK_FAILURES +#define TRACE_CHECK_FAILURE(what, errorstring) \ + if (pkixLog) { \ + PR_LOG(pkixLog, PR_LOG_DEBUG, \ + ("====> [%s] failed: %s\n", #what, errorstring)); \ + } +#else +#define TRACE_CHECK_FAILURE(what, errorstring) +#endif + +#define PKIX_CHECK(func, descNum) \ + do { \ + pkixErrorResult = (func); \ + if (pkixErrorResult) { \ + TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \ + pkixErrorClass = pkixErrorResult->errClass; \ + pkixErrorCode = descNum; \ + goto cleanup; \ + } \ + } while (0) + +/* like PKIX_CHECK but without goto cleanup */ +#define PKIX_CHECK_NO_GOTO(func, descNum) \ + do { \ + pkixErrorResult = (func); \ + if (pkixErrorResult) { \ + TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \ + pkixErrorClass = pkixErrorResult->errClass; \ + pkixErrorCode = descNum; \ + } \ + } while (0) + +#define PKIX_CHECK_ONLY_FATAL(func, descNum) \ + do { \ + pkixTempErrorReceived = PKIX_FALSE; \ + pkixErrorResult = (func); \ + if (pkixErrorResult) { \ + TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \ + pkixTempErrorReceived = PKIX_TRUE; \ + pkixErrorClass = pkixErrorResult->errClass; \ + if (pkixErrorClass == PKIX_FATAL_ERROR) { \ + goto cleanup; \ + } \ + PKIX_DECREF(pkixErrorResult); \ + } \ + } while (0) + +#define PKIX_LOG_ERROR(descNum) \ + _PKIX_LOG_ERROR(descNum, PKIX_LOGGER_LEVEL_ERROR) + +#define PKIX_ERROR(descNum) \ + { \ + PKIX_LOG_ERROR(descNum) \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = descNum; \ + goto cleanup; \ + } + +#define PKIX_ERROR_ALLOC_ERROR() \ + { \ + PKIX_LOG_ERROR(PKIX_ALLOCERROR) \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorResult = PKIX_ALLOC_ERROR(); \ + goto cleanup; \ + } + +#define PKIX_ERROR_FATAL(descNum) \ + { \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = descNum; \ + pkixErrorClass = PKIX_FATAL_ERROR; \ + _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \ + goto cleanup; \ + } + +#define PKIX_CHECK_FATAL(func, descNum) \ + do { \ + pkixErrorResult = (func); \ + if (pkixErrorResult) { \ + TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = descNum; \ + pkixErrorClass = PKIX_FATAL_ERROR; \ + _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \ + goto fatal; \ + } \ + } while (0) + +#define PKIX_NULLCHECK_ONE(a) \ + do { \ + if ((a) == NULL){ \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = PKIX_NULLARGUMENT; \ + PKIX_RETURN(FATAL); \ + } \ + } while (0) + +#define PKIX_NULLCHECK_TWO(a, b) \ + do { \ + if (((a) == NULL) || ((b) == NULL)){ \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = PKIX_NULLARGUMENT; \ + PKIX_RETURN(FATAL); \ + } \ + } while (0) + +#define PKIX_NULLCHECK_THREE(a, b, c) \ + do { \ + if (((a) == NULL) || ((b) == NULL) || ((c) == NULL)){ \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = PKIX_NULLARGUMENT; \ + PKIX_RETURN(FATAL); \ + } \ + } while (0) + +#define PKIX_NULLCHECK_FOUR(a, b, c, d) \ + do { \ + if (((a) == NULL) || ((b) == NULL) || \ + ((c) == NULL) || ((d) == NULL)){ \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = PKIX_NULLARGUMENT; \ + PKIX_RETURN(FATAL); \ + } \ + } while (0) + +#define PKIX_OBJECT_LOCK(obj) \ + do { \ + if (obj) { \ + pkixTempResult = \ + PKIX_PL_Object_Lock((PKIX_PL_Object*)(obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + pkixErrorCode = PKIX_OBJECTLOCKFAILED; \ + goto cleanup; \ + } \ + lockedObject = (PKIX_PL_Object *)(obj); \ + } \ + } while (0) + +#define PKIX_ERROR_CREATE(type, descNum, error) \ + { \ + pkixTempResult = (PKIX_Error*)pkix_Throw \ + (PKIX_ ## type ## _ERROR, myFuncName, \ + descNum, PKIX_ ## type ## _ERROR, pkixErrorResult, \ + &error, plContext); \ + if (pkixTempResult) { \ + error = pkixTempResult; \ + pkixTempResult = NULL; \ + } \ + } + + +#define PKIX_ERROR_RECEIVED \ + (pkixErrorReceived || pkixErrorResult || pkixTempErrorReceived || \ + pkixErrorList) + +#define PKIX_INCREF(obj) \ + do { \ + if (obj){ \ + pkixTempResult = PKIX_PL_Object_IncRef \ + ((PKIX_PL_Object *)(obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + goto cleanup; \ + } \ + } \ + } while (0) + +#define PKIX_FREE(obj) \ + do { \ + if (obj) { \ + pkixTempResult = PKIX_PL_Free((obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + } \ + obj = NULL; \ + } \ + } while (0) + +#define PKIX_EXACTLY_ONE_NULL(a, b) (((a) && !(b)) || ((b) && !(a))) + +/* DIGIT MACROS */ + +#define PKIX_ISDIGIT(c) (((c) >= '0') && ((c) <= '9')) + +#define PKIX_ISXDIGIT(c) \ + (PKIX_ISDIGIT(c) || ( (((c)|0x20) >= 'a') && (((c)|0x20) <= 'f') )) + +#define PKIX_TOSTRING(a, b, c, d) \ + do { \ + int descNum; \ + if ((a) != NULL) { \ + pkixErrorResult = \ + PKIX_PL_Object_ToString((PKIX_PL_Object *)(a), (b), (c)); \ + descNum = (d); \ + } else { \ + pkixErrorResult = \ + PKIX_PL_String_Create(PKIX_ESCASCII, "(null)", 0, (b), (c)); \ + descNum = PKIX_STRINGCREATEFAILED; \ + } \ + PKIX_CHECK(pkixErrorResult, descNum); \ + } while (0) + +#define PKIX_EQUALS(a, b, c, d, e) \ + do { \ + if ((a) != NULL && (b) != NULL) { \ + PKIX_CHECK(PKIX_PL_Object_Equals\ + ((PKIX_PL_Object *)(a), \ + (PKIX_PL_Object*)(b), \ + (c), \ + (d)), \ + (e)); \ + } else if ((a) == NULL && (b) == NULL) { \ + *(c) = PKIX_TRUE; \ + } else { \ + *(c) = PKIX_FALSE; \ + } \ + } while (0) + +#define PKIX_HASHCODE(a, b, c, d) \ + do { \ + if ((a) != NULL) { \ + PKIX_CHECK(PKIX_PL_Object_Hashcode\ + ((PKIX_PL_Object *)(a), (b), (c)), (d)); \ + } else { \ + *(b) = 0; \ + } \ + } while (0) + +#define PKIX_DUPLICATE(a, b, c, d) \ + do { \ + if ((a) != NULL) { \ + PKIX_CHECK(PKIX_PL_Object_Duplicate\ + ((PKIX_PL_Object *)(a), \ + (PKIX_PL_Object **)(b), \ + (c)), \ + (d)); \ + } else { \ + *(b) = (a); \ + } \ + } while (0) + +/* + * DEBUG MACROS + * + * Each type has an associated debug flag, which can + * be set on the compiler line using "-D<debugflag>". For convenience, + * "-DPKIX_DEBUGALL" turns on debug for all the components. + * + * If a type's debug flag is defined, then its two associated macros + * are defined: PKIX_type_DEBUG(expr) and PKIX_type_DEBUG_ARG(expr, arg), + * which call PKIX_DEBUG(expr) and PKIX_DEBUG_ARG(expr, arg) respectively, + * which, in turn, enable standard and consistently formatted output. + * + * If a type's debug flag is not defined, the two associated macros + * are defined as a NO-OP. As such, any PKIX_type_DEBUG or PKIX_type_DEBUG_ARG + * macros for an undefined type will be stripped from the code during + * pre-processing, thereby reducing code size. + */ + +#ifdef PKIX_DEBUGALL +#define PKIX_REFCOUNTDEBUG 1 +#define PKIX_MEMDEBUG 1 +#define PKIX_MUTEXDEBUG 1 +#define PKIX_OBJECTDEBUG 1 +#define PKIX_STRINGDEBUG 1 +#define PKIX_OIDDEBUG 1 +#define PKIX_LISTDEBUG 1 +#define PKIX_ERRORDEBUG 1 +#define PKIX_BYTEARRAYDEBUG 1 +#define PKIX_RWLOCKDEBUG 1 +#define PKIX_BIGINTDEBUG 1 +#define PKIX_HASHTABLEDEBUG 1 +#define PKIX_X500NAMEDEBUG 1 +#define PKIX_GENERALNAMEDEBUG 1 +#define PKIX_PUBLICKEYDEBUG 1 +#define PKIX_CERTDEBUG 1 +#define PKIX_HTTPCLIENTDEBUG 1 +#define PKIX_DATEDEBUG 1 +#define PKIX_TRUSTANCHORDEBUG 1 +#define PKIX_PROCESSINGPARAMSDEBUG 1 +#define PKIX_VALIDATEPARAMSDEBUG 1 +#define PKIX_VALIDATERESULTDEBUG 1 +#define PKIX_VALIDATEDEBUG 1 +#define PKIX_CERTCHAINCHECKERDEBUG 1 +#define PKIX_REVOCATIONCHECKERDEBUG 1 +#define PKIX_CERTSELECTORDEBUG 1 +#define PKIX_COMCERTSELPARAMSDEBUG 1 +#define PKIX_TARGETCERTCHECKERSTATEDEBUG 1 +#define PKIX_INITIALIZEPARAMSDEBUG 1 +#define PKIX_CERTBASICCONSTRAINTSDEBUG 1 +#define PKIX_CERTNAMECONSTRAINTSDEBUG 1 +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG 1 +#define PKIX_SUBJALTNAMECHECKERSTATEDEBUG 1 + +#define PKIX_CERTPOLICYQUALIFIERDEBUG 1 +#define PKIX_CERTPOLICYINFODEBUG 1 +#define PKIX_CERTPOLICYNODEDEBUG 1 +#define PKIX_CERTPOLICYCHECKERSTATEDEBUG 1 +#define PKIX_LIFECYCLEDEBUG 1 +#define PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG 1 +#define PKIX_CRLDEBUG 1 +#define PKIX_CRLENTRYDEBUG 1 +#define PKIX_CRLSELECTORDEBUG 1 +#define PKIX_COMCRLSELPARAMSDEBUG 1 +#define PKIX_CERTSTOREDEBUG 1 +#define PKIX_COLLECTIONCERTSTORECONTEXTDEBUG 1 +#define PKIX_DEFAULTCRLCHECKERSTATEDEBUG 1 +#define PKIX_CERTPOLICYMAPDEBUG 1 +#define PKIX_BUILDDEBUG 1 +#define PKIX_BUILDRESULTDEBUG 1 +#define PKIX_FORWARDBUILDERSTATEDEBUG 1 +#define PKIX_SIGNATURECHECKERSTATEDEBUG 1 +#define PKIX_USERDEFINEDMODULESDEBUG 1 +#define PKIX_CONTEXTDEBUG 1 +#define PKIX_DEFAULTREVOCATIONCHECKERDEBUG 1 +#define PKIX_LDAPREQUESTDEBUG 1 +#define PKIX_LDAPRESPONSEDEBUG 1 +#define PKIX_LDAPCLIENTDEBUG 1 +#define PKIX_LDAPDEFAULTCLIENTDEBUG 1 +#define PKIX_SOCKETDEBUG 1 +#define PKIX_RESOURCELIMITSDEBUG 1 +#define PKIX_LOGGERDEBUG 1 +#define PKIX_MONITORLOCKDEBUG 1 +#define PKIX_INFOACCESSDEBUG 1 +#define PKIX_AIAMGRDEBUG 1 +#define PKIX_OCSPCHECKERDEBUG 1 +#define PKIX_OCSPREQUESTDEBUG 1 +#define PKIX_OCSPRESPONSEDEBUG 1 +#define PKIX_HTTPDEFAULTCLIENTDEBUG 1 +#define PKIX_HTTPCERTSTORECONTEXTDEBUG 1 +#define PKIX_VERIFYNODEDEBUG 1 +#endif + +/* + * XXX Both PKIX_DEBUG and PKIX_DEBUG_ARG currently use printf. + * This needs to be replaced with Loggers. + */ + +#ifdef DEBUG +#define PKIX_DEBUG(expr) \ + do { \ + _PKIX_DEBUG_TRACE(pkixLoggersErrors, expr, PKIX_LOGGER_LEVEL_DEBUG); \ + (void) fprintf(stderr, "(%s: ", myFuncName); \ + (void) fprintf(stderr, expr); \ + } while (0) +#else +#define PKIX_DEBUG(expr) +#endif + +/* Logging doesn't support DEBUG with ARG: cannot convert control and arg */ +#define PKIX_DEBUG_ARG(expr, arg) \ + do { \ + (void) printf("(%s: ", myFuncName); \ + (void) printf(expr, arg); \ + } while (0) + +#if PKIX_FATALDEBUG +#define PKIX_FATAL_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_FATAL_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_FATAL_DEBUG(expr) +#define PKIX_FATAL_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_REFCOUNTDEBUG +#define PKIX_REF_COUNT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_REF_COUNT_DEBUG(expr) +#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_MEMDEBUG +#define PKIX_MEM_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_MEM_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_MEM_DEBUG(expr) +#define PKIX_MEM_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_MUTEXDEBUG +#define PKIX_MUTEX_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_MUTEX_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_MUTEX_DEBUG(expr) +#define PKIX_MUTEX_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OBJECTDEBUG +#define PKIX_OBJECT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OBJECT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OBJECT_DEBUG(expr) +#define PKIX_OBJECT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_ERRORDEBUG +#define PKIX_ERROR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_ERROR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_ERROR_DEBUG(expr) +#define PKIX_ERROR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_STRINGDEBUG +#define PKIX_STRING_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_STRING_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_STRING_DEBUG(expr) +#define PKIX_STRING_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OIDDEBUG +#define PKIX_OID_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OID_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OID_DEBUG(expr) +#define PKIX_OID_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LISTDEBUG +#define PKIX_LIST_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LIST_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LIST_DEBUG(expr) +#define PKIX_LIST_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_RWLOCKDEBUG +#define PKIX_RWLOCK_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_RWLOCK_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_RWLOCK_DEBUG(expr) +#define PKIX_RWLOCK_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BYTEARRAYDEBUG +#define PKIX_BYTEARRAY_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BYTEARRAY_DEBUG(expr) +#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_HASHTABLEDEBUG +#define PKIX_HASHTABLE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_HASHTABLE_DEBUG(expr) +#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_X500NAMEDEBUG +#define PKIX_X500NAME_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_X500NAME_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_X500NAME_DEBUG(expr) +#define PKIX_X500NAME_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_GENERALNAMEDEBUG +#define PKIX_GENERALNAME_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_GENERALNAME_DEBUG(expr) +#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_PUBLICKEYDEBUG +#define PKIX_PUBLICKEY_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_PUBLICKEY_DEBUG(expr) +#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTDEBUG +#define PKIX_CERT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERT_DEBUG(expr) +#define PKIX_CERT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLDPDEBUG +#define PKIX_CRLDP_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRLDP_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRLDP_DEBUG(expr) +#define PKIX_CRLDP_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_HTTPCLIENTDEBUG +#define PKIX_HTTPCLIENT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_HTTPCLIENT_DEBUG(expr) +#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BIGINTDEBUG +#define PKIX_BIGINT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BIGINT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BIGINT_DEBUG(expr) +#define PKIX_BIGINT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_DATEDEBUG +#define PKIX_DATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_DATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_DATE_DEBUG(expr) +#define PKIX_DATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_TRUSTANCHORDEBUG +#define PKIX_TRUSTANCHOR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_TRUSTANCHOR_DEBUG(expr) +#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_PROCESSINGPARAMSDEBUG +#define PKIX_PROCESSINGPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_PROCESSINGPARAMS_DEBUG(expr) +#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_VALIDATEPARAMSDEBUG +#define PKIX_VALIDATEPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_VALIDATEPARAMS_DEBUG(expr) +#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_VALIDATERESULTDEBUG +#define PKIX_VALIDATERESULT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_VALIDATERESULT_DEBUG(expr) +#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_VALIDATEDEBUG +#define PKIX_VALIDATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_VALIDATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_VALIDATE_DEBUG(expr) +#define PKIX_VALIDATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BUILDDEBUG +#define PKIX_BUILD_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BUILD_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BUILD_DEBUG(expr) +#define PKIX_BUILD_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTCHAINCHECKERDEBUG +#define PKIX_CERTCHAINCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTCHAINCHECKER_DEBUG(expr) +#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_REVOCATIONCHECKERDEBUG +#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_REVOCATIONCHECKER_DEBUG(expr) +#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_REVOCATIONMETHODDEBUG +#define PKIX_REVOCATIONMETHOD_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_REVOCATIONMETHOD_DEBUG(expr) +#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTSELECTORDEBUG +#define PKIX_CERTSELECTOR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTSELECTOR_DEBUG(expr) +#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_COMCERTSELPARAMSDEBUG +#define PKIX_COMCERTSELPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_COMCERTSELPARAMS_DEBUG(expr) +#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_TARGETCERTCHECKERSTATEDEBUG +#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr) +#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_INITIALIZEPARAMSDEBUG +#define PKIX_INITIALIZEPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_INITIALIZEPARAMS_DEBUG(expr) +#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTBASICCONSTRAINTSDEBUG +#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr) +#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTNAMECONSTRAINTSDEBUG +#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr) +#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr) +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_SUBJALTNAMECHECKERSTATEDEBUG +#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr) +#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYQUALIFIERDEBUG +#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr) +#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYINFODEBUG +#define PKIX_CERTPOLICYINFO_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYINFO_DEBUG(expr) +#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYNODEDEBUG +#define PKIX_CERTPOLICYNODE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYNODE_DEBUG(expr) +#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG +#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr) +#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LIFECYCLEDEBUG +#define PKIX_LIFECYCLE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LIFECYCLE_DEBUG(expr) +#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLDEBUG +#define PKIX_CRL_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRL_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRL_DEBUG(expr) +#define PKIX_CRL_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLENTRYDEBUG +#define PKIX_CRLENTRY_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRLENTRY_DEBUG(expr) +#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLSELECTORDEBUG +#define PKIX_CRLSELECTOR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRLSELECTOR_DEBUG(expr) +#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_COMCRLSELPARAMSDEBUG +#define PKIX_COMCRLSELPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_COMCRLSELPARAMS_DEBUG(expr) +#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTSTOREDEBUG +#define PKIX_CERTSTORE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTSTORE_DEBUG(expr) +#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_COLLECTIONCERTSTORECONTEXTDEBUG +#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr) +#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLCHECKERDEBUG +#define PKIX_CRLCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRLCHECKER_DEBUG(expr) +#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYMAPDEBUG +#define PKIX_CERTPOLICYMAP_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYMAP_DEBUG(expr) +#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BUILDRESULTDEBUG +#define PKIX_BUILDRESULT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BUILDRESULT_DEBUG(expr) +#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_FORWARDBUILDERSTATEDEBUG +#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr) +#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_SIGNATURECHECKERSTATEDEBUG +#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr) +#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_USERDEFINEDMODULESDEBUG +#define PKIX_USERDEFINEDMODULES_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_USERDEFINEDMODULES_DEBUG(expr) +#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CONTEXTDEBUG +#define PKIX_CONTEXT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CONTEXT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CONTEXT_DEBUG(expr) +#define PKIX_CONTEXT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_REVOCATIONCHECKERDEBUG +#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_REVOCATIONCHECKER_DEBUG(expr) +#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LDAPREQUESTDEBUG +#define PKIX_LDAPREQUEST_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LDAPREQUEST_DEBUG(expr) +#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LDAPRESPONSEDEBUG +#define PKIX_LDAPRESPONSE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LDAPRESPONSE_DEBUG(expr) +#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LDAPCLIENTDEBUG +#define PKIX_LDAPCLIENT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LDAPCLIENT_DEBUG(expr) +#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LDAPDEFAULTCLIENTDEBUG +#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr) +#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_SOCKETDEBUG +#define PKIX_SOCKET_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_SOCKET_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_SOCKET_DEBUG(expr) +#define PKIX_SOCKET_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_RESOURCELIMITSDEBUG +#define PKIX_RESOURCELIMITS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_RESOURCELIMITS_DEBUG(expr) +#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LOGGERDEBUG +#define PKIX_LOGGER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LOGGER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LOGGER_DEBUG(expr) +#define PKIX_LOGGER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_MONITORLOCKDEBUG +#define PKIX_MONITORLOCK_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_MONITORLOCK_DEBUG(expr) +#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_INFOACCESSDEBUG +#define PKIX_INFOACCESS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_INFOACCESS_DEBUG(expr) +#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_AIAMGRDEBUG +#define PKIX_AIAMGR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_AIAMGR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_AIAMGR_DEBUG(expr) +#define PKIX_AIAMGR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OCSPCHECKERDEBUG +#define PKIX_OCSPCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OCSPCHECKER_DEBUG(expr) +#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OCSPCERTIDDEBUG +#define PKIX_OCSPCERTID_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OCSPCERTID_DEBUG(expr) +#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OCSPREQUESTDEBUG +#define PKIX_OCSPREQUEST_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OCSPREQUEST_DEBUG(expr) +#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OCSPRESPONSEDEBUG +#define PKIX_OCSPRESPONSE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OCSPRESPONSE_DEBUG(expr) +#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_HTTPDEFAULTCLIENTDEBUG +#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr) +#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_HTTPCERTSTORECONTEXTDEBUG +#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr) +#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_VERIFYNODEDEBUG +#define PKIX_VERIFYNODE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_VERIFYNODE_DEBUG(expr) +#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_EKUCHECKER +#define PKIX_EKUCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_EKUCHECKER_DEBUG(expr) +#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTVFYPKIXDEBUG +#define PKIX_CERTVFYPKIX_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTVFYPKIX_DEBUG(expr) +#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg) +#endif + +/* + * All object types register themselves with the system using a + * pkix_ClassTable_Entry, which consists of a set of functions for that + * type and an ASCII string (char *) which is used by the default + * ToStringCallback (if necessary). System types register themselves directly + * when their respective PKIX_"type"_RegisterSelf functions are called. + * User-defined types can be registered using PKIX_PL_Object_RegisterType. + * (see comments in pkix_pl_system.h) + */ + +typedef struct pkix_ClassTable_EntryStruct pkix_ClassTable_Entry; +struct pkix_ClassTable_EntryStruct { + char *description; + PKIX_UInt32 objCounter; + PKIX_UInt32 typeObjectSize; + PKIX_PL_DestructorCallback destructor; + PKIX_PL_EqualsCallback equalsFunction; + PKIX_PL_HashcodeCallback hashcodeFunction; + PKIX_PL_ToStringCallback toStringFunction; + PKIX_PL_ComparatorCallback comparator; + PKIX_PL_DuplicateCallback duplicateFunction; +}; + +/* + * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a + * descriptive name for an error code. This is used by the default + * PKIX_PL_Error_ToString function. + */ +extern const char *PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES]; + +#define MAX_STACK_DEPTH 1000 + +extern PRLogModuleInfo *pkixLog; + +#define PKIX_MAGIC_HEADER PR_UINT64(0xFEEDC0FFEEFACADE) +#define PKIX_MAGIC_HEADER_DESTROYED PR_UINT64(0xBAADF00DDEADBEEF) + +/* see source file for function documentation */ + +PKIX_Error * +pkix_IsCertSelfIssued( + PKIX_PL_Cert *cert, + PKIX_Boolean *pSelfIssued, + void *plContext); + +PKIX_Error * +pkix_Throw( + PKIX_ERRORCLASS errClass, + const char *funcName, + PKIX_ERRORCODE errorTextCode, + PKIX_ERRORCLASS overrideClass, + PKIX_Error *cause, + PKIX_Error **pError, + void *plContext); + +PKIX_Error * +pkix_CheckTypes( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_UInt32 type, + void *plContext); + +PKIX_Error * +pkix_CheckType( + PKIX_PL_Object *object, + PKIX_UInt32 type, + void *plContext); + +PKIX_Error * +pkix_hash( + const unsigned char *bytes, + PKIX_UInt32 length, + PKIX_UInt32 *hash, + void *plContext); + +PKIX_Error * +pkix_duplicateImmutable( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext); + +PKIX_UInt32 +pkix_countArray(void **array); + +PKIX_UInt32 +pkix_hex2i(char c); + +char +pkix_i2hex(char c); + +PKIX_Boolean +pkix_isPlaintext(unsigned char c, PKIX_Boolean debug); + +PKIX_Error * +pkix_CacheCertChain_Lookup( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + PKIX_PL_Date *testDate, + PKIX_Boolean *pFound, + PKIX_BuildResult **pBuildResult, + void *plContext); + +PKIX_Error * +pkix_CacheCertChain_Remove( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + void *plContext); + +PKIX_Error * +pkix_CacheCertChain_Add( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + PKIX_PL_Date *validityDate, + PKIX_BuildResult *buildResult, + void *plContext); + +PKIX_Error * +pkix_CacheCert_Lookup( + PKIX_CertStore *store, + PKIX_ComCertSelParams *certSelParams, + PKIX_PL_Date *testDate, + PKIX_Boolean *pFound, + PKIX_List** pCerts, + void *plContext); + +PKIX_Error * +pkix_CacheCert_Add( + PKIX_CertStore *store, + PKIX_ComCertSelParams *certSelParams, + PKIX_List* certs, + void *plContext); + +PKIX_Error * +pkix_CacheCrlEntry_Lookup( + PKIX_CertStore *store, + PKIX_PL_X500Name *certIssuer, + PKIX_PL_BigInt *certSerialNumber, + PKIX_Boolean *pFound, + PKIX_List** pCrlEntryList, + void *plContext); + +PKIX_Error * +pkix_CacheCrlEntry_Add( + PKIX_CertStore *store, + PKIX_PL_X500Name *certIssuer, + PKIX_PL_BigInt *certSerialNumber, + PKIX_List* crlEntryList, + void *plContext); + +#ifdef PR_LOGGING +void +pkix_trace_dump_cert( + const char *info, + PKIX_PL_Cert *cert, + void *plContext); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_TOOLS_H */ diff --git a/security/nss/lib/libpkix/pkix/util/util.gyp b/security/nss/lib/libpkix/pkix/util/util.gyp new file mode 100644 index 0000000000..078852f52b --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/util.gyp @@ -0,0 +1,27 @@ +# 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': 'pkixutil', + 'type': 'static_library', + 'sources': [ + 'pkix_error.c', + 'pkix_errpaths.c', + 'pkix_list.c', + 'pkix_logger.c', + 'pkix_tools.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file |